Doc fixes.
[emacs.git] / src / xterm.c
blobb60912dd9dbc2bfda0bee54e801fb13be3700f8e
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
25 #include <config.h>
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
31 #include <stdio.h>
33 #ifdef HAVE_X_WINDOWS
35 #include "lisp.h"
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
47 #ifndef USG
48 /* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
50 #ifndef makedev
51 #include <sys/types.h>
52 #endif /* makedev */
53 #endif /* USG */
55 #ifdef BSD_SYSTEM
56 #include <sys/ioctl.h>
57 #endif /* ! defined (BSD_SYSTEM) */
59 #include "systty.h"
60 #include "systime.h"
62 #ifndef INCLUDED_FCNTL
63 #include <fcntl.h>
64 #endif
65 #include <ctype.h>
66 #include <errno.h>
67 #include <setjmp.h>
68 #include <sys/stat.h>
69 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70 /* #include <sys/param.h> */
72 #include "charset.h"
73 #include "ccl.h"
74 #include "frame.h"
75 #include "fontset.h"
76 #include "dispextern.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #if 0
81 #include "sink.h"
82 #include "sinkmask.h"
83 #endif /* ! 0 */
84 #include "gnu.h"
85 #include "disptab.h"
86 #include "buffer.h"
87 #include "window.h"
88 #include "keyboard.h"
89 #include "intervals.h"
90 #include "process.h"
91 #include "atimer.h"
93 #ifdef USE_X_TOOLKIT
94 #include <X11/Shell.h>
95 #endif
97 #include <sys/types.h>
98 #ifdef HAVE_SYS_TIME_H
99 #include <sys/time.h>
100 #endif
101 #ifdef HAVE_UNISTD_H
102 #include <unistd.h>
103 #endif
105 #ifdef USE_X_TOOLKIT
107 extern void free_frame_menubar ();
108 extern FRAME_PTR x_menubar_window_to_frame ();
110 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
111 #define HACK_EDITRES
112 extern void _XEditResCheckMessages ();
113 #endif /* not NO_EDITRES */
115 /* Include toolkit specific headers for the scroll bar widget. */
117 #ifdef USE_TOOLKIT_SCROLL_BARS
118 #if defined USE_MOTIF
119 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
120 #include <Xm/ScrollBar.h>
121 #include <Xm/ScrollBarP.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
124 #ifdef HAVE_XAW3D
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
133 #ifndef XtNpickTop
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
139 #endif /* USE_X_TOOLKIT */
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
144 #endif
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
153 #ifdef SOLARIS2
154 /* memmove will be defined as a macro in Xfuncs.h unless
155 <string.h> is included beforehand. The declaration for memmove in
156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
157 #include <string.h>
158 #endif
160 #ifndef min
161 #define min(a,b) ((a) < (b) ? (a) : (b))
162 #endif
163 #ifndef max
164 #define max(a,b) ((a) > (b) ? (a) : (b))
165 #endif
167 #define abs(x) ((x) < 0 ? -(x) : (x))
169 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
172 /* Bitmaps for truncated lines. */
174 enum bitmap_type
176 NO_BITMAP,
177 LEFT_TRUNCATION_BITMAP,
178 RIGHT_TRUNCATION_BITMAP,
179 OVERLAY_ARROW_BITMAP,
180 CONTINUED_LINE_BITMAP,
181 CONTINUATION_LINE_BITMAP,
182 ZV_LINE_BITMAP
185 /* Bitmap drawn to indicate lines not displaying text if
186 `indicate-empty-lines' is non-nil. */
188 #define zv_width 8
189 #define zv_height 8
190 static unsigned char zv_bits[] = {
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
193 /* An arrow like this: `<-'. */
195 #define left_width 8
196 #define left_height 8
197 static unsigned char left_bits[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
200 /* Right truncation arrow bitmap `->'. */
202 #define right_width 8
203 #define right_height 8
204 static unsigned char right_bits[] = {
205 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
207 /* Marker for continued lines. */
209 #define continued_width 8
210 #define continued_height 8
211 static unsigned char continued_bits[] = {
212 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
214 /* Marker for continuation lines. */
216 #define continuation_width 8
217 #define continuation_height 8
218 static unsigned char continuation_bits[] = {
219 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
221 /* Overlay arrow bitmap. */
223 #if 0
224 /* A bomb. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
229 #else
230 /* A triangular arrow. */
231 #define ov_width 8
232 #define ov_height 8
233 static unsigned char ov_bits[] = {
234 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
236 #endif
238 extern Lisp_Object Qhelp_echo;
241 /* Non-zero means Emacs uses toolkit scroll bars. */
243 int x_toolkit_scroll_bars_p;
245 /* If a string, XTread_socket generates an event to display that string.
246 (The display is done in read_char.) */
248 static Lisp_Object help_echo;
250 /* Temporary variable for XTread_socket. */
252 static Lisp_Object previous_help_echo;
254 /* Non-zero means that a HELP_EVENT has been generated since Emacs
255 start. */
257 static int any_help_event_p;
259 /* Non-zero means draw block and hollow cursor as wide as the glyph
260 under it. For example, if a block cursor is over a tab, it will be
261 drawn as wide as that tab on the display. */
263 int x_stretch_cursor_p;
265 /* This is a chain of structures for all the X displays currently in
266 use. */
268 struct x_display_info *x_display_list;
270 /* This is a list of cons cells, each of the form (NAME
271 . FONT-LIST-CACHE), one for each element of x_display_list and in
272 the same order. NAME is the name of the frame. FONT-LIST-CACHE
273 records previous values returned by x-list-fonts. */
275 Lisp_Object x_display_name_list;
277 /* Frame being updated by update_frame. This is declared in term.c.
278 This is set by update_begin and looked at by all the XT functions.
279 It is zero while not inside an update. In that case, the XT
280 functions assume that `selected_frame' is the frame to apply to. */
282 extern struct frame *updating_frame;
284 extern int waiting_for_input;
286 /* This is a frame waiting to be auto-raised, within XTread_socket. */
288 struct frame *pending_autoraise_frame;
290 #ifdef USE_X_TOOLKIT
291 /* The application context for Xt use. */
292 XtAppContext Xt_app_con;
293 static String Xt_default_resources[] = {0};
294 #endif /* USE_X_TOOLKIT */
296 /* Nominal cursor position -- where to draw output.
297 HPOS and VPOS are window relative glyph matrix coordinates.
298 X and Y are window relative pixel coordinates. */
300 struct cursor_pos output_cursor;
302 /* Non-zero means user is interacting with a toolkit scroll bar. */
304 static int toolkit_scroll_bar_interaction;
306 /* Mouse movement.
308 Formerly, we used PointerMotionHintMask (in standard_event_mask)
309 so that we would have to call XQueryPointer after each MotionNotify
310 event to ask for another such event. However, this made mouse tracking
311 slow, and there was a bug that made it eventually stop.
313 Simply asking for MotionNotify all the time seems to work better.
315 In order to avoid asking for motion events and then throwing most
316 of them away or busy-polling the server for mouse positions, we ask
317 the server for pointer motion hints. This means that we get only
318 one event per group of mouse movements. "Groups" are delimited by
319 other kinds of events (focus changes and button clicks, for
320 example), or by XQueryPointer calls; when one of these happens, we
321 get another MotionNotify event the next time the mouse moves. This
322 is at least as efficient as getting motion events when mouse
323 tracking is on, and I suspect only negligibly worse when tracking
324 is off. */
326 /* Where the mouse was last time we reported a mouse event. */
328 FRAME_PTR last_mouse_frame;
329 static XRectangle last_mouse_glyph;
330 static Lisp_Object last_mouse_press_frame;
332 /* The scroll bar in which the last X motion event occurred.
334 If the last X motion event occurred in a scroll bar, we set this so
335 XTmouse_position can know whether to report a scroll bar motion or
336 an ordinary motion.
338 If the last X motion event didn't occur in a scroll bar, we set
339 this to Qnil, to tell XTmouse_position to return an ordinary motion
340 event. */
342 static Lisp_Object last_mouse_scroll_bar;
344 /* This is a hack. We would really prefer that XTmouse_position would
345 return the time associated with the position it returns, but there
346 doesn't seem to be any way to wrest the time-stamp from the server
347 along with the position query. So, we just keep track of the time
348 of the last movement we received, and return that in hopes that
349 it's somewhat accurate. */
351 static Time last_mouse_movement_time;
353 /* Incremented by XTread_socket whenever it really tries to read
354 events. */
356 #ifdef __STDC__
357 static int volatile input_signal_count;
358 #else
359 static int input_signal_count;
360 #endif
362 /* Used locally within XTread_socket. */
364 static int x_noop_count;
366 /* Initial values of argv and argc. */
368 extern char **initial_argv;
369 extern int initial_argc;
371 extern Lisp_Object Vcommand_line_args, Vsystem_name;
373 /* Tells if a window manager is present or not. */
375 extern Lisp_Object Vx_no_window_manager;
377 extern Lisp_Object Qface, Qmouse_face;
379 extern int errno;
381 /* A mask of extra modifier bits to put into every keyboard char. */
383 extern int extra_keyboard_modifiers;
385 static Lisp_Object Qvendor_specific_keysyms;
387 extern XrmDatabase x_load_resources ();
388 extern Lisp_Object x_icon_type ();
391 /* Enumeration for overriding/changing the face to use for drawing
392 glyphs in x_draw_glyphs. */
394 enum draw_glyphs_face
396 DRAW_NORMAL_TEXT,
397 DRAW_INVERSE_VIDEO,
398 DRAW_CURSOR,
399 DRAW_MOUSE_FACE,
400 DRAW_IMAGE_RAISED,
401 DRAW_IMAGE_SUNKEN
404 static void x_update_window_end P_ ((struct window *, int));
405 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
406 void x_delete_display P_ ((struct x_display_info *));
407 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
408 unsigned));
409 static int fast_find_position P_ ((struct window *, int, int *, int *,
410 int *, int *));
411 static void set_output_cursor P_ ((struct cursor_pos *));
412 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
413 int *, int *, int *));
414 static void note_mode_line_highlight P_ ((struct window *, int, int));
415 static void x_check_font P_ ((struct frame *, XFontStruct *));
416 static void note_mouse_highlight P_ ((struct frame *, int, int));
417 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
418 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
419 static void show_mouse_face P_ ((struct x_display_info *,
420 enum draw_glyphs_face));
421 static int x_io_error_quitter P_ ((Display *));
422 int x_catch_errors P_ ((Display *));
423 void x_uncatch_errors P_ ((Display *, int));
424 void x_lower_frame P_ ((struct frame *));
425 void x_scroll_bar_clear P_ ((struct frame *));
426 int x_had_errors_p P_ ((Display *));
427 void x_wm_set_size_hint P_ ((struct frame *, long, int));
428 void x_raise_frame P_ ((struct frame *));
429 void x_set_window_size P_ ((struct frame *, int, int, int));
430 void x_wm_set_window_state P_ ((struct frame *, int));
431 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
432 void x_initialize P_ ((void));
433 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
434 static int x_compute_min_glyph_bounds P_ ((struct frame *));
435 static void x_draw_phys_cursor_glyph P_ ((struct window *,
436 struct glyph_row *,
437 enum draw_glyphs_face));
438 static void x_update_end P_ ((struct frame *));
439 static void XTframe_up_to_date P_ ((struct frame *));
440 static void XTreassert_line_highlight P_ ((int, int));
441 static void x_change_line_highlight P_ ((int, int, int, int));
442 static void XTset_terminal_modes P_ ((void));
443 static void XTreset_terminal_modes P_ ((void));
444 static void XTcursor_to P_ ((int, int, int, int));
445 static void x_write_glyphs P_ ((struct glyph *, int));
446 static void x_clear_end_of_line P_ ((int));
447 static void x_clear_frame P_ ((void));
448 static void x_clear_cursor P_ ((struct window *));
449 static void frame_highlight P_ ((struct frame *));
450 static void frame_unhighlight P_ ((struct frame *));
451 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
452 static void XTframe_rehighlight P_ ((struct frame *));
453 static void x_frame_rehighlight P_ ((struct x_display_info *));
454 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
455 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
456 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
457 XRectangle *));
458 static void expose_frame P_ ((struct frame *, int, int, int, int));
459 static void expose_window_tree P_ ((struct window *, XRectangle *));
460 static void expose_window P_ ((struct window *, XRectangle *));
461 static void expose_area P_ ((struct window *, struct glyph_row *,
462 XRectangle *, enum glyph_row_area));
463 static void expose_line P_ ((struct window *, struct glyph_row *,
464 XRectangle *));
465 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
466 static void x_update_window_cursor P_ ((struct window *, int));
467 static void x_erase_phys_cursor P_ ((struct window *));
468 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
469 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
470 enum bitmap_type));
472 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
473 GC, int));
474 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
475 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
476 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
477 static void x_flush P_ ((struct frame *f));
480 /* Flush display of frame F, or of all frames if F is null. */
482 static void
483 x_flush (f)
484 struct frame *f;
486 BLOCK_INPUT;
487 if (f == NULL)
489 Lisp_Object rest, frame;
490 FOR_EACH_FRAME (rest, frame)
491 x_flush (XFRAME (frame));
493 else if (FRAME_X_P (f))
494 XFlush (FRAME_X_DISPLAY (f));
495 UNBLOCK_INPUT;
499 /* Remove calls to XFlush by defining XFlush to an empty replacement.
500 Calls to XFlush should be unnecessary because the X output buffer
501 is flushed automatically as needed by calls to XPending,
502 XNextEvent, or XWindowEvent according to the XFlush man page.
503 XTread_socket calls XPending. Removing XFlush improves
504 performance. */
506 #define XFlush(DISPLAY) (void) 0
509 /***********************************************************************
510 Debugging
511 ***********************************************************************/
513 #if 0
515 /* This is a function useful for recording debugging information about
516 the sequence of occurrences in this file. */
518 struct record
520 char *locus;
521 int type;
524 struct record event_record[100];
526 int event_record_index;
528 record_event (locus, type)
529 char *locus;
530 int type;
532 if (event_record_index == sizeof (event_record) / sizeof (struct record))
533 event_record_index = 0;
535 event_record[event_record_index].locus = locus;
536 event_record[event_record_index].type = type;
537 event_record_index++;
540 #endif /* 0 */
544 /* Return the struct x_display_info corresponding to DPY. */
546 struct x_display_info *
547 x_display_info_for_display (dpy)
548 Display *dpy;
550 struct x_display_info *dpyinfo;
552 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
553 if (dpyinfo->display == dpy)
554 return dpyinfo;
556 return 0;
561 /***********************************************************************
562 Starting and ending an update
563 ***********************************************************************/
565 /* Start an update of frame F. This function is installed as a hook
566 for update_begin, i.e. it is called when update_begin is called.
567 This function is called prior to calls to x_update_window_begin for
568 each window being updated. Currently, there is nothing to do here
569 because all interesting stuff is done on a window basis. */
571 static void
572 x_update_begin (f)
573 struct frame *f;
575 /* Nothing to do. */
579 /* Start update of window W. Set the global variable updated_window
580 to the window being updated and set output_cursor to the cursor
581 position of W. */
583 static void
584 x_update_window_begin (w)
585 struct window *w;
587 struct frame *f = XFRAME (WINDOW_FRAME (w));
588 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
590 updated_window = w;
591 set_output_cursor (&w->cursor);
593 BLOCK_INPUT;
595 if (f == display_info->mouse_face_mouse_frame)
597 /* Don't do highlighting for mouse motion during the update. */
598 display_info->mouse_face_defer = 1;
600 /* If F needs to be redrawn, simply forget about any prior mouse
601 highlighting. */
602 if (FRAME_GARBAGED_P (f))
603 display_info->mouse_face_window = Qnil;
605 /* Can we tell that this update does not affect the window
606 where the mouse highlight is? If so, no need to turn off.
607 Likewise, don't do anything if the frame is garbaged;
608 in that case, the frame's current matrix that we would use
609 is all wrong, and we will redisplay that line anyway. */
610 if (!NILP (display_info->mouse_face_window)
611 && w == XWINDOW (display_info->mouse_face_window))
613 int i;
615 for (i = 0; i < w->desired_matrix->nrows; ++i)
616 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
617 break;
619 if (i < w->desired_matrix->nrows)
620 clear_mouse_face (display_info);
624 UNBLOCK_INPUT;
628 /* Draw a vertical window border to the right of window W if W doesn't
629 have vertical scroll bars. */
631 static void
632 x_draw_vertical_border (w)
633 struct window *w;
635 struct frame *f = XFRAME (WINDOW_FRAME (w));
637 /* Redraw borders between horizontally adjacent windows. Don't
638 do it for frames with vertical scroll bars because either the
639 right scroll bar of a window, or the left scroll bar of its
640 neighbor will suffice as a border. */
641 if (!WINDOW_RIGHTMOST_P (w)
642 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
644 int x0, x1, y0, y1;
646 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
647 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
648 y1 -= 1;
650 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
651 f->output_data.x->normal_gc, x1, y0, x1, y1);
656 /* End update of window W (which is equal to updated_window). Draw
657 vertical borders between horizontally adjacent windows, and display
658 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
659 pseudo-window in case we don't have X toolkit support. Such
660 windows don't have a cursor, so don't display it here. */
662 static void
663 x_update_window_end (w, cursor_on_p)
664 struct window *w;
665 int cursor_on_p;
667 if (!w->pseudo_window_p)
669 BLOCK_INPUT;
670 if (cursor_on_p)
671 x_display_and_set_cursor (w, 1, output_cursor.hpos,
672 output_cursor.vpos,
673 output_cursor.x, output_cursor.y);
674 x_draw_vertical_border (w);
675 UNBLOCK_INPUT;
678 updated_window = NULL;
682 /* End update of frame F. This function is installed as a hook in
683 update_end. */
685 static void
686 x_update_end (f)
687 struct frame *f;
689 /* Mouse highlight may be displayed again. */
690 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
692 BLOCK_INPUT;
693 XFlush (FRAME_X_DISPLAY (f));
694 UNBLOCK_INPUT;
698 /* This function is called from various places in xdisp.c whenever a
699 complete update has been performed. The global variable
700 updated_window is not available here. */
702 static void
703 XTframe_up_to_date (f)
704 struct frame *f;
706 if (FRAME_X_P (f))
708 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
709 if (dpyinfo->mouse_face_deferred_gc
710 || f == dpyinfo->mouse_face_mouse_frame)
712 BLOCK_INPUT;
713 if (dpyinfo->mouse_face_mouse_frame)
714 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
715 dpyinfo->mouse_face_mouse_x,
716 dpyinfo->mouse_face_mouse_y);
717 dpyinfo->mouse_face_deferred_gc = 0;
718 UNBLOCK_INPUT;
724 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
725 arrow bitmaps, or clear the areas where they would be displayed
726 before DESIRED_ROW is made current. The window being updated is
727 found in updated_window. This function It is called from
728 update_window_line only if it is known that there are differences
729 between bitmaps to be drawn between current row and DESIRED_ROW. */
731 static void
732 x_after_update_window_line (desired_row)
733 struct glyph_row *desired_row;
735 struct window *w = updated_window;
737 xassert (w);
739 if (!desired_row->mode_line_p && !w->pseudo_window_p)
741 BLOCK_INPUT;
742 x_draw_row_bitmaps (w, desired_row);
744 /* When a window has disappeared, make sure that no rest of
745 full-width rows stays visible in the internal border. */
746 if (windows_or_buffers_changed)
748 struct frame *f = XFRAME (w->frame);
749 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
750 int height = desired_row->visible_height;
751 int x = (window_box_right (w, -1)
752 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
753 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
755 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
756 x, y, width, height, False);
759 UNBLOCK_INPUT;
764 /* Draw the bitmap WHICH in one of the areas to the left or right of
765 window W. ROW is the glyph row for which to display the bitmap; it
766 determines the vertical position at which the bitmap has to be
767 drawn. */
769 static void
770 x_draw_bitmap (w, row, which)
771 struct window *w;
772 struct glyph_row *row;
773 enum bitmap_type which;
775 struct frame *f = XFRAME (WINDOW_FRAME (w));
776 Display *display = FRAME_X_DISPLAY (f);
777 Window window = FRAME_X_WINDOW (f);
778 int x, y, wd, h, dy;
779 unsigned char *bits;
780 Pixmap pixmap;
781 GC gc = f->output_data.x->normal_gc;
782 struct face *face;
783 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
785 /* Must clip because of partially visible lines. */
786 x_clip_to_row (w, row, gc, 1);
788 switch (which)
790 case LEFT_TRUNCATION_BITMAP:
791 wd = left_width;
792 h = left_height;
793 bits = left_bits;
794 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
795 - wd
796 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
797 break;
799 case OVERLAY_ARROW_BITMAP:
800 wd = left_width;
801 h = left_height;
802 bits = ov_bits;
803 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
804 - wd
805 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
806 break;
808 case RIGHT_TRUNCATION_BITMAP:
809 wd = right_width;
810 h = right_height;
811 bits = right_bits;
812 x = window_box_right (w, -1);
813 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
814 break;
816 case CONTINUED_LINE_BITMAP:
817 wd = right_width;
818 h = right_height;
819 bits = continued_bits;
820 x = window_box_right (w, -1);
821 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
822 break;
824 case CONTINUATION_LINE_BITMAP:
825 wd = continuation_width;
826 h = continuation_height;
827 bits = continuation_bits;
828 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
829 - wd
830 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
831 break;
833 case ZV_LINE_BITMAP:
834 wd = zv_width;
835 h = zv_height;
836 bits = zv_bits;
837 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
838 - wd
839 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
840 break;
842 default:
843 abort ();
846 /* Convert to frame coordinates. Set dy to the offset in the row to
847 start drawing the bitmap. */
848 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
849 dy = (row->height - h) / 2;
851 /* Draw the bitmap. I believe these small pixmaps can be cached
852 by the server. */
853 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
854 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
855 face->foreground,
856 face->background, depth);
857 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
858 XFreePixmap (display, pixmap);
859 XSetClipMask (display, gc, None);
863 /* Draw flags bitmaps for glyph row ROW on window W. Call this
864 function with input blocked. */
866 static void
867 x_draw_row_bitmaps (w, row)
868 struct window *w;
869 struct glyph_row *row;
871 struct frame *f = XFRAME (w->frame);
872 enum bitmap_type bitmap;
873 struct face *face;
874 int header_line_height = -1;
876 xassert (interrupt_input_blocked);
878 /* If row is completely invisible, because of vscrolling, we
879 don't have to draw anything. */
880 if (row->visible_height <= 0)
881 return;
883 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
884 PREPARE_FACE_FOR_DISPLAY (f, face);
886 /* Decide which bitmap to draw at the left side. */
887 if (row->overlay_arrow_p)
888 bitmap = OVERLAY_ARROW_BITMAP;
889 else if (row->truncated_on_left_p)
890 bitmap = LEFT_TRUNCATION_BITMAP;
891 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
892 bitmap = CONTINUATION_LINE_BITMAP;
893 else if (row->indicate_empty_line_p)
894 bitmap = ZV_LINE_BITMAP;
895 else
896 bitmap = NO_BITMAP;
898 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
899 the flags area. */
900 if (bitmap == NO_BITMAP
901 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
902 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
904 /* If W has a vertical border to its left, don't draw over it. */
905 int border = ((XFASTINT (w->left) > 0
906 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
907 ? 1 : 0);
908 int left = window_box_left (w, -1);
910 if (header_line_height < 0)
911 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
913 /* In case the same realized face is used for bitmap areas and
914 for something displayed in the text (e.g. face `region' on
915 mono-displays, the fill style may have been changed to
916 FillSolid in x_draw_glyph_string_background. */
917 if (face->stipple)
918 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
919 else
920 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
922 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
923 face->gc,
924 (left
925 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
926 + border),
927 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
928 row->y)),
929 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
930 row->visible_height);
931 if (!face->stipple)
932 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
935 /* Draw the left bitmap. */
936 if (bitmap != NO_BITMAP)
937 x_draw_bitmap (w, row, bitmap);
939 /* Decide which bitmap to draw at the right side. */
940 if (row->truncated_on_right_p)
941 bitmap = RIGHT_TRUNCATION_BITMAP;
942 else if (row->continued_p)
943 bitmap = CONTINUED_LINE_BITMAP;
944 else
945 bitmap = NO_BITMAP;
947 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
948 the flags area. */
949 if (bitmap == NO_BITMAP
950 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
951 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
953 int right = window_box_right (w, -1);
955 if (header_line_height < 0)
956 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
958 /* In case the same realized face is used for bitmap areas and
959 for something displayed in the text (e.g. face `region' on
960 mono-displays, the fill style may have been changed to
961 FillSolid in x_draw_glyph_string_background. */
962 if (face->stipple)
963 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
964 else
965 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
966 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
967 face->gc,
968 right,
969 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
970 row->y)),
971 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
972 row->visible_height);
973 if (!face->stipple)
974 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
977 /* Draw the right bitmap. */
978 if (bitmap != NO_BITMAP)
979 x_draw_bitmap (w, row, bitmap);
983 /***********************************************************************
984 Line Highlighting
985 ***********************************************************************/
987 /* External interface to control of standout mode. Not used for X
988 frames. Aborts when called. */
990 static void
991 XTreassert_line_highlight (new, vpos)
992 int new, vpos;
994 abort ();
998 /* Call this when about to modify line at position VPOS and change
999 whether it is highlighted. Not used for X frames. Aborts when
1000 called. */
1002 static void
1003 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1004 int new_highlight, vpos, y, first_unused_hpos;
1006 abort ();
1010 /* This is called when starting Emacs and when restarting after
1011 suspend. When starting Emacs, no X window is mapped. And nothing
1012 must be done to Emacs's own window if it is suspended (though that
1013 rarely happens). */
1015 static void
1016 XTset_terminal_modes ()
1020 /* This is called when exiting or suspending Emacs. Exiting will make
1021 the X-windows go away, and suspending requires no action. */
1023 static void
1024 XTreset_terminal_modes ()
1030 /***********************************************************************
1031 Output Cursor
1032 ***********************************************************************/
1034 /* Set the global variable output_cursor to CURSOR. All cursor
1035 positions are relative to updated_window. */
1037 static void
1038 set_output_cursor (cursor)
1039 struct cursor_pos *cursor;
1041 output_cursor.hpos = cursor->hpos;
1042 output_cursor.vpos = cursor->vpos;
1043 output_cursor.x = cursor->x;
1044 output_cursor.y = cursor->y;
1048 /* Set a nominal cursor position.
1050 HPOS and VPOS are column/row positions in a window glyph matrix. X
1051 and Y are window text area relative pixel positions.
1053 If this is done during an update, updated_window will contain the
1054 window that is being updated and the position is the future output
1055 cursor position for that window. If updated_window is null, use
1056 selected_window and display the cursor at the given position. */
1058 static void
1059 XTcursor_to (vpos, hpos, y, x)
1060 int vpos, hpos, y, x;
1062 struct window *w;
1064 /* If updated_window is not set, work on selected_window. */
1065 if (updated_window)
1066 w = updated_window;
1067 else
1068 w = XWINDOW (selected_window);
1070 /* Set the output cursor. */
1071 output_cursor.hpos = hpos;
1072 output_cursor.vpos = vpos;
1073 output_cursor.x = x;
1074 output_cursor.y = y;
1076 /* If not called as part of an update, really display the cursor.
1077 This will also set the cursor position of W. */
1078 if (updated_window == NULL)
1080 BLOCK_INPUT;
1081 x_display_cursor (w, 1, hpos, vpos, x, y);
1082 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1083 UNBLOCK_INPUT;
1089 /***********************************************************************
1090 Display Iterator
1091 ***********************************************************************/
1093 /* Function prototypes of this page. */
1095 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1096 struct glyph *,
1097 XChar2b *));
1098 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1099 int, XChar2b *, int));
1100 static XCharStruct *x_per_char_metric_1 P_ ((XFontStruct *, XChar2b *));
1101 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1102 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1103 static void x_append_glyph P_ ((struct it *));
1104 static void x_append_composite_glyph P_ ((struct it *));
1105 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1106 int, int, double));
1107 static void x_produce_glyphs P_ ((struct it *));
1108 static void x_produce_image_glyph P_ ((struct it *it));
1109 static XCharStruct *x_default_char P_ ((XFontStruct *, XChar2b *));
1112 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1113 is not contained in the font. */
1115 static INLINE XCharStruct *
1116 x_per_char_metric_1 (font, char2b)
1117 XFontStruct *font;
1118 XChar2b *char2b;
1120 /* The result metric information. */
1121 XCharStruct *pcm = NULL;
1123 xassert (font && char2b);
1125 if (font->per_char != NULL)
1127 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1129 /* min_char_or_byte2 specifies the linear character index
1130 corresponding to the first element of the per_char array,
1131 max_char_or_byte2 is the index of the last character. A
1132 character with non-zero CHAR2B->byte1 is not in the font.
1133 A character with byte2 less than min_char_or_byte2 or
1134 greater max_char_or_byte2 is not in the font. */
1135 if (char2b->byte1 == 0
1136 && char2b->byte2 >= font->min_char_or_byte2
1137 && char2b->byte2 <= font->max_char_or_byte2)
1138 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1140 else
1142 /* If either min_byte1 or max_byte1 are nonzero, both
1143 min_char_or_byte2 and max_char_or_byte2 are less than
1144 256, and the 2-byte character index values corresponding
1145 to the per_char array element N (counting from 0) are:
1147 byte1 = N/D + min_byte1
1148 byte2 = N\D + min_char_or_byte2
1150 where:
1152 D = max_char_or_byte2 - min_char_or_byte2 + 1
1153 / = integer division
1154 \ = integer modulus */
1155 if (char2b->byte1 >= font->min_byte1
1156 && char2b->byte1 <= font->max_byte1
1157 && char2b->byte2 >= font->min_char_or_byte2
1158 && char2b->byte2 <= font->max_char_or_byte2)
1160 pcm = (font->per_char
1161 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1162 * (char2b->byte1 - font->min_byte1))
1163 + (char2b->byte2 - font->min_char_or_byte2));
1167 else
1169 /* If the per_char pointer is null, all glyphs between the first
1170 and last character indexes inclusive have the same
1171 information, as given by both min_bounds and max_bounds. */
1172 if (char2b->byte2 >= font->min_char_or_byte2
1173 && char2b->byte2 <= font->max_char_or_byte2)
1174 pcm = &font->max_bounds;
1177 if (pcm && pcm->width == 0)
1178 pcm = NULL;
1180 return pcm;
1184 /* Return in *DEFAULT_CHAR the default char to use for characters not
1185 contained in FONT. This is either FONT->default_char if that is
1186 valid, or some suitable other character if FONT->default_char is
1187 invalid. Value is a pointer to the XCharStruct of
1188 FONT->default_char or null if FONT->default_char is invalid. */
1190 static INLINE XCharStruct *
1191 x_default_char (font, default_char)
1192 XFontStruct *font;
1193 XChar2b *default_char;
1195 XCharStruct *pcm;
1197 /* FONT->default_char is a 16-bit character code with byte1 in the
1198 most significant byte and byte2 in the least significant
1199 byte. */
1200 default_char->byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
1201 default_char->byte2 = font->default_char & 0xff;
1202 pcm = x_per_char_metric_1 (font, default_char);
1204 /* If FONT->default_char is invalid, choose a better one. */
1205 if (pcm == NULL)
1207 if (font->per_char)
1209 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1211 default_char->byte1 = 0;
1212 default_char->byte2 = font->min_char_or_byte2;
1214 else
1216 default_char->byte1 = font->min_byte1;
1217 default_char->byte2 = font->min_char_or_byte2;
1220 else
1221 default_char->byte2 = font->min_char_or_byte2;
1224 return pcm;
1228 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1229 If CHAR2B is not contained in FONT, a default character metric is
1230 returned. */
1232 static INLINE XCharStruct *
1233 x_per_char_metric (font, char2b)
1234 XFontStruct *font;
1235 XChar2b *char2b;
1237 XCharStruct *pcm = x_per_char_metric_1 (font, char2b);
1239 if (pcm == NULL)
1241 /* Character not contained in the font. FONT->default_char
1242 gives the character that will be printed. FONT->default_char
1243 is a 16-bit character code with byte1 in the most significant
1244 byte and byte2 in the least significant byte. */
1245 XChar2b default_char;
1247 pcm = x_default_char (font, &default_char);
1248 if (pcm == NULL)
1249 pcm = x_per_char_metric_1 (font, &default_char);
1252 xassert (pcm != NULL);
1253 return pcm;
1257 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1258 the two-byte form of C. Encoding is returned in *CHAR2B. */
1260 static INLINE void
1261 x_encode_char (c, char2b, font_info)
1262 int c;
1263 XChar2b *char2b;
1264 struct font_info *font_info;
1266 int charset = CHAR_CHARSET (c);
1267 XFontStruct *font = font_info->font;
1269 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1270 This may be either a program in a special encoder language or a
1271 fixed encoding. */
1272 if (font_info->font_encoder)
1274 /* It's a program. */
1275 struct ccl_program *ccl = font_info->font_encoder;
1277 if (CHARSET_DIMENSION (charset) == 1)
1279 ccl->reg[0] = charset;
1280 ccl->reg[1] = char2b->byte2;
1282 else
1284 ccl->reg[0] = charset;
1285 ccl->reg[1] = char2b->byte1;
1286 ccl->reg[2] = char2b->byte2;
1289 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1291 /* We assume that MSBs are appropriately set/reset by CCL
1292 program. */
1293 if (font->max_byte1 == 0) /* 1-byte font */
1294 char2b->byte2 = ccl->reg[1];
1295 else
1296 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1298 else if (font_info->encoding[charset])
1300 /* Fixed encoding scheme. See fontset.h for the meaning of the
1301 encoding numbers. */
1302 int enc = font_info->encoding[charset];
1304 if ((enc == 1 || enc == 2)
1305 && CHARSET_DIMENSION (charset) == 2)
1306 char2b->byte1 |= 0x80;
1308 if (enc == 1 || enc == 3)
1309 char2b->byte2 |= 0x80;
1314 /* Get face and two-byte form of character C in face FACE_ID on frame
1315 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1316 means we want to display multibyte text. Value is a pointer to a
1317 realized face that is ready for display. */
1319 static INLINE struct face *
1320 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1321 struct frame *f;
1322 int c, face_id;
1323 XChar2b *char2b;
1324 int multibyte_p;
1326 struct face *face = FACE_FROM_ID (f, face_id);
1328 if (!multibyte_p)
1330 /* Unibyte case. We don't have to encode, but we have to make
1331 sure to use a face suitable for unibyte. */
1332 char2b->byte1 = 0;
1333 char2b->byte2 = c;
1335 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
1337 face_id = FACE_FOR_CHARSET (f, face_id, -1);
1338 face = FACE_FROM_ID (f, face_id);
1341 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1343 /* Case of ASCII in a face known to fit ASCII. */
1344 char2b->byte1 = 0;
1345 char2b->byte2 = c;
1347 else
1349 int c1, c2, charset;
1351 /* Split characters into bytes. If c2 is -1 afterwards, C is
1352 really a one-byte character so that byte1 is zero. */
1353 SPLIT_CHAR (c, charset, c1, c2);
1354 if (c2 > 0)
1355 char2b->byte1 = c1, char2b->byte2 = c2;
1356 else
1357 char2b->byte1 = 0, char2b->byte2 = c1;
1359 /* Get the face for displaying C. If `face' is not suitable for
1360 charset, get the one that fits. (This can happen for the
1361 translations of a composition where the glyph
1362 specifies a face for the first component, but the other
1363 components have a different charset.) */
1364 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
1366 face_id = FACE_FOR_CHARSET (f, face_id, charset);
1367 face = FACE_FROM_ID (f, face_id);
1370 /* Maybe encode the character in *CHAR2B. */
1371 if (charset != CHARSET_ASCII)
1373 struct font_info *font_info
1374 = FONT_INFO_FROM_ID (f, face->font_info_id);
1375 if (font_info)
1377 x_encode_char (c, char2b, font_info);
1378 if (charset == charset_latin_iso8859_1)
1380 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
1381 >= 0x80);
1382 char2b->byte2 |= 0x80;
1388 /* Make sure X resources of the face are allocated. */
1389 xassert (face != NULL);
1390 PREPARE_FACE_FOR_DISPLAY (f, face);
1392 return face;
1396 /* Get face and two-byte form of character glyph GLYPH on frame F.
1397 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1398 a pointer to a realized face that is ready for display. */
1400 static INLINE struct face *
1401 x_get_glyph_face_and_encoding (f, glyph, char2b)
1402 struct frame *f;
1403 struct glyph *glyph;
1404 XChar2b *char2b;
1406 struct face *face;
1408 xassert (glyph->type == CHAR_GLYPH);
1409 face = FACE_FROM_ID (f, glyph->face_id);
1411 if (!glyph->multibyte_p)
1413 /* Unibyte case. We don't have to encode, but we have to make
1414 sure to use a face suitable for unibyte. */
1415 char2b->byte1 = 0;
1416 char2b->byte2 = glyph->u.ch;
1418 else if (glyph->u.ch < 128
1419 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1421 /* Case of ASCII in a face known to fit ASCII. */
1422 char2b->byte1 = 0;
1423 char2b->byte2 = glyph->u.ch;
1425 else
1427 int c1, c2, charset;
1429 /* Split characters into bytes. If c2 is -1 afterwards, C is
1430 really a one-byte character so that byte1 is zero. */
1431 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1432 if (c2 > 0)
1433 char2b->byte1 = c1, char2b->byte2 = c2;
1434 else
1435 char2b->byte1 = 0, char2b->byte2 = c1;
1437 /* Maybe encode the character in *CHAR2B. */
1438 if (charset != CHARSET_ASCII)
1440 struct font_info *font_info
1441 = FONT_INFO_FROM_ID (f, face->font_info_id);
1442 if (font_info)
1444 x_encode_char (glyph->u.ch, char2b, font_info);
1445 if (charset == charset_latin_iso8859_1)
1446 char2b->byte2 |= 0x80;
1451 /* Make sure X resources of the face are allocated. */
1452 xassert (face != NULL);
1453 PREPARE_FACE_FOR_DISPLAY (f, face);
1454 return face;
1458 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1459 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1461 static INLINE void
1462 x_append_glyph (it)
1463 struct it *it;
1465 struct glyph *glyph;
1466 enum glyph_row_area area = it->area;
1468 xassert (it->glyph_row);
1469 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1471 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1472 if (glyph < it->glyph_row->glyphs[area + 1])
1474 /* Play it safe. If sub-structures of the glyph are not all the
1475 same size, it otherwise be that some bits stay set. This
1476 would prevent a comparison with GLYPH_EQUAL_P. */
1477 glyph->u.val = 0;
1479 glyph->type = CHAR_GLYPH;
1480 glyph->pixel_width = it->pixel_width;
1481 glyph->u.ch = it->char_to_display;
1482 glyph->face_id = it->face_id;
1483 glyph->charpos = CHARPOS (it->position);
1484 glyph->object = it->object;
1485 glyph->left_box_line_p = it->start_of_box_run_p;
1486 glyph->right_box_line_p = it->end_of_box_run_p;
1487 glyph->voffset = it->voffset;
1488 glyph->multibyte_p = it->multibyte_p;
1489 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1490 || it->phys_descent > it->descent);
1491 ++it->glyph_row->used[area];
1495 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1496 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1498 static INLINE void
1499 x_append_composite_glyph (it)
1500 struct it *it;
1502 struct glyph *glyph;
1503 enum glyph_row_area area = it->area;
1505 xassert (it->glyph_row);
1507 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1508 if (glyph < it->glyph_row->glyphs[area + 1])
1510 /* Play it safe. If sub-structures of the glyph are not all the
1511 same size, it otherwise be that some bits stay set. This
1512 would prevent a comparison with GLYPH_EQUAL_P. */
1513 glyph->u.val = 0;
1515 glyph->type = COMPOSITE_GLYPH;
1516 glyph->pixel_width = it->pixel_width;
1517 glyph->u.cmp_id = it->cmp_id;
1518 glyph->face_id = it->face_id;
1519 glyph->charpos = CHARPOS (it->position);
1520 glyph->object = it->object;
1521 glyph->left_box_line_p = it->start_of_box_run_p;
1522 glyph->right_box_line_p = it->end_of_box_run_p;
1523 glyph->voffset = it->voffset;
1524 glyph->multibyte_p = it->multibyte_p;
1525 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1526 || it->phys_descent > it->descent);
1527 ++it->glyph_row->used[area];
1532 /* Change IT->ascent and IT->height according to the setting of
1533 IT->voffset. */
1535 static INLINE void
1536 take_vertical_position_into_account (it)
1537 struct it *it;
1539 if (it->voffset)
1541 if (it->voffset < 0)
1542 /* Increase the ascent so that we can display the text higher
1543 in the line. */
1544 it->ascent += abs (it->voffset);
1545 else
1546 /* Increase the descent so that we can display the text lower
1547 in the line. */
1548 it->descent += it->voffset;
1553 /* Produce glyphs/get display metrics for the image IT is loaded with.
1554 See the description of struct display_iterator in dispextern.h for
1555 an overview of struct display_iterator. */
1557 static void
1558 x_produce_image_glyph (it)
1559 struct it *it;
1561 struct image *img;
1562 struct face *face;
1564 xassert (it->what == IT_IMAGE);
1566 face = FACE_FROM_ID (it->f, it->face_id);
1567 img = IMAGE_FROM_ID (it->f, it->image_id);
1568 xassert (img);
1570 /* Make sure X resources of the face and image are loaded. */
1571 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1572 prepare_image_for_display (it->f, img);
1574 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1575 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1576 it->pixel_width = img->width + 2 * img->margin;
1578 it->nglyphs = 1;
1580 if (face->box != FACE_NO_BOX)
1582 it->ascent += face->box_line_width;
1583 it->descent += face->box_line_width;
1585 if (it->start_of_box_run_p)
1586 it->pixel_width += face->box_line_width;
1587 if (it->end_of_box_run_p)
1588 it->pixel_width += face->box_line_width;
1591 take_vertical_position_into_account (it);
1593 if (it->glyph_row)
1595 struct glyph *glyph;
1596 enum glyph_row_area area = it->area;
1598 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1599 if (glyph < it->glyph_row->glyphs[area + 1])
1601 glyph->type = IMAGE_GLYPH;
1602 glyph->u.img_id = img->id;
1603 glyph->face_id = it->face_id;
1604 glyph->pixel_width = it->pixel_width;
1605 glyph->charpos = CHARPOS (it->position);
1606 glyph->object = it->object;
1607 glyph->left_box_line_p = it->start_of_box_run_p;
1608 glyph->right_box_line_p = it->end_of_box_run_p;
1609 glyph->voffset = it->voffset;
1610 glyph->multibyte_p = it->multibyte_p;
1611 ++it->glyph_row->used[area];
1617 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1618 of the glyph, WIDTH and HEIGHT are the width and height of the
1619 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1620 ascent of the glyph (0 <= ASCENT <= 1). */
1622 static void
1623 x_append_stretch_glyph (it, object, width, height, ascent)
1624 struct it *it;
1625 Lisp_Object object;
1626 int width, height;
1627 double ascent;
1629 struct glyph *glyph;
1630 enum glyph_row_area area = it->area;
1632 xassert (ascent >= 0 && ascent <= 1);
1634 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1635 if (glyph < it->glyph_row->glyphs[area + 1])
1637 glyph->type = STRETCH_GLYPH;
1638 glyph->u.stretch.ascent = height * ascent;
1639 glyph->u.stretch.height = height;
1640 glyph->face_id = it->face_id;
1641 glyph->pixel_width = width;
1642 glyph->charpos = CHARPOS (it->position);
1643 glyph->object = object;
1644 glyph->left_box_line_p = it->start_of_box_run_p;
1645 glyph->right_box_line_p = it->end_of_box_run_p;
1646 glyph->voffset = it->voffset;
1647 glyph->multibyte_p = it->multibyte_p;
1648 ++it->glyph_row->used[area];
1653 /* Produce a stretch glyph for iterator IT. IT->object is the value
1654 of the glyph property displayed. The value must be a list
1655 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1656 being recognized:
1658 1. `:width WIDTH' specifies that the space should be WIDTH *
1659 canonical char width wide. WIDTH may be an integer or floating
1660 point number.
1662 2. `:relative-width FACTOR' specifies that the width of the stretch
1663 should be computed from the width of the first character having the
1664 `glyph' property, and should be FACTOR times that width.
1666 3. `:align-to HPOS' specifies that the space should be wide enough
1667 to reach HPOS, a value in canonical character units.
1669 Exactly one of the above pairs must be present.
1671 4. `:height HEIGHT' specifies that the height of the stretch produced
1672 should be HEIGHT, measured in canonical character units.
1674 5. `:relative-height FACTOR' specifies that the height of the the
1675 stretch should be FACTOR times the height of the characters having
1676 the glyph property.
1678 Either none or exactly one of 4 or 5 must be present.
1680 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1681 of the stretch should be used for the ascent of the stretch.
1682 ASCENT must be in the range 0 <= ASCENT <= 100. */
1684 #define NUMVAL(X) \
1685 ((INTEGERP (X) || FLOATP (X)) \
1686 ? XFLOATINT (X) \
1687 : - 1)
1690 static void
1691 x_produce_stretch_glyph (it)
1692 struct it *it;
1694 /* (space :width WIDTH :height HEIGHT. */
1695 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1696 extern Lisp_Object QCrelative_width, QCrelative_height;
1697 extern Lisp_Object QCalign_to;
1698 Lisp_Object prop, plist;
1699 double width = 0, height = 0, ascent = 0;
1700 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1701 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1703 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1705 /* List should start with `space'. */
1706 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1707 plist = XCDR (it->object);
1709 /* Compute the width of the stretch. */
1710 if (prop = Fplist_get (plist, QCwidth),
1711 NUMVAL (prop) > 0)
1712 /* Absolute width `:width WIDTH' specified and valid. */
1713 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1714 else if (prop = Fplist_get (plist, QCrelative_width),
1715 NUMVAL (prop) > 0)
1717 /* Relative width `:relative-width FACTOR' specified and valid.
1718 Compute the width of the characters having the `glyph'
1719 property. */
1720 struct it it2;
1721 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1723 it2 = *it;
1724 if (it->multibyte_p)
1726 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1727 - IT_BYTEPOS (*it));
1728 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1730 else
1731 it2.c = *p, it2.len = 1;
1733 it2.glyph_row = NULL;
1734 it2.what = IT_CHARACTER;
1735 x_produce_glyphs (&it2);
1736 width = NUMVAL (prop) * it2.pixel_width;
1738 else if (prop = Fplist_get (plist, QCalign_to),
1739 NUMVAL (prop) > 0)
1740 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1741 else
1742 /* Nothing specified -> width defaults to canonical char width. */
1743 width = CANON_X_UNIT (it->f);
1745 /* Compute height. */
1746 if (prop = Fplist_get (plist, QCheight),
1747 NUMVAL (prop) > 0)
1748 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1749 else if (prop = Fplist_get (plist, QCrelative_height),
1750 NUMVAL (prop) > 0)
1751 height = FONT_HEIGHT (font) * NUMVAL (prop);
1752 else
1753 height = FONT_HEIGHT (font);
1755 /* Compute percentage of height used for ascent. If
1756 `:ascent ASCENT' is present and valid, use that. Otherwise,
1757 derive the ascent from the font in use. */
1758 if (prop = Fplist_get (plist, QCascent),
1759 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1760 ascent = NUMVAL (prop) / 100.0;
1761 else
1762 ascent = (double) font->ascent / FONT_HEIGHT (font);
1764 if (width <= 0)
1765 width = 1;
1766 if (height <= 0)
1767 height = 1;
1769 if (it->glyph_row)
1771 Lisp_Object object = it->stack[it->sp - 1].string;
1772 if (!STRINGP (object))
1773 object = it->w->buffer;
1774 x_append_stretch_glyph (it, object, width, height, ascent);
1777 it->pixel_width = width;
1778 it->ascent = it->phys_ascent = height * ascent;
1779 it->descent = it->phys_descent = height - it->ascent;
1780 it->nglyphs = 1;
1782 if (face->box != FACE_NO_BOX)
1784 it->ascent += face->box_line_width;
1785 it->descent += face->box_line_width;
1787 if (it->start_of_box_run_p)
1788 it->pixel_width += face->box_line_width;
1789 if (it->end_of_box_run_p)
1790 it->pixel_width += face->box_line_width;
1793 take_vertical_position_into_account (it);
1796 /* Return proper value to be used as baseline offset of font that has
1797 ASCENT and DESCENT to draw characters by the font at the vertical
1798 center of the line of frame F.
1800 Here, out task is to find the value of BOFF in the following figure;
1802 -------------------------+-----------+-
1803 -+-+---------+-+ | |
1804 | | | | | |
1805 | | | | F_ASCENT F_HEIGHT
1806 | | | ASCENT | |
1807 HEIGHT | | | | |
1808 | | |-|-+------+-----------|------- baseline
1809 | | | | BOFF | |
1810 | |---------|-+-+ | |
1811 | | | DESCENT | |
1812 -+-+---------+-+ F_DESCENT |
1813 -------------------------+-----------+-
1815 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1816 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1817 DESCENT = FONT->descent
1818 HEIGHT = FONT_HEIGHT (FONT)
1819 F_DESCENT = (F->output_data.x->font->descent
1820 - F->output_data.x->baseline_offset)
1821 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1824 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1825 ((FONT)->descent \
1826 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1827 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1829 /* Produce glyphs/get display metrics for the display element IT is
1830 loaded with. See the description of struct display_iterator in
1831 dispextern.h for an overview of struct display_iterator. */
1833 static void
1834 x_produce_glyphs (it)
1835 struct it *it;
1837 if (it->what == IT_CHARACTER)
1839 XChar2b char2b;
1840 XFontStruct *font;
1841 struct face *face;
1842 XCharStruct *pcm;
1843 int font_not_found_p;
1844 struct font_info *font_info;
1845 int boff; /* baseline offset */
1847 /* Maybe translate single-byte characters to multibyte. */
1848 it->char_to_display = it->c;
1849 if (unibyte_display_via_language_environment
1850 && SINGLE_BYTE_CHAR_P (it->c)
1851 && (it->c >= 0240
1852 || (it->c >= 0200
1853 && !NILP (Vnonascii_translation_table))))
1855 it->char_to_display = unibyte_char_to_multibyte (it->c);
1856 it->charset = CHAR_CHARSET (it->char_to_display);
1859 /* Get face and font to use. Encode IT->char_to_display. */
1860 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1861 it->face_id, &char2b,
1862 it->multibyte_p);
1863 font = face->font;
1865 /* When no suitable font found, use the default font. */
1866 font_not_found_p = font == NULL;
1867 if (font_not_found_p)
1869 font = FRAME_FONT (it->f);
1870 boff = it->f->output_data.x->baseline_offset;
1871 font_info = NULL;
1873 else
1875 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1876 boff = font_info->baseline_offset;
1877 if (font_info->vertical_centering)
1878 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1881 if (it->char_to_display >= ' '
1882 && (!it->multibyte_p || it->char_to_display < 128))
1884 /* Either unibyte or ASCII. */
1885 int stretched_p;
1887 it->nglyphs = 1;
1889 pcm = x_per_char_metric (font, &char2b);
1890 it->ascent = font->ascent + boff;
1891 it->descent = font->descent - boff;
1892 it->phys_ascent = pcm->ascent + boff;
1893 it->phys_descent = pcm->descent - boff;
1894 it->pixel_width = pcm->width;
1896 /* If this is a space inside a region of text with
1897 `space-width' property, change its width. */
1898 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1899 if (stretched_p)
1900 it->pixel_width *= XFLOATINT (it->space_width);
1902 /* If face has a box, add the box thickness to the character
1903 height. If character has a box line to the left and/or
1904 right, add the box line width to the character's width. */
1905 if (face->box != FACE_NO_BOX)
1907 int thick = face->box_line_width;
1909 it->ascent += thick;
1910 it->descent += thick;
1912 if (it->start_of_box_run_p)
1913 it->pixel_width += thick;
1914 if (it->end_of_box_run_p)
1915 it->pixel_width += thick;
1918 /* If face has an overline, add the height of the overline
1919 (1 pixel) and a 1 pixel margin to the character height. */
1920 if (face->overline_p)
1921 it->ascent += 2;
1923 take_vertical_position_into_account (it);
1925 /* If we have to actually produce glyphs, do it. */
1926 if (it->glyph_row)
1928 if (stretched_p)
1930 /* Translate a space with a `space-width' property
1931 into a stretch glyph. */
1932 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1933 x_append_stretch_glyph (it, it->object, it->pixel_width,
1934 it->ascent + it->descent, ascent);
1936 else
1937 x_append_glyph (it);
1939 /* If characters with lbearing or rbearing are displayed
1940 in this line, record that fact in a flag of the
1941 glyph row. This is used to optimize X output code. */
1942 if (pcm->lbearing < 0
1943 || pcm->rbearing > pcm->width)
1944 it->glyph_row->contains_overlapping_glyphs_p = 1;
1947 else if (it->char_to_display == '\n')
1949 /* A newline has no width but we need the height of the line. */
1950 it->pixel_width = 0;
1951 it->nglyphs = 0;
1952 it->ascent = it->phys_ascent = font->ascent + boff;
1953 it->descent = it->phys_descent = font->descent - boff;
1955 if (face->box != FACE_NO_BOX)
1957 int thick = face->box_line_width;
1958 it->ascent += thick;
1959 it->descent += thick;
1962 else if (it->char_to_display == '\t')
1964 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1965 int x = (it->current_x
1966 - it->prompt_width
1967 + it->continuation_lines_width);
1968 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1970 it->pixel_width = next_tab_x - x;
1971 it->nglyphs = 1;
1972 it->ascent = it->phys_ascent = font->ascent + boff;
1973 it->descent = it->phys_descent = font->descent - boff;
1975 if (it->glyph_row)
1977 double ascent = (double) it->ascent / (it->ascent + it->descent);
1978 x_append_stretch_glyph (it, it->object, it->pixel_width,
1979 it->ascent + it->descent, ascent);
1982 else
1984 /* A multi-byte character. Assume that the display width of the
1985 character is the width of the character multiplied by the
1986 width of the font. */
1988 /* If we found a font, this font should give us the right
1989 metrics. If we didn't find a font, use the frame's
1990 default font and calculate the width of the character
1991 from the charset width; this is what old redisplay code
1992 did. */
1993 pcm = x_per_char_metric (font, &char2b);
1994 it->pixel_width = pcm->width;
1995 if (font_not_found_p)
1996 it->pixel_width *= CHARSET_WIDTH (it->charset);
1997 it->nglyphs = 1;
1998 it->ascent = font->ascent + boff;
1999 it->descent = font->descent - boff;
2000 it->phys_ascent = pcm->ascent + boff;
2001 it->phys_descent = pcm->descent - boff;
2002 if (it->glyph_row
2003 && (pcm->lbearing < 0
2004 || pcm->rbearing > pcm->width))
2005 it->glyph_row->contains_overlapping_glyphs_p = 1;
2007 if (face->box != FACE_NO_BOX)
2009 int thick = face->box_line_width;
2010 it->ascent += thick;
2011 it->descent += thick;
2013 if (it->start_of_box_run_p)
2014 it->pixel_width += thick;
2015 if (it->end_of_box_run_p)
2016 it->pixel_width += thick;
2019 /* If face has an overline, add the height of the overline
2020 (1 pixel) and a 1 pixel margin to the character height. */
2021 if (face->overline_p)
2022 it->ascent += 2;
2024 take_vertical_position_into_account (it);
2026 if (it->glyph_row)
2027 x_append_glyph (it);
2030 else if (it->what == IT_COMPOSITION)
2032 /* Note: A composition is represented as one glyph in the
2033 glyph matrix. There are no padding glyphs. */
2034 XChar2b char2b;
2035 XFontStruct *font;
2036 struct face *face;
2037 XCharStruct *pcm;
2038 int font_not_found_p;
2039 struct font_info *font_info;
2040 int boff; /* baseline offset */
2041 struct composition *cmp = composition_table[it->cmp_id];
2043 /* Maybe translate single-byte characters to multibyte. */
2044 it->char_to_display = it->c;
2045 if (unibyte_display_via_language_environment
2046 && SINGLE_BYTE_CHAR_P (it->c)
2047 && (it->c >= 0240
2048 || (it->c >= 0200
2049 && !NILP (Vnonascii_translation_table))))
2051 it->char_to_display = unibyte_char_to_multibyte (it->c);
2052 it->charset = CHAR_CHARSET (it->char_to_display);
2055 /* Get face and font to use. Encode IT->char_to_display. */
2056 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
2057 it->face_id, &char2b,
2058 it->multibyte_p);
2059 font = face->font;
2061 /* When no suitable font found, use the default font. */
2062 font_not_found_p = font == NULL;
2063 if (font_not_found_p)
2065 font = FRAME_FONT (it->f);
2066 boff = it->f->output_data.x->baseline_offset;
2067 font_info = NULL;
2069 else
2071 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2072 boff = font_info->baseline_offset;
2073 if (font_info->vertical_centering)
2074 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2077 /* There are no padding glyphs, so there is only one glyph to
2078 produce for the composition. Important is that pixel_width,
2079 ascent and descent are the values of what is drawn by
2080 draw_glyphs (i.e. the values of the overall glyphs composed). */
2081 it->nglyphs = 1;
2083 /* If we have not yet calculated pixel size data of glyphs of
2084 the composition for the current face font, calculate them
2085 now. Theoretically, we have to check all fonts for the
2086 glyphs, but that requires much time and memory space. So,
2087 here we check only the font of the first glyph. This leads
2088 to incorrect display very rarely, and C-l (recenter) can
2089 correct the display anyway. */
2090 if (cmp->font != (void *) font)
2092 /* Ascent and descent of the font of the first character of
2093 this composition (adjusted by baseline offset). Ascent
2094 and descent of overall glyphs should not be less than
2095 them respectively. */
2096 int font_ascent = font->ascent + boff;
2097 int font_descent = font->descent - boff;
2098 /* Bounding box of the overall glyphs. */
2099 int leftmost, rightmost, lowest, highest;
2100 int i;
2102 cmp->font = (void *) font;
2104 /* Initialize the bounding box. */
2105 pcm = x_per_char_metric (font, &char2b);
2106 leftmost = 0;
2107 rightmost = pcm->width;
2108 lowest = - pcm->descent + boff;
2109 highest = pcm->ascent + boff;
2110 if (font_info
2111 && font_info->default_ascent
2112 && CHAR_TABLE_P (Vuse_default_ascent)
2113 && !NILP (Faref (Vuse_default_ascent,
2114 make_number (it->char_to_display))))
2115 highest = font_info->default_ascent + boff;
2117 /* Draw the first glyph at the normal position. It may be
2118 shifted to right later if some other glyphs are drawn at
2119 the left. */
2120 cmp->offsets[0] = 0;
2121 cmp->offsets[1] = boff;
2123 /* Set cmp->offsets for the remaining glyphs. */
2124 for (i = 1; i < cmp->glyph_len; i++)
2126 int left, right, btm, top;
2127 int ch = COMPOSITION_GLYPH (cmp, i);
2129 face = x_get_char_face_and_encoding (it->f, ch,
2130 it->face_id, &char2b,
2131 it->multibyte_p);
2132 font = face->font;
2133 if (font == NULL)
2135 font = FRAME_FONT (it->f);
2136 boff = it->f->output_data.x->baseline_offset;
2137 font_info = NULL;
2139 else
2141 font_info
2142 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2143 boff = font_info->baseline_offset;
2144 if (font_info->vertical_centering)
2145 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2148 pcm = x_per_char_metric (font, &char2b);
2150 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2152 /* Relative composition with or without
2153 alternate chars. */
2154 left = (leftmost + rightmost - pcm->width) / 2;
2155 btm = - pcm->descent + boff;
2156 if (font_info && font_info->relative_compose
2157 && (! CHAR_TABLE_P (Vignore_relative_composition)
2158 || NILP (Faref (Vignore_relative_composition,
2159 make_number (ch)))))
2162 if (- pcm->descent
2163 >= font_info->relative_compose)
2164 /* One extra pixel between two glyphs. */
2165 btm = highest + 1;
2166 else if (pcm->ascent <= 0)
2167 /* One extra pixel between two glyphs. */
2168 btm = lowest - 1 - pcm->ascent - pcm->descent;
2171 else
2173 /* A composition rule is specified by an integer
2174 value that encodes global and new reference
2175 points (GREF and NREF). GREF and NREF are
2176 specified by numbers as below:
2178 0---1---2 -- ascent
2182 9--10--11 -- center
2184 ---3---4---5--- baseline
2186 6---7---8 -- descent
2188 int rule = COMPOSITION_RULE (cmp, i);
2189 int gref, nref, grefx, grefy, nrefx, nrefy;
2191 COMPOSITION_DECODE_RULE (rule, gref, nref);
2192 grefx = gref % 3, nrefx = nref % 3;
2193 grefy = gref / 3, nrefy = nref / 3;
2195 left = (leftmost
2196 + grefx * (rightmost - leftmost) / 2
2197 - nrefx * pcm->width / 2);
2198 btm = ((grefy == 0 ? highest
2199 : grefy == 1 ? 0
2200 : grefy == 2 ? lowest
2201 : (highest + lowest) / 2)
2202 - (nrefy == 0 ? pcm->ascent + pcm->descent
2203 : nrefy == 1 ? pcm->descent - boff
2204 : nrefy == 2 ? 0
2205 : (pcm->ascent + pcm->descent) / 2));
2208 cmp->offsets[i * 2] = left;
2209 cmp->offsets[i * 2 + 1] = btm + pcm->descent;
2211 /* Update the bounding box of the overall glyphs. */
2212 right = left + pcm->width;
2213 top = btm + pcm->descent + pcm->ascent;
2214 if (left < leftmost)
2215 leftmost = left;
2216 if (right > rightmost)
2217 rightmost = right;
2218 if (top > highest)
2219 highest = top;
2220 if (btm < lowest)
2221 lowest = btm;
2224 /* If there are glyphs whose x-offsets are negative,
2225 shift all glyphs to the right and make all x-offsets
2226 non-negative. */
2227 if (leftmost < 0)
2229 for (i = 0; i < cmp->glyph_len; i++)
2230 cmp->offsets[i * 2] -= leftmost;
2231 rightmost -= leftmost;
2234 cmp->pixel_width = rightmost;
2235 cmp->ascent = highest;
2236 cmp->descent = - lowest;
2237 if (cmp->ascent < font_ascent)
2238 cmp->ascent = font_ascent;
2239 if (cmp->descent < font_descent)
2240 cmp->descent = font_descent;
2243 it->pixel_width = cmp->pixel_width;
2244 it->ascent = it->phys_ascent = cmp->ascent;
2245 it->descent = it->phys_descent = cmp->descent;
2247 if (face->box != FACE_NO_BOX)
2249 int thick = face->box_line_width;
2250 it->ascent += thick;
2251 it->descent += thick;
2253 if (it->start_of_box_run_p)
2254 it->pixel_width += thick;
2255 if (it->end_of_box_run_p)
2256 it->pixel_width += thick;
2259 /* If face has an overline, add the height of the overline
2260 (1 pixel) and a 1 pixel margin to the character height. */
2261 if (face->overline_p)
2262 it->ascent += 2;
2264 take_vertical_position_into_account (it);
2266 if (it->glyph_row)
2267 x_append_composite_glyph (it);
2269 else if (it->what == IT_IMAGE)
2270 x_produce_image_glyph (it);
2271 else if (it->what == IT_STRETCH)
2272 x_produce_stretch_glyph (it);
2274 /* Accumulate dimensions. */
2275 xassert (it->ascent >= 0 && it->descent > 0);
2276 if (it->area == TEXT_AREA)
2277 it->current_x += it->pixel_width;
2279 it->max_ascent = max (it->max_ascent, it->ascent);
2280 it->max_descent = max (it->max_descent, it->descent);
2281 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2282 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2286 /* Estimate the pixel height of the mode or top line on frame F.
2287 FACE_ID specifies what line's height to estimate. */
2290 x_estimate_mode_line_height (f, face_id)
2291 struct frame *f;
2292 enum face_id face_id;
2294 int height = 1;
2296 /* This function is called so early when Emacs starts that the face
2297 cache and mode line face are not yet initialized. */
2298 if (FRAME_FACE_CACHE (f))
2300 struct face *face = FACE_FROM_ID (f, face_id);
2301 if (face)
2302 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2305 return height;
2309 /***********************************************************************
2310 Glyph display
2311 ***********************************************************************/
2313 /* A sequence of glyphs to be drawn in the same face.
2315 This data structure is not really completely X specific, so it
2316 could possibly, at least partially, be useful for other systems. It
2317 is currently not part of the external redisplay interface because
2318 it's not clear what other systems will need. */
2320 struct glyph_string
2322 /* X-origin of the string. */
2323 int x;
2325 /* Y-origin and y-position of the base line of this string. */
2326 int y, ybase;
2328 /* The width of the string, not including a face extension. */
2329 int width;
2331 /* The width of the string, including a face extension. */
2332 int background_width;
2334 /* The height of this string. This is the height of the line this
2335 string is drawn in, and can be different from the height of the
2336 font the string is drawn in. */
2337 int height;
2339 /* Number of pixels this string overwrites in front of its x-origin.
2340 This number is zero if the string has an lbearing >= 0; it is
2341 -lbearing, if the string has an lbearing < 0. */
2342 int left_overhang;
2344 /* Number of pixels this string overwrites past its right-most
2345 nominal x-position, i.e. x + width. Zero if the string's
2346 rbearing is <= its nominal width, rbearing - width otherwise. */
2347 int right_overhang;
2349 /* The frame on which the glyph string is drawn. */
2350 struct frame *f;
2352 /* The window on which the glyph string is drawn. */
2353 struct window *w;
2355 /* X display and window for convenience. */
2356 Display *display;
2357 Window window;
2359 /* The glyph row for which this string was built. It determines the
2360 y-origin and height of the string. */
2361 struct glyph_row *row;
2363 /* The area within row. */
2364 enum glyph_row_area area;
2366 /* Characters to be drawn, and number of characters. */
2367 XChar2b *char2b;
2368 int nchars;
2370 /* Character set of this glyph string. */
2371 int charset;
2373 /* A face-override for drawing cursors, mouse face and similar. */
2374 enum draw_glyphs_face hl;
2376 /* Face in which this string is to be drawn. */
2377 struct face *face;
2379 /* Font in which this string is to be drawn. */
2380 XFontStruct *font;
2382 /* Font info for this string. */
2383 struct font_info *font_info;
2385 /* Non-null means this string describes (part of) a composition.
2386 All characters from char2b are drawn composed. */
2387 struct composition *cmp;
2389 /* Index of this glyph string's first character in the glyph
2390 definition of CMP. If this is zero, this glyph string describes
2391 the first character of a composition. */
2392 int gidx;
2394 /* 1 means this glyph strings face has to be drawn to the right end
2395 of the window's drawing area. */
2396 unsigned extends_to_end_of_line_p : 1;
2398 /* 1 means the background of this string has been drawn. */
2399 unsigned background_filled_p : 1;
2401 /* 1 means glyph string must be drawn with 16-bit functions. */
2402 unsigned two_byte_p : 1;
2404 /* 1 means that the original font determined for drawing this glyph
2405 string could not be loaded. The member `font' has been set to
2406 the frame's default font in this case. */
2407 unsigned font_not_found_p : 1;
2409 /* 1 means that the face in which this glyph string is drawn has a
2410 stipple pattern. */
2411 unsigned stippled_p : 1;
2413 /* 1 means only the foreground of this glyph string must be drawn,
2414 and we should use the physical height of the line this glyph
2415 string appears in as clip rect. */
2416 unsigned for_overlaps_p : 1;
2418 /* The GC to use for drawing this glyph string. */
2419 GC gc;
2421 /* A pointer to the first glyph in the string. This glyph
2422 corresponds to char2b[0]. Needed to draw rectangles if
2423 font_not_found_p is 1. */
2424 struct glyph *first_glyph;
2426 /* Image, if any. */
2427 struct image *img;
2429 struct glyph_string *next, *prev;
2433 #if 0
2435 static void
2436 x_dump_glyph_string (s)
2437 struct glyph_string *s;
2439 fprintf (stderr, "glyph string\n");
2440 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2441 s->x, s->y, s->width, s->height);
2442 fprintf (stderr, " ybase = %d\n", s->ybase);
2443 fprintf (stderr, " hl = %d\n", s->hl);
2444 fprintf (stderr, " left overhang = %d, right = %d\n",
2445 s->left_overhang, s->right_overhang);
2446 fprintf (stderr, " nchars = %d\n", s->nchars);
2447 fprintf (stderr, " extends to end of line = %d\n",
2448 s->extends_to_end_of_line_p);
2449 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2450 fprintf (stderr, " bg width = %d\n", s->background_width);
2453 #endif /* GLYPH_DEBUG */
2457 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2458 struct glyph_string **,
2459 struct glyph_string *,
2460 struct glyph_string *));
2461 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2462 struct glyph_string **,
2463 struct glyph_string *,
2464 struct glyph_string *));
2465 static void x_append_glyph_string P_ ((struct glyph_string **,
2466 struct glyph_string **,
2467 struct glyph_string *));
2468 static int x_left_overwritten P_ ((struct glyph_string *));
2469 static int x_left_overwriting P_ ((struct glyph_string *));
2470 static int x_right_overwritten P_ ((struct glyph_string *));
2471 static int x_right_overwriting P_ ((struct glyph_string *));
2472 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2473 int));
2474 static void x_init_glyph_string P_ ((struct glyph_string *,
2475 XChar2b *, struct window *,
2476 struct glyph_row *,
2477 enum glyph_row_area, int,
2478 enum draw_glyphs_face));
2479 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2480 enum glyph_row_area, int, int,
2481 enum draw_glyphs_face, int *, int *, int));
2482 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2483 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2484 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2485 int));
2486 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2487 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2488 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2489 static void x_draw_glyph_string P_ ((struct glyph_string *));
2490 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2491 static void x_set_cursor_gc P_ ((struct glyph_string *));
2492 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2493 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2494 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2495 int *, int *));
2496 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2497 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2498 unsigned long *, double, int));
2499 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2500 double, int, unsigned long));
2501 static void x_setup_relief_colors P_ ((struct glyph_string *));
2502 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2503 static void x_draw_image_relief P_ ((struct glyph_string *));
2504 static void x_draw_image_foreground P_ ((struct glyph_string *));
2505 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2506 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2507 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2508 int, int, int));
2509 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2510 int, int, int, int, XRectangle *));
2511 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2512 int, int, int, XRectangle *));
2513 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2514 enum glyph_row_area));
2517 /* Append the list of glyph strings with head H and tail T to the list
2518 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2520 static INLINE void
2521 x_append_glyph_string_lists (head, tail, h, t)
2522 struct glyph_string **head, **tail;
2523 struct glyph_string *h, *t;
2525 if (h)
2527 if (*head)
2528 (*tail)->next = h;
2529 else
2530 *head = h;
2531 h->prev = *tail;
2532 *tail = t;
2537 /* Prepend the list of glyph strings with head H and tail T to the
2538 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2539 result. */
2541 static INLINE void
2542 x_prepend_glyph_string_lists (head, tail, h, t)
2543 struct glyph_string **head, **tail;
2544 struct glyph_string *h, *t;
2546 if (h)
2548 if (*head)
2549 (*head)->prev = t;
2550 else
2551 *tail = t;
2552 t->next = *head;
2553 *head = h;
2558 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2559 Set *HEAD and *TAIL to the resulting list. */
2561 static INLINE void
2562 x_append_glyph_string (head, tail, s)
2563 struct glyph_string **head, **tail;
2564 struct glyph_string *s;
2566 s->next = s->prev = NULL;
2567 x_append_glyph_string_lists (head, tail, s, s);
2571 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2572 face. */
2574 static void
2575 x_set_cursor_gc (s)
2576 struct glyph_string *s;
2578 if (s->font == FRAME_FONT (s->f)
2579 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2580 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2581 && !s->cmp)
2582 s->gc = s->f->output_data.x->cursor_gc;
2583 else
2585 /* Cursor on non-default face: must merge. */
2586 XGCValues xgcv;
2587 unsigned long mask;
2589 xgcv.background = s->f->output_data.x->cursor_pixel;
2590 xgcv.foreground = s->face->background;
2592 /* If the glyph would be invisible, try a different foreground. */
2593 if (xgcv.foreground == xgcv.background)
2594 xgcv.foreground = s->face->foreground;
2595 if (xgcv.foreground == xgcv.background)
2596 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2597 if (xgcv.foreground == xgcv.background)
2598 xgcv.foreground = s->face->foreground;
2600 /* Make sure the cursor is distinct from text in this face. */
2601 if (xgcv.background == s->face->background
2602 && xgcv.foreground == s->face->foreground)
2604 xgcv.background = s->face->foreground;
2605 xgcv.foreground = s->face->background;
2608 IF_DEBUG (x_check_font (s->f, s->font));
2609 xgcv.font = s->font->fid;
2610 xgcv.graphics_exposures = False;
2611 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2613 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2614 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2615 mask, &xgcv);
2616 else
2617 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2618 = XCreateGC (s->display, s->window, mask, &xgcv);
2620 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2625 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2627 static void
2628 x_set_mouse_face_gc (s)
2629 struct glyph_string *s;
2631 int face_id;
2633 /* What face has to be used for the mouse face? */
2634 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2635 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
2636 s->face = FACE_FROM_ID (s->f, face_id);
2637 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2639 /* If font in this face is same as S->font, use it. */
2640 if (s->font == s->face->font)
2641 s->gc = s->face->gc;
2642 else
2644 /* Otherwise construct scratch_cursor_gc with values from FACE
2645 but font FONT. */
2646 XGCValues xgcv;
2647 unsigned long mask;
2649 xgcv.background = s->face->background;
2650 xgcv.foreground = s->face->foreground;
2651 IF_DEBUG (x_check_font (s->f, s->font));
2652 xgcv.font = s->font->fid;
2653 xgcv.graphics_exposures = False;
2654 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2656 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2657 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2658 mask, &xgcv);
2659 else
2660 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2661 = XCreateGC (s->display, s->window, mask, &xgcv);
2663 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2666 xassert (s->gc != 0);
2670 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2671 Faces to use in the mode line have already been computed when the
2672 matrix was built, so there isn't much to do, here. */
2674 static INLINE void
2675 x_set_mode_line_face_gc (s)
2676 struct glyph_string *s;
2678 s->gc = s->face->gc;
2679 xassert (s->gc != 0);
2683 /* Set S->gc of glyph string S for drawing that glyph string. Set
2684 S->stippled_p to a non-zero value if the face of S has a stipple
2685 pattern. */
2687 static INLINE void
2688 x_set_glyph_string_gc (s)
2689 struct glyph_string *s;
2691 if (s->hl == DRAW_NORMAL_TEXT)
2693 s->gc = s->face->gc;
2694 s->stippled_p = s->face->stipple != 0;
2696 else if (s->hl == DRAW_INVERSE_VIDEO)
2698 x_set_mode_line_face_gc (s);
2699 s->stippled_p = s->face->stipple != 0;
2701 else if (s->hl == DRAW_CURSOR)
2703 x_set_cursor_gc (s);
2704 s->stippled_p = 0;
2706 else if (s->hl == DRAW_MOUSE_FACE)
2708 x_set_mouse_face_gc (s);
2709 s->stippled_p = s->face->stipple != 0;
2711 else if (s->hl == DRAW_IMAGE_RAISED
2712 || s->hl == DRAW_IMAGE_SUNKEN)
2714 s->gc = s->face->gc;
2715 s->stippled_p = s->face->stipple != 0;
2717 else
2719 s->gc = s->face->gc;
2720 s->stippled_p = s->face->stipple != 0;
2723 /* GC must have been set. */
2724 xassert (s->gc != 0);
2728 /* Return in *R the clipping rectangle for glyph string S. */
2730 static void
2731 x_get_glyph_string_clip_rect (s, r)
2732 struct glyph_string *s;
2733 XRectangle *r;
2735 if (s->row->full_width_p)
2737 /* Draw full-width. X coordinates are relative to S->w->left. */
2738 int canon_x = CANON_X_UNIT (s->f);
2740 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2741 r->width = XFASTINT (s->w->width) * canon_x;
2743 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2745 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2746 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2747 r->x -= width;
2750 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2752 /* Unless displaying a mode or menu bar line, which are always
2753 fully visible, clip to the visible part of the row. */
2754 if (s->w->pseudo_window_p)
2755 r->height = s->row->visible_height;
2756 else
2757 r->height = s->height;
2759 else
2761 /* This is a text line that may be partially visible. */
2762 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2763 r->width = window_box_width (s->w, s->area);
2764 r->height = s->row->visible_height;
2767 /* Don't use S->y for clipping because it doesn't take partially
2768 visible lines into account. For example, it can be negative for
2769 partially visible lines at the top of a window. */
2770 if (!s->row->full_width_p
2771 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2772 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2773 else
2774 r->y = max (0, s->row->y);
2776 /* If drawing a tool-bar window, draw it over the internal border
2777 at the top of the window. */
2778 if (s->w == XWINDOW (s->f->tool_bar_window))
2779 r->y -= s->f->output_data.x->internal_border_width;
2781 /* If S draws overlapping rows, it's sufficient to use the top and
2782 bottom of the window for clipping because this glyph string
2783 intentionally draws over other lines. */
2784 if (s->for_overlaps_p)
2786 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2787 r->height = window_text_bottom_y (s->w) - r->y;
2790 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2794 /* Set clipping for output of glyph string S. S may be part of a mode
2795 line or menu if we don't have X toolkit support. */
2797 static INLINE void
2798 x_set_glyph_string_clipping (s)
2799 struct glyph_string *s;
2801 XRectangle r;
2802 x_get_glyph_string_clip_rect (s, &r);
2803 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2807 /* Compute left and right overhang of glyph string S. If S is a glyph
2808 string for a composition, assume overhangs don't exist. */
2810 static INLINE void
2811 x_compute_glyph_string_overhangs (s)
2812 struct glyph_string *s;
2814 if (s->cmp == NULL
2815 && s->first_glyph->type == CHAR_GLYPH)
2817 XCharStruct cs;
2818 int direction, font_ascent, font_descent;
2819 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2820 &font_ascent, &font_descent, &cs);
2821 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2822 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2827 /* Compute overhangs and x-positions for glyph string S and its
2828 predecessors, or successors. X is the starting x-position for S.
2829 BACKWARD_P non-zero means process predecessors. */
2831 static void
2832 x_compute_overhangs_and_x (s, x, backward_p)
2833 struct glyph_string *s;
2834 int x;
2835 int backward_p;
2837 if (backward_p)
2839 while (s)
2841 x_compute_glyph_string_overhangs (s);
2842 x -= s->width;
2843 s->x = x;
2844 s = s->prev;
2847 else
2849 while (s)
2851 x_compute_glyph_string_overhangs (s);
2852 s->x = x;
2853 x += s->width;
2854 s = s->next;
2860 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2861 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2862 assumed to be zero. */
2864 static void
2865 x_get_glyph_overhangs (glyph, f, left, right)
2866 struct glyph *glyph;
2867 struct frame *f;
2868 int *left, *right;
2870 int c;
2872 *left = *right = 0;
2874 if (glyph->type == CHAR_GLYPH)
2876 XFontStruct *font;
2877 struct face *face;
2878 struct font_info *font_info;
2879 XChar2b char2b;
2881 face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
2882 font = face->font;
2883 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2884 if (font)
2886 XCharStruct *pcm = x_per_char_metric (font, &char2b);
2888 if (pcm->rbearing > pcm->width)
2889 *right = pcm->rbearing - pcm->width;
2890 if (pcm->lbearing < 0)
2891 *left = -pcm->lbearing;
2897 /* Return the index of the first glyph preceding glyph string S that
2898 is overwritten by S because of S's left overhang. Value is -1
2899 if no glyphs are overwritten. */
2901 static int
2902 x_left_overwritten (s)
2903 struct glyph_string *s;
2905 int k;
2907 if (s->left_overhang)
2909 int x = 0, i;
2910 struct glyph *glyphs = s->row->glyphs[s->area];
2911 int first = s->first_glyph - glyphs;
2913 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2914 x -= glyphs[i].pixel_width;
2916 k = i + 1;
2918 else
2919 k = -1;
2921 return k;
2925 /* Return the index of the first glyph preceding glyph string S that
2926 is overwriting S because of its right overhang. Value is -1 if no
2927 glyph in front of S overwrites S. */
2929 static int
2930 x_left_overwriting (s)
2931 struct glyph_string *s;
2933 int i, k, x;
2934 struct glyph *glyphs = s->row->glyphs[s->area];
2935 int first = s->first_glyph - glyphs;
2937 k = -1;
2938 x = 0;
2939 for (i = first - 1; i >= 0; --i)
2941 int left, right;
2942 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2943 if (x + right > 0)
2944 k = i;
2945 x -= glyphs[i].pixel_width;
2948 return k;
2952 /* Return the index of the last glyph following glyph string S that is
2953 not overwritten by S because of S's right overhang. Value is -1 if
2954 no such glyph is found. */
2956 static int
2957 x_right_overwritten (s)
2958 struct glyph_string *s;
2960 int k = -1;
2962 if (s->right_overhang)
2964 int x = 0, i;
2965 struct glyph *glyphs = s->row->glyphs[s->area];
2966 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2967 int end = s->row->used[s->area];
2969 for (i = first; i < end && s->right_overhang > x; ++i)
2970 x += glyphs[i].pixel_width;
2972 k = i;
2975 return k;
2979 /* Return the index of the last glyph following glyph string S that
2980 overwrites S because of its left overhang. Value is negative
2981 if no such glyph is found. */
2983 static int
2984 x_right_overwriting (s)
2985 struct glyph_string *s;
2987 int i, k, x;
2988 int end = s->row->used[s->area];
2989 struct glyph *glyphs = s->row->glyphs[s->area];
2990 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2992 k = -1;
2993 x = 0;
2994 for (i = first; i < end; ++i)
2996 int left, right;
2997 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2998 if (x - left < 0)
2999 k = i;
3000 x += glyphs[i].pixel_width;
3003 return k;
3007 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3009 static INLINE void
3010 x_clear_glyph_string_rect (s, x, y, w, h)
3011 struct glyph_string *s;
3012 int x, y, w, h;
3014 XGCValues xgcv;
3015 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3016 XSetForeground (s->display, s->gc, xgcv.background);
3017 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3018 XSetForeground (s->display, s->gc, xgcv.foreground);
3022 /* Draw the background of glyph_string S. If S->background_filled_p
3023 is non-zero don't draw it. FORCE_P non-zero means draw the
3024 background even if it wouldn't be drawn normally. This is used
3025 when a string preceding S draws into the background of S, or S
3026 contains the first component of a composition. */
3028 static void
3029 x_draw_glyph_string_background (s, force_p)
3030 struct glyph_string *s;
3031 int force_p;
3033 /* Nothing to do if background has already been drawn or if it
3034 shouldn't be drawn in the first place. */
3035 if (!s->background_filled_p)
3037 if (s->stippled_p)
3039 /* Fill background with a stipple pattern. */
3040 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3041 XFillRectangle (s->display, s->window, s->gc, s->x,
3042 s->y + s->face->box_line_width,
3043 s->background_width,
3044 s->height - 2 * s->face->box_line_width);
3045 XSetFillStyle (s->display, s->gc, FillSolid);
3046 s->background_filled_p = 1;
3048 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3049 || s->font_not_found_p
3050 || s->extends_to_end_of_line_p
3051 || force_p)
3053 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3054 s->background_width,
3055 s->height - 2 * s->face->box_line_width);
3056 s->background_filled_p = 1;
3062 /* Draw the foreground of glyph string S. */
3064 static void
3065 x_draw_glyph_string_foreground (s)
3066 struct glyph_string *s;
3068 int i, x;
3070 /* If first glyph of S has a left box line, start drawing the text
3071 of S to the right of that box line. */
3072 if (s->face->box != FACE_NO_BOX
3073 && s->first_glyph->left_box_line_p)
3074 x = s->x + s->face->box_line_width;
3075 else
3076 x = s->x;
3078 /* Draw characters of S as rectangles if S's font could not be
3079 loaded. */
3080 if (s->font_not_found_p)
3082 for (i = 0; i < s->nchars; ++i)
3084 struct glyph *g = s->first_glyph + i;
3085 XDrawRectangle (s->display, s->window,
3086 s->gc, x, s->y, g->pixel_width - 1,
3087 s->height - 1);
3088 x += g->pixel_width;
3091 else
3093 char *char1b = (char *) s->char2b;
3094 int boff = s->font_info->baseline_offset;
3095 XChar2b default_char;
3097 if (s->font_info->vertical_centering)
3098 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3100 /* If S->font has an invalid default char, X might output some
3101 characters with zero width which is highly undesirable.
3102 Choose another default char in this case, and replace all
3103 occurrences of invalid characters in the string with that
3104 char. */
3105 if (!x_default_char (s->font, &default_char))
3106 for (i = 0; i < s->nchars; ++i)
3107 if (!x_per_char_metric_1 (s->font, s->char2b + i))
3108 s->char2b[i] = default_char;
3110 /* If we can use 8-bit functions, condense S->char2b. */
3111 if (!s->two_byte_p)
3112 for (i = 0; i < s->nchars; ++i)
3113 char1b[i] = s->char2b[i].byte2;
3115 /* Draw text with XDrawString if background has already been
3116 filled. Otherwise, use XDrawImageString. (Note that
3117 XDrawImageString is usually faster than XDrawString.) Always
3118 use XDrawImageString when drawing the cursor so that there is
3119 no chance that characters under a box cursor are invisible. */
3120 if (s->for_overlaps_p
3121 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3123 /* Draw characters with 16-bit or 8-bit functions. */
3124 if (s->two_byte_p)
3125 XDrawString16 (s->display, s->window, s->gc, x,
3126 s->ybase - boff, s->char2b, s->nchars);
3127 else
3128 XDrawString (s->display, s->window, s->gc, x,
3129 s->ybase - boff, char1b, s->nchars);
3131 else
3133 if (s->two_byte_p)
3134 XDrawImageString16 (s->display, s->window, s->gc, x,
3135 s->ybase - boff, s->char2b, s->nchars);
3136 else
3137 XDrawImageString (s->display, s->window, s->gc, x,
3138 s->ybase - boff, char1b, s->nchars);
3143 /* Draw the foreground of composite glyph string S. */
3145 static void
3146 x_draw_composite_glyph_string_foreground (s)
3147 struct glyph_string *s;
3149 int i, x;
3151 /* If first glyph of S has a left box line, start drawing the text
3152 of S to the right of that box line. */
3153 if (s->face->box != FACE_NO_BOX
3154 && s->first_glyph->left_box_line_p)
3155 x = s->x + s->face->box_line_width;
3156 else
3157 x = s->x;
3159 /* S is a glyph string for a composition. S->gidx is the index of
3160 the first character drawn for glyphs of this composition.
3161 S->gidx == 0 means we are drawing the very first character of
3162 this composition. */
3164 /* Draw a rectangle for the composition if the font for the very
3165 first character of the composition could not be loaded. */
3166 if (s->font_not_found_p)
3168 if (s->gidx == 0)
3169 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3170 s->width - 1, s->height - 1);
3172 else
3174 for (i = 0; i < s->nchars; i++, ++s->gidx)
3175 XDrawString16 (s->display, s->window, s->gc,
3176 x + s->cmp->offsets[s->gidx * 2],
3177 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3178 s->char2b + i, 1);
3183 #ifdef USE_X_TOOLKIT
3185 /* Allocate the color COLOR->pixel on the screen and display of
3186 widget WIDGET in colormap CMAP. If an exact match cannot be
3187 allocated, try the nearest color available. Value is non-zero
3188 if successful. This is called from lwlib. */
3191 x_alloc_nearest_color_for_widget (widget, cmap, color)
3192 Widget widget;
3193 Colormap cmap;
3194 XColor *color;
3196 struct frame *f;
3197 struct x_display_info *dpyinfo;
3198 Lisp_Object tail;
3200 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3202 /* Find the top-level shell of the widget. Note that this function
3203 can be called when the widget is not yet realized, so XtWindow
3204 (widget) == 0. That's the reason we can't simply use
3205 x_any_window_to_frame. */
3206 while (!XtIsTopLevelShell (widget))
3207 widget = XtParent (widget);
3209 /* Look for a frame with that top-level widget. Allocate the color
3210 on that frame to get the right gamma correction value. */
3211 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3212 if (GC_FRAMEP (XCAR (tail))
3213 && (f = XFRAME (XCAR (tail)),
3214 (f->output_data.nothing != 1
3215 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3216 && f->output_data.x->widget == widget)
3217 return x_alloc_nearest_color (f, cmap, color);
3219 abort ();
3222 #endif /* USE_X_TOOLKIT */
3225 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3226 CMAP. If an exact match can't be allocated, try the nearest color
3227 available. Value is non-zero if successful. Set *COLOR to the
3228 color allocated. */
3231 x_alloc_nearest_color (f, cmap, color)
3232 struct frame *f;
3233 Colormap cmap;
3234 XColor *color;
3236 Display *display = FRAME_X_DISPLAY (f);
3237 Screen *screen = FRAME_X_SCREEN (f);
3238 int rc;
3240 gamma_correct (f, color);
3241 rc = XAllocColor (display, cmap, color);
3242 if (rc == 0)
3244 /* If we got to this point, the colormap is full, so we're going
3245 to try to get the next closest color. The algorithm used is
3246 a least-squares matching, which is what X uses for closest
3247 color matching with StaticColor visuals. */
3248 int nearest, i;
3249 unsigned long nearest_delta = ~0;
3250 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3251 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3253 for (i = 0; i < ncells; ++i)
3254 cells[i].pixel = i;
3255 XQueryColors (display, cmap, cells, ncells);
3257 for (nearest = i = 0; i < ncells; ++i)
3259 long dred = (color->red >> 8) - (cells[i].red >> 8);
3260 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3261 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3262 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3264 if (delta < nearest_delta)
3266 nearest = i;
3267 nearest_delta = delta;
3271 color->red = cells[nearest].red;
3272 color->green = cells[nearest].green;
3273 color->blue = cells[nearest].blue;
3274 rc = XAllocColor (display, cmap, color);
3277 return rc;
3281 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3282 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3283 If this produces the same color as PIXEL, try a color where all RGB
3284 values have DELTA added. Return the allocated color in *PIXEL.
3285 DISPLAY is the X display, CMAP is the colormap to operate on.
3286 Value is non-zero if successful. */
3288 static int
3289 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3290 struct frame *f;
3291 Display *display;
3292 Colormap cmap;
3293 unsigned long *pixel;
3294 double factor;
3295 int delta;
3297 XColor color, new;
3298 int success_p;
3300 /* Get RGB color values. */
3301 color.pixel = *pixel;
3302 XQueryColor (display, cmap, &color);
3304 /* Change RGB values by specified FACTOR. Avoid overflow! */
3305 xassert (factor >= 0);
3306 new.red = min (0xffff, factor * color.red);
3307 new.green = min (0xffff, factor * color.green);
3308 new.blue = min (0xffff, factor * color.blue);
3310 /* Try to allocate the color. */
3311 success_p = x_alloc_nearest_color (f, cmap, &new);
3312 if (success_p)
3314 if (new.pixel == *pixel)
3316 /* If we end up with the same color as before, try adding
3317 delta to the RGB values. */
3318 x_free_colors (f, &new.pixel, 1);
3320 new.red = min (0xffff, delta + color.red);
3321 new.green = min (0xffff, delta + color.green);
3322 new.blue = min (0xffff, delta + color.blue);
3323 success_p = x_alloc_nearest_color (f, cmap, &new);
3325 else
3326 success_p = 1;
3327 *pixel = new.pixel;
3330 return success_p;
3334 /* Set up the foreground color for drawing relief lines of glyph
3335 string S. RELIEF is a pointer to a struct relief containing the GC
3336 with which lines will be drawn. Use a color that is FACTOR or
3337 DELTA lighter or darker than the relief's background which is found
3338 in S->f->output_data.x->relief_background. If such a color cannot
3339 be allocated, use DEFAULT_PIXEL, instead. */
3341 static void
3342 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3343 struct frame *f;
3344 struct relief *relief;
3345 double factor;
3346 int delta;
3347 unsigned long default_pixel;
3349 XGCValues xgcv;
3350 struct x_output *di = f->output_data.x;
3351 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3352 unsigned long pixel;
3353 unsigned long background = di->relief_background;
3354 Colormap cmap = FRAME_X_COLORMAP (f);
3355 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3356 Display *dpy = FRAME_X_DISPLAY (f);
3358 xgcv.graphics_exposures = False;
3359 xgcv.line_width = 1;
3361 /* Free previously allocated color. The color cell will be reused
3362 when it has been freed as many times as it was allocated, so this
3363 doesn't affect faces using the same colors. */
3364 if (relief->gc
3365 && relief->allocated_p)
3367 /* If display has an immutable color map, freeing colors is not
3368 necessary and some servers don't allow it. So don't do it. */
3369 x_free_colors (f, &relief->pixel, 1);
3370 relief->allocated_p = 0;
3373 /* Allocate new color. */
3374 xgcv.foreground = default_pixel;
3375 pixel = background;
3376 if (dpyinfo->n_planes != 1
3377 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3379 relief->allocated_p = 1;
3380 xgcv.foreground = relief->pixel = pixel;
3383 if (relief->gc == 0)
3385 xgcv.stipple = dpyinfo->gray;
3386 mask |= GCStipple;
3387 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3389 else
3390 XChangeGC (dpy, relief->gc, mask, &xgcv);
3394 /* Set up colors for the relief lines around glyph string S. */
3396 static void
3397 x_setup_relief_colors (s)
3398 struct glyph_string *s;
3400 struct x_output *di = s->f->output_data.x;
3401 unsigned long color;
3403 if (s->face->use_box_color_for_shadows_p)
3404 color = s->face->box_color;
3405 else
3407 XGCValues xgcv;
3409 /* Get the background color of the face. */
3410 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3411 color = xgcv.background;
3414 if (di->white_relief.gc == 0
3415 || color != di->relief_background)
3417 di->relief_background = color;
3418 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3419 WHITE_PIX_DEFAULT (s->f));
3420 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3421 BLACK_PIX_DEFAULT (s->f));
3426 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3427 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3428 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3429 relief. LEFT_P non-zero means draw a relief on the left side of
3430 the rectangle. RIGHT_P non-zero means draw a relief on the right
3431 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3432 when drawing. */
3434 static void
3435 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3436 raised_p, left_p, right_p, clip_rect)
3437 struct frame *f;
3438 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3439 XRectangle *clip_rect;
3441 int i;
3442 GC gc;
3444 if (raised_p)
3445 gc = f->output_data.x->white_relief.gc;
3446 else
3447 gc = f->output_data.x->black_relief.gc;
3448 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3450 /* Top. */
3451 for (i = 0; i < width; ++i)
3452 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3453 left_x + i * left_p, top_y + i,
3454 right_x + 1 - i * right_p, top_y + i);
3456 /* Left. */
3457 if (left_p)
3458 for (i = 0; i < width; ++i)
3459 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3460 left_x + i, top_y + i, left_x + i, bottom_y - i);
3462 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3463 if (raised_p)
3464 gc = f->output_data.x->black_relief.gc;
3465 else
3466 gc = f->output_data.x->white_relief.gc;
3467 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3469 /* Bottom. */
3470 for (i = 0; i < width; ++i)
3471 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3472 left_x + i * left_p, bottom_y - i,
3473 right_x + 1 - i * right_p, bottom_y - i);
3475 /* Right. */
3476 if (right_p)
3477 for (i = 0; i < width; ++i)
3478 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3479 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3481 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3485 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3486 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3487 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3488 left side of the rectangle. RIGHT_P non-zero means draw a line
3489 on the right side of the rectangle. CLIP_RECT is the clipping
3490 rectangle to use when drawing. */
3492 static void
3493 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3494 left_p, right_p, clip_rect)
3495 struct glyph_string *s;
3496 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3497 XRectangle *clip_rect;
3499 XGCValues xgcv;
3501 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3502 XSetForeground (s->display, s->gc, s->face->box_color);
3503 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3505 /* Top. */
3506 XFillRectangle (s->display, s->window, s->gc,
3507 left_x, top_y, right_x - left_x, width);
3509 /* Left. */
3510 if (left_p)
3511 XFillRectangle (s->display, s->window, s->gc,
3512 left_x, top_y, width, bottom_y - top_y);
3514 /* Bottom. */
3515 XFillRectangle (s->display, s->window, s->gc,
3516 left_x, bottom_y - width, right_x - left_x, width);
3518 /* Right. */
3519 if (right_p)
3520 XFillRectangle (s->display, s->window, s->gc,
3521 right_x - width, top_y, width, bottom_y - top_y);
3523 XSetForeground (s->display, s->gc, xgcv.foreground);
3524 XSetClipMask (s->display, s->gc, None);
3528 /* Draw a box around glyph string S. */
3530 static void
3531 x_draw_glyph_string_box (s)
3532 struct glyph_string *s;
3534 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3535 int left_p, right_p;
3536 struct glyph *last_glyph;
3537 XRectangle clip_rect;
3539 last_x = window_box_right (s->w, s->area);
3540 if (s->row->full_width_p
3541 && !s->w->pseudo_window_p)
3543 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3544 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3545 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3548 /* The glyph that may have a right box line. */
3549 last_glyph = (s->cmp || s->img
3550 ? s->first_glyph
3551 : s->first_glyph + s->nchars - 1);
3553 width = s->face->box_line_width;
3554 raised_p = s->face->box == FACE_RAISED_BOX;
3555 left_x = s->x;
3556 right_x = ((s->row->full_width_p
3557 ? last_x - 1
3558 : min (last_x, s->x + s->background_width) - 1));
3559 top_y = s->y;
3560 bottom_y = top_y + s->height - 1;
3562 left_p = (s->first_glyph->left_box_line_p
3563 || (s->hl == DRAW_MOUSE_FACE
3564 && (s->prev == NULL
3565 || s->prev->hl != s->hl)));
3566 right_p = (last_glyph->right_box_line_p
3567 || (s->hl == DRAW_MOUSE_FACE
3568 && (s->next == NULL
3569 || s->next->hl != s->hl)));
3571 x_get_glyph_string_clip_rect (s, &clip_rect);
3573 if (s->face->box == FACE_SIMPLE_BOX)
3574 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3575 left_p, right_p, &clip_rect);
3576 else
3578 x_setup_relief_colors (s);
3579 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3580 width, raised_p, left_p, right_p, &clip_rect);
3585 /* Draw foreground of image glyph string S. */
3587 static void
3588 x_draw_image_foreground (s)
3589 struct glyph_string *s;
3591 int x;
3592 int y = s->ybase - IMAGE_ASCENT (s->img);
3594 /* If first glyph of S has a left box line, start drawing it to the
3595 right of that line. */
3596 if (s->face->box != FACE_NO_BOX
3597 && s->first_glyph->left_box_line_p)
3598 x = s->x + s->face->box_line_width;
3599 else
3600 x = s->x;
3602 /* If there is a margin around the image, adjust x- and y-position
3603 by that margin. */
3604 if (s->img->margin)
3606 x += s->img->margin;
3607 y += s->img->margin;
3610 if (s->img->pixmap)
3612 if (s->img->mask)
3614 /* We can't set both a clip mask and use XSetClipRectangles
3615 because the latter also sets a clip mask. We also can't
3616 trust on the shape extension to be available
3617 (XShapeCombineRegion). So, compute the rectangle to draw
3618 manually. */
3619 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3620 | GCFunction);
3621 XGCValues xgcv;
3622 XRectangle clip_rect, image_rect, r;
3624 xgcv.clip_mask = s->img->mask;
3625 xgcv.clip_x_origin = x;
3626 xgcv.clip_y_origin = y;
3627 xgcv.function = GXcopy;
3628 XChangeGC (s->display, s->gc, mask, &xgcv);
3630 x_get_glyph_string_clip_rect (s, &clip_rect);
3631 image_rect.x = x;
3632 image_rect.y = y;
3633 image_rect.width = s->img->width;
3634 image_rect.height = s->img->height;
3635 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3636 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3637 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3639 else
3641 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3642 0, 0, s->img->width, s->img->height, x, y);
3644 /* When the image has a mask, we can expect that at
3645 least part of a mouse highlight or a block cursor will
3646 be visible. If the image doesn't have a mask, make
3647 a block cursor visible by drawing a rectangle around
3648 the image. I believe it's looking better if we do
3649 nothing here for mouse-face. */
3650 if (s->hl == DRAW_CURSOR)
3651 XDrawRectangle (s->display, s->window, s->gc, x, y,
3652 s->img->width - 1, s->img->height - 1);
3655 else
3656 /* Draw a rectangle if image could not be loaded. */
3657 XDrawRectangle (s->display, s->window, s->gc, x, y,
3658 s->img->width - 1, s->img->height - 1);
3662 /* Draw a relief around the image glyph string S. */
3664 static void
3665 x_draw_image_relief (s)
3666 struct glyph_string *s;
3668 int x0, y0, x1, y1, thick, raised_p;
3669 XRectangle r;
3670 int x;
3671 int y = s->ybase - IMAGE_ASCENT (s->img);
3673 /* If first glyph of S has a left box line, start drawing it to the
3674 right of that line. */
3675 if (s->face->box != FACE_NO_BOX
3676 && s->first_glyph->left_box_line_p)
3677 x = s->x + s->face->box_line_width;
3678 else
3679 x = s->x;
3681 /* If there is a margin around the image, adjust x- and y-position
3682 by that margin. */
3683 if (s->img->margin)
3685 x += s->img->margin;
3686 y += s->img->margin;
3689 if (s->hl == DRAW_IMAGE_SUNKEN
3690 || s->hl == DRAW_IMAGE_RAISED)
3692 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3693 raised_p = s->hl == DRAW_IMAGE_RAISED;
3695 else
3697 thick = abs (s->img->relief);
3698 raised_p = s->img->relief > 0;
3701 x0 = x - thick;
3702 y0 = y - thick;
3703 x1 = x + s->img->width + thick - 1;
3704 y1 = y + s->img->height + thick - 1;
3706 x_setup_relief_colors (s);
3707 x_get_glyph_string_clip_rect (s, &r);
3708 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3712 /* Draw the foreground of image glyph string S to PIXMAP. */
3714 static void
3715 x_draw_image_foreground_1 (s, pixmap)
3716 struct glyph_string *s;
3717 Pixmap pixmap;
3719 int x;
3720 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3722 /* If first glyph of S has a left box line, start drawing it to the
3723 right of that line. */
3724 if (s->face->box != FACE_NO_BOX
3725 && s->first_glyph->left_box_line_p)
3726 x = s->face->box_line_width;
3727 else
3728 x = 0;
3730 /* If there is a margin around the image, adjust x- and y-position
3731 by that margin. */
3732 if (s->img->margin)
3734 x += s->img->margin;
3735 y += s->img->margin;
3738 if (s->img->pixmap)
3740 if (s->img->mask)
3742 /* We can't set both a clip mask and use XSetClipRectangles
3743 because the latter also sets a clip mask. We also can't
3744 trust on the shape extension to be available
3745 (XShapeCombineRegion). So, compute the rectangle to draw
3746 manually. */
3747 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3748 | GCFunction);
3749 XGCValues xgcv;
3751 xgcv.clip_mask = s->img->mask;
3752 xgcv.clip_x_origin = x;
3753 xgcv.clip_y_origin = y;
3754 xgcv.function = GXcopy;
3755 XChangeGC (s->display, s->gc, mask, &xgcv);
3757 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3758 0, 0, s->img->width, s->img->height, x, y);
3759 XSetClipMask (s->display, s->gc, None);
3761 else
3763 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3764 0, 0, s->img->width, s->img->height, x, y);
3766 /* When the image has a mask, we can expect that at
3767 least part of a mouse highlight or a block cursor will
3768 be visible. If the image doesn't have a mask, make
3769 a block cursor visible by drawing a rectangle around
3770 the image. I believe it's looking better if we do
3771 nothing here for mouse-face. */
3772 if (s->hl == DRAW_CURSOR)
3773 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3774 s->img->width - 1, s->img->height - 1);
3777 else
3778 /* Draw a rectangle if image could not be loaded. */
3779 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3780 s->img->width - 1, s->img->height - 1);
3784 /* Draw part of the background of glyph string S. X, Y, W, and H
3785 give the rectangle to draw. */
3787 static void
3788 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3789 struct glyph_string *s;
3790 int x, y, w, h;
3792 if (s->stippled_p)
3794 /* Fill background with a stipple pattern. */
3795 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3796 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3797 XSetFillStyle (s->display, s->gc, FillSolid);
3799 else
3800 x_clear_glyph_string_rect (s, x, y, w, h);
3804 /* Draw image glyph string S.
3806 s->y
3807 s->x +-------------------------
3808 | s->face->box
3810 | +-------------------------
3811 | | s->img->margin
3813 | | +-------------------
3814 | | | the image
3818 static void
3819 x_draw_image_glyph_string (s)
3820 struct glyph_string *s;
3822 int x, y;
3823 int box_line_width = s->face->box_line_width;
3824 int margin = s->img->margin;
3825 int height;
3826 Pixmap pixmap = None;
3828 height = s->height - 2 * box_line_width;
3830 /* Fill background with face under the image. Do it only if row is
3831 taller than image or if image has a clip mask to reduce
3832 flickering. */
3833 s->stippled_p = s->face->stipple != 0;
3834 if (height > s->img->height
3835 || margin
3836 || s->img->mask
3837 || s->img->pixmap == 0
3838 || s->width != s->background_width)
3840 if (box_line_width && s->first_glyph->left_box_line_p)
3841 x = s->x + box_line_width;
3842 else
3843 x = s->x;
3845 y = s->y + box_line_width;
3847 if (s->img->mask)
3849 /* Create a pixmap as large as the glyph string Fill it with
3850 the background color. Copy the image to it, using its
3851 mask. Copy the temporary pixmap to the display. */
3852 Screen *screen = FRAME_X_SCREEN (s->f);
3853 int depth = DefaultDepthOfScreen (screen);
3855 /* Create a pixmap as large as the glyph string. */
3856 pixmap = XCreatePixmap (s->display, s->window,
3857 s->background_width,
3858 s->height, depth);
3860 /* Don't clip in the following because we're working on the
3861 pixmap. */
3862 XSetClipMask (s->display, s->gc, None);
3864 /* Fill the pixmap with the background color/stipple. */
3865 if (s->stippled_p)
3867 /* Fill background with a stipple pattern. */
3868 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3869 XFillRectangle (s->display, pixmap, s->gc,
3870 0, 0, s->background_width, s->height);
3871 XSetFillStyle (s->display, s->gc, FillSolid);
3873 else
3875 XGCValues xgcv;
3876 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3877 &xgcv);
3878 XSetForeground (s->display, s->gc, xgcv.background);
3879 XFillRectangle (s->display, pixmap, s->gc,
3880 0, 0, s->background_width, s->height);
3881 XSetForeground (s->display, s->gc, xgcv.foreground);
3884 else
3885 /* Implementation idea: Is it possible to construct a mask?
3886 We could look at the color at the margins of the image, and
3887 say that this color is probably the background color of the
3888 image. */
3889 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3891 s->background_filled_p = 1;
3894 /* Draw the foreground. */
3895 if (pixmap != None)
3897 x_draw_image_foreground_1 (s, pixmap);
3898 x_set_glyph_string_clipping (s);
3899 XCopyArea (s->display, pixmap, s->window, s->gc,
3900 0, 0, s->background_width, s->height, s->x, s->y);
3901 XFreePixmap (s->display, pixmap);
3903 else
3904 x_draw_image_foreground (s);
3906 /* If we must draw a relief around the image, do it. */
3907 if (s->img->relief
3908 || s->hl == DRAW_IMAGE_RAISED
3909 || s->hl == DRAW_IMAGE_SUNKEN)
3910 x_draw_image_relief (s);
3914 /* Draw stretch glyph string S. */
3916 static void
3917 x_draw_stretch_glyph_string (s)
3918 struct glyph_string *s;
3920 xassert (s->first_glyph->type == STRETCH_GLYPH);
3921 s->stippled_p = s->face->stipple != 0;
3923 if (s->hl == DRAW_CURSOR
3924 && !x_stretch_cursor_p)
3926 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3927 as wide as the stretch glyph. */
3928 int width = min (CANON_X_UNIT (s->f), s->background_width);
3930 /* Draw cursor. */
3931 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3933 /* Clear rest using the GC of the original non-cursor face. */
3934 if (width < s->background_width)
3936 GC gc = s->face->gc;
3937 int x = s->x + width, y = s->y;
3938 int w = s->background_width - width, h = s->height;
3939 XRectangle r;
3941 x_get_glyph_string_clip_rect (s, &r);
3942 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
3944 if (s->face->stipple)
3946 /* Fill background with a stipple pattern. */
3947 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3948 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3949 XSetFillStyle (s->display, gc, FillSolid);
3951 else
3953 XGCValues xgcv;
3954 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3955 XSetForeground (s->display, gc, xgcv.background);
3956 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3957 XSetForeground (s->display, gc, xgcv.foreground);
3961 else
3962 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3963 s->height);
3965 s->background_filled_p = 1;
3969 /* Draw glyph string S. */
3971 static void
3972 x_draw_glyph_string (s)
3973 struct glyph_string *s;
3975 /* If S draws into the background of its successor, draw the
3976 background of the successor first so that S can draw into it.
3977 This makes S->next use XDrawString instead of XDrawImageString. */
3978 if (s->next && s->right_overhang && !s->for_overlaps_p)
3980 xassert (s->next->img == NULL);
3981 x_set_glyph_string_gc (s->next);
3982 x_set_glyph_string_clipping (s->next);
3983 x_draw_glyph_string_background (s->next, 1);
3986 /* Set up S->gc, set clipping and draw S. */
3987 x_set_glyph_string_gc (s);
3988 x_set_glyph_string_clipping (s);
3990 switch (s->first_glyph->type)
3992 case IMAGE_GLYPH:
3993 x_draw_image_glyph_string (s);
3994 break;
3996 case STRETCH_GLYPH:
3997 x_draw_stretch_glyph_string (s);
3998 break;
4000 case CHAR_GLYPH:
4001 if (s->for_overlaps_p)
4002 s->background_filled_p = 1;
4003 else
4004 x_draw_glyph_string_background (s, 0);
4005 x_draw_glyph_string_foreground (s);
4006 break;
4008 case COMPOSITE_GLYPH:
4009 if (s->for_overlaps_p || s->gidx > 0)
4010 s->background_filled_p = 1;
4011 else
4012 x_draw_glyph_string_background (s, 1);
4013 x_draw_composite_glyph_string_foreground (s);
4014 break;
4016 default:
4017 abort ();
4020 if (!s->for_overlaps_p)
4022 /* Draw underline. */
4023 if (s->face->underline_p)
4025 unsigned long dy, h;
4027 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4028 h = 1;
4029 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4030 dy = s->height - h;
4032 if (s->face->underline_defaulted_p)
4033 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4034 s->width, h);
4035 else
4037 XGCValues xgcv;
4038 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4039 XSetForeground (s->display, s->gc, s->face->underline_color);
4040 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4041 s->width, h);
4042 XSetForeground (s->display, s->gc, xgcv.foreground);
4046 /* Draw overline. */
4047 if (s->face->overline_p)
4049 unsigned long dy = 0, h = 1;
4051 if (s->face->overline_color_defaulted_p)
4052 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4053 s->width, h);
4054 else
4056 XGCValues xgcv;
4057 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4058 XSetForeground (s->display, s->gc, s->face->overline_color);
4059 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4060 s->width, h);
4061 XSetForeground (s->display, s->gc, xgcv.foreground);
4065 /* Draw strike-through. */
4066 if (s->face->strike_through_p)
4068 unsigned long h = 1;
4069 unsigned long dy = (s->height - h) / 2;
4071 if (s->face->strike_through_color_defaulted_p)
4072 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4073 s->width, h);
4074 else
4076 XGCValues xgcv;
4077 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4078 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4079 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4080 s->width, h);
4081 XSetForeground (s->display, s->gc, xgcv.foreground);
4085 /* Draw relief. */
4086 if (s->face->box != FACE_NO_BOX)
4087 x_draw_glyph_string_box (s);
4090 /* Reset clipping. */
4091 XSetClipMask (s->display, s->gc, None);
4095 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4096 struct face **, int));
4099 /* Load glyph string S with a composition components specified by S->cmp.
4100 FACES is an array of faces for all components of this composition.
4101 S->gidx is the index of the first component for S.
4102 OVERLAPS_P non-zero means S should draw the foreground only, and
4103 use its lines physical height for clipping.
4105 Value is the index of a component not in S. */
4107 static int
4108 x_fill_composite_glyph_string (s, faces, overlaps_p)
4109 struct glyph_string *s;
4110 struct face **faces;
4111 int overlaps_p;
4113 int i;
4115 xassert (s);
4117 s->for_overlaps_p = overlaps_p;
4119 s->face = faces[s->gidx];
4120 s->font = s->face->font;
4121 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4123 /* For all glyphs of this composition, starting at the offset
4124 S->gidx, until we reach the end of the definition or encounter a
4125 glyph that requires the different face, add it to S. */
4126 ++s->nchars;
4127 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4128 ++s->nchars;
4130 /* All glyph strings for the same composition has the same width,
4131 i.e. the width set for the first component of the composition. */
4133 s->width = s->first_glyph->pixel_width;
4135 /* If the specified font could not be loaded, use the frame's
4136 default font, but record the fact that we couldn't load it in
4137 the glyph string so that we can draw rectangles for the
4138 characters of the glyph string. */
4139 if (s->font == NULL)
4141 s->font_not_found_p = 1;
4142 s->font = FRAME_FONT (s->f);
4145 /* Adjust base line for subscript/superscript text. */
4146 s->ybase += s->first_glyph->voffset;
4148 xassert (s->face && s->face->gc);
4150 /* This glyph string must always be drawn with 16-bit functions. */
4151 s->two_byte_p = 1;
4153 return s->gidx + s->nchars;
4157 /* Load glyph string S with a sequence characters.
4158 FACE_ID is the face id of the string. START is the index of the
4159 first glyph to consider, END is the index of the last + 1.
4160 OVERLAPS_P non-zero means S should draw the foreground only, and
4161 use its lines physical height for clipping.
4163 Value is the index of the first glyph not in S. */
4165 static int
4166 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4167 struct glyph_string *s;
4168 int face_id;
4169 int start, end, overlaps_p;
4171 struct glyph *glyph, *last;
4172 int voffset;
4174 xassert (s->f == XFRAME (s->w->frame));
4175 xassert (s->nchars == 0);
4176 xassert (start >= 0 && end > start);
4178 s->for_overlaps_p = overlaps_p,
4179 glyph = s->row->glyphs[s->area] + start;
4180 last = s->row->glyphs[s->area] + end;
4181 voffset = glyph->voffset;
4183 while (glyph < last
4184 && glyph->type == CHAR_GLYPH
4185 && glyph->voffset == voffset
4186 /* Same face id implies same charset, nowadays. */
4187 && glyph->face_id == face_id)
4189 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4190 s->char2b + s->nchars);
4191 if (s->char2b[s->nchars].byte2 != 0)
4192 s->two_byte_p = 1;
4194 ++s->nchars;
4195 xassert (s->nchars <= end - start);
4196 s->width += glyph->pixel_width;
4197 ++glyph;
4200 s->font = s->face->font;
4201 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4203 /* If the specified font could not be loaded, use the frame's font,
4204 but record the fact that we couldn't load it in
4205 S->font_not_found_p so that we can draw rectangles for the
4206 characters of the glyph string. */
4207 if (s->font == NULL)
4209 s->font_not_found_p = 1;
4210 s->font = FRAME_FONT (s->f);
4213 /* Adjust base line for subscript/superscript text. */
4214 s->ybase += voffset;
4216 xassert (s->face && s->face->gc);
4217 return glyph - s->row->glyphs[s->area];
4221 /* Fill glyph string S from image glyph S->first_glyph. */
4223 static void
4224 x_fill_image_glyph_string (s)
4225 struct glyph_string *s;
4227 xassert (s->first_glyph->type == IMAGE_GLYPH);
4228 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4229 xassert (s->img);
4230 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4231 s->font = s->face->font;
4232 s->width = s->first_glyph->pixel_width;
4234 /* Adjust base line for subscript/superscript text. */
4235 s->ybase += s->first_glyph->voffset;
4239 /* Fill glyph string S from stretch glyph S->first_glyph. */
4241 static void
4242 x_fill_stretch_glyph_string (s)
4243 struct glyph_string *s;
4245 xassert (s->first_glyph->type == STRETCH_GLYPH);
4246 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4247 s->font = s->face->font;
4248 s->width = s->first_glyph->pixel_width;
4250 /* Adjust base line for subscript/superscript text. */
4251 s->ybase += s->first_glyph->voffset;
4255 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4256 of XChar2b structures for S; it can't be allocated in
4257 x_init_glyph_string because it must be allocated via `alloca'. W
4258 is the window on which S is drawn. ROW and AREA are the glyph row
4259 and area within the row from which S is constructed. START is the
4260 index of the first glyph structure covered by S. HL is a
4261 face-override for drawing S. */
4263 static void
4264 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4265 struct glyph_string *s;
4266 XChar2b *char2b;
4267 struct window *w;
4268 struct glyph_row *row;
4269 enum glyph_row_area area;
4270 int start;
4271 enum draw_glyphs_face hl;
4273 bzero (s, sizeof *s);
4274 s->w = w;
4275 s->f = XFRAME (w->frame);
4276 s->display = FRAME_X_DISPLAY (s->f);
4277 s->window = FRAME_X_WINDOW (s->f);
4278 s->char2b = char2b;
4279 s->hl = hl;
4280 s->row = row;
4281 s->area = area;
4282 s->first_glyph = row->glyphs[area] + start;
4283 s->height = row->height;
4284 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4286 /* Display the internal border below the tool-bar window. */
4287 if (s->w == XWINDOW (s->f->tool_bar_window))
4288 s->y -= s->f->output_data.x->internal_border_width;
4290 s->ybase = s->y + row->ascent;
4294 /* Set background width of glyph string S. START is the index of the
4295 first glyph following S. LAST_X is the right-most x-position + 1
4296 in the drawing area. */
4298 static INLINE void
4299 x_set_glyph_string_background_width (s, start, last_x)
4300 struct glyph_string *s;
4301 int start;
4302 int last_x;
4304 /* If the face of this glyph string has to be drawn to the end of
4305 the drawing area, set S->extends_to_end_of_line_p. */
4306 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4308 if (start == s->row->used[s->area]
4309 && s->hl == DRAW_NORMAL_TEXT
4310 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4311 || s->face->background != default_face->background
4312 || s->face->stipple != default_face->stipple))
4313 s->extends_to_end_of_line_p = 1;
4315 /* If S extends its face to the end of the line, set its
4316 background_width to the distance to the right edge of the drawing
4317 area. */
4318 if (s->extends_to_end_of_line_p)
4319 s->background_width = last_x - s->x + 1;
4320 else
4321 s->background_width = s->width;
4325 /* Add a glyph string for a stretch glyph to the list of strings
4326 between HEAD and TAIL. START is the index of the stretch glyph in
4327 row area AREA of glyph row ROW. END is the index of the last glyph
4328 in that glyph row area. X is the current output position assigned
4329 to the new glyph string constructed. HL overrides that face of the
4330 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4331 is the right-most x-position of the drawing area. */
4333 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4334 and below -- keep them on one line. */
4335 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4336 do \
4338 s = (struct glyph_string *) alloca (sizeof *s); \
4339 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4340 x_fill_stretch_glyph_string (s); \
4341 x_append_glyph_string (&HEAD, &TAIL, s); \
4342 ++START; \
4343 s->x = (X); \
4345 while (0)
4348 /* Add a glyph string for an image glyph to the list of strings
4349 between HEAD and TAIL. START is the index of the image glyph in
4350 row area AREA of glyph row ROW. END is the index of the last glyph
4351 in that glyph row area. X is the current output position assigned
4352 to the new glyph string constructed. HL overrides that face of the
4353 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4354 is the right-most x-position of the drawing area. */
4356 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4357 do \
4359 s = (struct glyph_string *) alloca (sizeof *s); \
4360 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4361 x_fill_image_glyph_string (s); \
4362 x_append_glyph_string (&HEAD, &TAIL, s); \
4363 ++START; \
4364 s->x = (X); \
4366 while (0)
4369 /* Add a glyph string for a sequence of character glyphs to the list
4370 of strings between HEAD and TAIL. START is the index of the first
4371 glyph in row area AREA of glyph row ROW that is part of the new
4372 glyph string. END is the index of the last glyph in that glyph row
4373 area. X is the current output position assigned to the new glyph
4374 string constructed. HL overrides that face of the glyph; e.g. it
4375 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4376 right-most x-position of the drawing area. */
4378 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4379 do \
4381 int c, charset, face_id; \
4382 XChar2b *char2b; \
4384 c = (ROW)->glyphs[AREA][START].u.ch; \
4385 charset = CHAR_CHARSET (c); \
4386 face_id = (ROW)->glyphs[AREA][START].face_id; \
4388 s = (struct glyph_string *) alloca (sizeof *s); \
4389 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4390 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4391 x_append_glyph_string (&HEAD, &TAIL, s); \
4392 s->charset = charset; \
4393 s->x = (X); \
4394 START = x_fill_glyph_string (s, face_id, START, END, \
4395 OVERLAPS_P); \
4397 while (0)
4400 /* Add a glyph string for a composite sequence to the list of strings
4401 between HEAD and TAIL. START is the index of the first glyph in
4402 row area AREA of glyph row ROW that is part of the new glyph
4403 string. END is the index of the last glyph in that glyph row area.
4404 X is the current output position assigned to the new glyph string
4405 constructed. HL overrides that face of the glyph; e.g. it is
4406 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4407 x-position of the drawing area. */
4409 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4410 do { \
4411 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4412 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4413 struct composition *cmp = composition_table[cmp_id]; \
4414 int glyph_len = cmp->glyph_len; \
4415 XChar2b *char2b; \
4416 struct face **faces; \
4417 struct glyph_string *first_s = NULL; \
4418 int n; \
4420 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4421 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4422 /* At first, fill in `char2b' and `faces'. */ \
4423 for (n = 0; n < glyph_len; n++) \
4425 int c = COMPOSITION_GLYPH (cmp, n); \
4426 faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4427 face_id, char2b + n, 1); \
4430 /* Make glyph_strings for each glyph sequence that is drawable by \
4431 the same face, and append them to HEAD/TAIL. */ \
4432 for (n = 0; n < cmp->glyph_len;) \
4434 s = (struct glyph_string *) alloca (sizeof *s); \
4435 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4436 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4437 s->cmp = cmp; \
4438 s->gidx = n; \
4439 s->charset = 0; \
4440 s->x = (X); \
4442 if (n == 0) \
4443 first_s = s; \
4445 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4448 ++START; \
4449 s = first_s; \
4450 } while (0)
4453 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4454 of AREA of glyph row ROW on window W between indices START and END.
4455 HL overrides the face for drawing glyph strings, e.g. it is
4456 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4457 x-positions of the drawing area.
4459 This is an ugly monster macro construct because we must use alloca
4460 to allocate glyph strings (because x_draw_glyphs can be called
4461 asynchronously). */
4463 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4464 do \
4466 HEAD = TAIL = NULL; \
4467 while (START < END) \
4469 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4470 switch (first_glyph->type) \
4472 case CHAR_GLYPH: \
4473 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4474 TAIL, HL, X, LAST_X, \
4475 OVERLAPS_P); \
4476 break; \
4478 case COMPOSITE_GLYPH: \
4479 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4480 HEAD, TAIL, HL, X, LAST_X,\
4481 OVERLAPS_P); \
4482 break; \
4484 case STRETCH_GLYPH: \
4485 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4486 HEAD, TAIL, HL, X, LAST_X); \
4487 break; \
4489 case IMAGE_GLYPH: \
4490 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4491 TAIL, HL, X, LAST_X); \
4492 break; \
4494 default: \
4495 abort (); \
4498 x_set_glyph_string_background_width (s, START, LAST_X); \
4499 (X) += s->width; \
4502 while (0)
4505 /* Draw glyphs between START and END in AREA of ROW on window W,
4506 starting at x-position X. X is relative to AREA in W. HL is a
4507 face-override with the following meaning:
4509 DRAW_NORMAL_TEXT draw normally
4510 DRAW_CURSOR draw in cursor face
4511 DRAW_MOUSE_FACE draw in mouse face.
4512 DRAW_INVERSE_VIDEO draw in mode line face
4513 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4514 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4516 If REAL_START is non-null, return in *REAL_START the real starting
4517 position for display. This can be different from START in case
4518 overlapping glyphs must be displayed. If REAL_END is non-null,
4519 return in *REAL_END the real end position for display. This can be
4520 different from END in case overlapping glyphs must be displayed.
4522 If OVERLAPS_P is non-zero, draw only the foreground of characters
4523 and clip to the physical height of ROW.
4525 Value is the x-position reached, relative to AREA of W. */
4527 static int
4528 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4529 overlaps_p)
4530 struct window *w;
4531 int x;
4532 struct glyph_row *row;
4533 enum glyph_row_area area;
4534 int start, end;
4535 enum draw_glyphs_face hl;
4536 int *real_start, *real_end;
4537 int overlaps_p;
4539 struct glyph_string *head, *tail;
4540 struct glyph_string *s;
4541 int last_x, area_width;
4542 int x_reached;
4543 int i, j;
4545 /* Let's rather be paranoid than getting a SEGV. */
4546 start = max (0, start);
4547 end = min (end, row->used[area]);
4548 if (real_start)
4549 *real_start = start;
4550 if (real_end)
4551 *real_end = end;
4553 /* Translate X to frame coordinates. Set last_x to the right
4554 end of the drawing area. */
4555 if (row->full_width_p)
4557 /* X is relative to the left edge of W, without scroll bars
4558 or flag areas. */
4559 struct frame *f = XFRAME (w->frame);
4560 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4561 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4563 x += window_left_x;
4564 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4565 last_x = window_left_x + area_width;
4567 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4569 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4570 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4571 last_x += width;
4572 else
4573 x -= width;
4576 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4577 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4579 else
4581 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4582 area_width = window_box_width (w, area);
4583 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4586 /* Build a doubly-linked list of glyph_string structures between
4587 head and tail from what we have to draw. Note that the macro
4588 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4589 the reason we use a separate variable `i'. */
4590 i = start;
4591 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4592 overlaps_p);
4593 if (tail)
4594 x_reached = tail->x + tail->background_width;
4595 else
4596 x_reached = x;
4598 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4599 the row, redraw some glyphs in front or following the glyph
4600 strings built above. */
4601 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4603 int dummy_x = 0;
4604 struct glyph_string *h, *t;
4606 /* Compute overhangs for all glyph strings. */
4607 for (s = head; s; s = s->next)
4608 x_compute_glyph_string_overhangs (s);
4610 /* Prepend glyph strings for glyphs in front of the first glyph
4611 string that are overwritten because of the first glyph
4612 string's left overhang. The background of all strings
4613 prepended must be drawn because the first glyph string
4614 draws over it. */
4615 i = x_left_overwritten (head);
4616 if (i >= 0)
4618 j = i;
4619 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4620 DRAW_NORMAL_TEXT, dummy_x, last_x,
4621 overlaps_p);
4622 start = i;
4623 if (real_start)
4624 *real_start = start;
4625 x_compute_overhangs_and_x (t, head->x, 1);
4626 x_prepend_glyph_string_lists (&head, &tail, h, t);
4629 /* Prepend glyph strings for glyphs in front of the first glyph
4630 string that overwrite that glyph string because of their
4631 right overhang. For these strings, only the foreground must
4632 be drawn, because it draws over the glyph string at `head'.
4633 The background must not be drawn because this would overwrite
4634 right overhangs of preceding glyphs for which no glyph
4635 strings exist. */
4636 i = x_left_overwriting (head);
4637 if (i >= 0)
4639 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4640 DRAW_NORMAL_TEXT, dummy_x, last_x,
4641 overlaps_p);
4642 for (s = h; s; s = s->next)
4643 s->background_filled_p = 1;
4644 if (real_start)
4645 *real_start = i;
4646 x_compute_overhangs_and_x (t, head->x, 1);
4647 x_prepend_glyph_string_lists (&head, &tail, h, t);
4650 /* Append glyphs strings for glyphs following the last glyph
4651 string tail that are overwritten by tail. The background of
4652 these strings has to be drawn because tail's foreground draws
4653 over it. */
4654 i = x_right_overwritten (tail);
4655 if (i >= 0)
4657 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4658 DRAW_NORMAL_TEXT, x, last_x,
4659 overlaps_p);
4660 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4661 x_append_glyph_string_lists (&head, &tail, h, t);
4662 if (real_end)
4663 *real_end = i;
4666 /* Append glyph strings for glyphs following the last glyph
4667 string tail that overwrite tail. The foreground of such
4668 glyphs has to be drawn because it writes into the background
4669 of tail. The background must not be drawn because it could
4670 paint over the foreground of following glyphs. */
4671 i = x_right_overwriting (tail);
4672 if (i >= 0)
4674 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4675 DRAW_NORMAL_TEXT, x, last_x,
4676 overlaps_p);
4677 for (s = h; s; s = s->next)
4678 s->background_filled_p = 1;
4679 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4680 x_append_glyph_string_lists (&head, &tail, h, t);
4681 if (real_end)
4682 *real_end = i;
4686 /* Draw all strings. */
4687 for (s = head; s; s = s->next)
4688 x_draw_glyph_string (s);
4690 /* Value is the x-position up to which drawn, relative to AREA of W.
4691 This doesn't include parts drawn because of overhangs. */
4692 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4693 if (!row->full_width_p)
4695 if (area > LEFT_MARGIN_AREA)
4696 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4697 if (area > TEXT_AREA)
4698 x_reached -= window_box_width (w, TEXT_AREA);
4700 return x_reached;
4704 /* Fix the display of area AREA of overlapping row ROW in window W. */
4706 static void
4707 x_fix_overlapping_area (w, row, area)
4708 struct window *w;
4709 struct glyph_row *row;
4710 enum glyph_row_area area;
4712 int i, x;
4714 BLOCK_INPUT;
4716 if (area == LEFT_MARGIN_AREA)
4717 x = 0;
4718 else if (area == TEXT_AREA)
4719 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4720 else
4721 x = (window_box_width (w, LEFT_MARGIN_AREA)
4722 + window_box_width (w, TEXT_AREA));
4724 for (i = 0; i < row->used[area];)
4726 if (row->glyphs[area][i].overlaps_vertically_p)
4728 int start = i, start_x = x;
4732 x += row->glyphs[area][i].pixel_width;
4733 ++i;
4735 while (i < row->used[area]
4736 && row->glyphs[area][i].overlaps_vertically_p);
4738 x_draw_glyphs (w, start_x, row, area, start, i,
4739 (row->inverse_p
4740 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4741 NULL, NULL, 1);
4743 else
4745 x += row->glyphs[area][i].pixel_width;
4746 ++i;
4750 UNBLOCK_INPUT;
4754 /* Output LEN glyphs starting at START at the nominal cursor position.
4755 Advance the nominal cursor over the text. The global variable
4756 updated_window contains the window being updated, updated_row is
4757 the glyph row being updated, and updated_area is the area of that
4758 row being updated. */
4760 static void
4761 x_write_glyphs (start, len)
4762 struct glyph *start;
4763 int len;
4765 int x, hpos, real_start, real_end;
4767 xassert (updated_window && updated_row);
4768 BLOCK_INPUT;
4770 /* Write glyphs. */
4772 hpos = start - updated_row->glyphs[updated_area];
4773 x = x_draw_glyphs (updated_window, output_cursor.x,
4774 updated_row, updated_area,
4775 hpos, hpos + len,
4776 (updated_row->inverse_p
4777 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4778 &real_start, &real_end, 0);
4780 /* If we drew over the cursor, note that it is not visible any more. */
4781 note_overwritten_text_cursor (updated_window, real_start,
4782 real_end - real_start);
4784 UNBLOCK_INPUT;
4786 /* Advance the output cursor. */
4787 output_cursor.hpos += len;
4788 output_cursor.x = x;
4792 /* Insert LEN glyphs from START at the nominal cursor position. */
4794 static void
4795 x_insert_glyphs (start, len)
4796 struct glyph *start;
4797 register int len;
4799 struct frame *f;
4800 struct window *w;
4801 int line_height, shift_by_width, shifted_region_width;
4802 struct glyph_row *row;
4803 struct glyph *glyph;
4804 int frame_x, frame_y, hpos, real_start, real_end;
4806 xassert (updated_window && updated_row);
4807 BLOCK_INPUT;
4808 w = updated_window;
4809 f = XFRAME (WINDOW_FRAME (w));
4811 /* Get the height of the line we are in. */
4812 row = updated_row;
4813 line_height = row->height;
4815 /* Get the width of the glyphs to insert. */
4816 shift_by_width = 0;
4817 for (glyph = start; glyph < start + len; ++glyph)
4818 shift_by_width += glyph->pixel_width;
4820 /* Get the width of the region to shift right. */
4821 shifted_region_width = (window_box_width (w, updated_area)
4822 - output_cursor.x
4823 - shift_by_width);
4825 /* Shift right. */
4826 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4827 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4828 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4829 f->output_data.x->normal_gc,
4830 frame_x, frame_y,
4831 shifted_region_width, line_height,
4832 frame_x + shift_by_width, frame_y);
4834 /* Write the glyphs. */
4835 hpos = start - row->glyphs[updated_area];
4836 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4837 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4838 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4840 /* Advance the output cursor. */
4841 output_cursor.hpos += len;
4842 output_cursor.x += shift_by_width;
4843 UNBLOCK_INPUT;
4847 /* Delete N glyphs at the nominal cursor position. Not implemented
4848 for X frames. */
4850 static void
4851 x_delete_glyphs (n)
4852 register int n;
4854 abort ();
4858 /* Erase the current text line from the nominal cursor position
4859 (inclusive) to pixel column TO_X (exclusive). The idea is that
4860 everything from TO_X onward is already erased.
4862 TO_X is a pixel position relative to updated_area of
4863 updated_window. TO_X == -1 means clear to the end of this area. */
4865 static void
4866 x_clear_end_of_line (to_x)
4867 int to_x;
4869 struct frame *f;
4870 struct window *w = updated_window;
4871 int max_x, min_y, max_y;
4872 int from_x, from_y, to_y;
4874 xassert (updated_window && updated_row);
4875 f = XFRAME (w->frame);
4877 if (updated_row->full_width_p)
4879 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4880 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4881 && !w->pseudo_window_p)
4882 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4884 else
4885 max_x = window_box_width (w, updated_area);
4886 max_y = window_text_bottom_y (w);
4888 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4889 of window. For TO_X > 0, truncate to end of drawing area. */
4890 if (to_x == 0)
4891 return;
4892 else if (to_x < 0)
4893 to_x = max_x;
4894 else
4895 to_x = min (to_x, max_x);
4897 to_y = min (max_y, output_cursor.y + updated_row->height);
4899 /* Notice if the cursor will be cleared by this operation. */
4900 if (!updated_row->full_width_p)
4901 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4903 from_x = output_cursor.x;
4905 /* Translate to frame coordinates. */
4906 if (updated_row->full_width_p)
4908 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4909 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4911 else
4913 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4914 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4917 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4918 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4919 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4921 /* Prevent inadvertently clearing to end of the X window. */
4922 if (to_x > from_x && to_y > from_y)
4924 BLOCK_INPUT;
4925 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4926 from_x, from_y, to_x - from_x, to_y - from_y,
4927 False);
4928 UNBLOCK_INPUT;
4933 /* Clear entire frame. If updating_frame is non-null, clear that
4934 frame. Otherwise clear the selected frame. */
4936 static void
4937 x_clear_frame ()
4939 struct frame *f;
4941 if (updating_frame)
4942 f = updating_frame;
4943 else
4944 f = SELECTED_FRAME ();
4946 /* Clearing the frame will erase any cursor, so mark them all as no
4947 longer visible. */
4948 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4949 output_cursor.hpos = output_cursor.vpos = 0;
4950 output_cursor.x = -1;
4952 /* We don't set the output cursor here because there will always
4953 follow an explicit cursor_to. */
4954 BLOCK_INPUT;
4955 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4957 /* We have to clear the scroll bars, too. If we have changed
4958 colors or something like that, then they should be notified. */
4959 x_scroll_bar_clear (f);
4961 XFlush (FRAME_X_DISPLAY (f));
4962 UNBLOCK_INPUT;
4967 /* Invert the middle quarter of the frame for .15 sec. */
4969 /* We use the select system call to do the waiting, so we have to make
4970 sure it's available. If it isn't, we just won't do visual bells. */
4972 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4975 /* Subtract the `struct timeval' values X and Y, storing the result in
4976 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4978 static int
4979 timeval_subtract (result, x, y)
4980 struct timeval *result, x, y;
4982 /* Perform the carry for the later subtraction by updating y. This
4983 is safer because on some systems the tv_sec member is unsigned. */
4984 if (x.tv_usec < y.tv_usec)
4986 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4987 y.tv_usec -= 1000000 * nsec;
4988 y.tv_sec += nsec;
4991 if (x.tv_usec - y.tv_usec > 1000000)
4993 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4994 y.tv_usec += 1000000 * nsec;
4995 y.tv_sec -= nsec;
4998 /* Compute the time remaining to wait. tv_usec is certainly
4999 positive. */
5000 result->tv_sec = x.tv_sec - y.tv_sec;
5001 result->tv_usec = x.tv_usec - y.tv_usec;
5003 /* Return indication of whether the result should be considered
5004 negative. */
5005 return x.tv_sec < y.tv_sec;
5008 void
5009 XTflash (f)
5010 struct frame *f;
5012 BLOCK_INPUT;
5015 GC gc;
5017 /* Create a GC that will use the GXxor function to flip foreground
5018 pixels into background pixels. */
5020 XGCValues values;
5022 values.function = GXxor;
5023 values.foreground = (f->output_data.x->foreground_pixel
5024 ^ f->output_data.x->background_pixel);
5026 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5027 GCFunction | GCForeground, &values);
5031 /* Get the height not including a menu bar widget. */
5032 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5033 /* Height of each line to flash. */
5034 int flash_height = FRAME_LINE_HEIGHT (f);
5035 /* These will be the left and right margins of the rectangles. */
5036 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5037 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5039 int width;
5041 /* Don't flash the area between a scroll bar and the frame
5042 edge it is next to. */
5043 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5045 case vertical_scroll_bar_left:
5046 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5047 break;
5049 case vertical_scroll_bar_right:
5050 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5051 break;
5053 default:
5054 break;
5057 width = flash_right - flash_left;
5059 /* If window is tall, flash top and bottom line. */
5060 if (height > 3 * FRAME_LINE_HEIGHT (f))
5062 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5063 flash_left,
5064 (FRAME_INTERNAL_BORDER_WIDTH (f)
5065 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5066 width, flash_height);
5067 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5068 flash_left,
5069 (height - flash_height
5070 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5071 width, flash_height);
5073 else
5074 /* If it is short, flash it all. */
5075 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5076 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5077 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5079 x_flush (f);
5082 struct timeval wakeup;
5084 EMACS_GET_TIME (wakeup);
5086 /* Compute time to wait until, propagating carry from usecs. */
5087 wakeup.tv_usec += 150000;
5088 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5089 wakeup.tv_usec %= 1000000;
5091 /* Keep waiting until past the time wakeup. */
5092 while (1)
5094 struct timeval timeout;
5096 EMACS_GET_TIME (timeout);
5098 /* In effect, timeout = wakeup - timeout.
5099 Break if result would be negative. */
5100 if (timeval_subtract (&timeout, wakeup, timeout))
5101 break;
5103 /* Try to wait that long--but we might wake up sooner. */
5104 select (0, NULL, NULL, NULL, &timeout);
5108 /* If window is tall, flash top and bottom line. */
5109 if (height > 3 * FRAME_LINE_HEIGHT (f))
5111 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5112 flash_left,
5113 (FRAME_INTERNAL_BORDER_WIDTH (f)
5114 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5115 width, flash_height);
5116 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5117 flash_left,
5118 (height - flash_height
5119 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5120 width, flash_height);
5122 else
5123 /* If it is short, flash it all. */
5124 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5125 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5126 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5128 XFreeGC (FRAME_X_DISPLAY (f), gc);
5129 x_flush (f);
5133 UNBLOCK_INPUT;
5136 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5139 /* Make audible bell. */
5141 void
5142 XTring_bell ()
5144 struct frame *f = SELECTED_FRAME ();
5146 if (FRAME_X_DISPLAY (f))
5148 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5149 if (visible_bell)
5150 XTflash (f);
5151 else
5152 #endif
5154 BLOCK_INPUT;
5155 XBell (FRAME_X_DISPLAY (f), 0);
5156 XFlush (FRAME_X_DISPLAY (f));
5157 UNBLOCK_INPUT;
5163 /* Specify how many text lines, from the top of the window,
5164 should be affected by insert-lines and delete-lines operations.
5165 This, and those operations, are used only within an update
5166 that is bounded by calls to x_update_begin and x_update_end. */
5168 static void
5169 XTset_terminal_window (n)
5170 register int n;
5172 /* This function intentionally left blank. */
5177 /***********************************************************************
5178 Line Dance
5179 ***********************************************************************/
5181 /* Perform an insert-lines or delete-lines operation, inserting N
5182 lines or deleting -N lines at vertical position VPOS. */
5184 static void
5185 x_ins_del_lines (vpos, n)
5186 int vpos, n;
5188 abort ();
5192 /* Scroll part of the display as described by RUN. */
5194 static void
5195 x_scroll_run (w, run)
5196 struct window *w;
5197 struct run *run;
5199 struct frame *f = XFRAME (w->frame);
5200 int x, y, width, height, from_y, to_y, bottom_y;
5202 /* Get frame-relative bounding box of the text display area of W,
5203 without mode lines. Include in this box the flags areas to the
5204 left and right of W. */
5205 window_box (w, -1, &x, &y, &width, &height);
5206 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5207 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5209 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5210 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5211 bottom_y = y + height;
5213 if (to_y < from_y)
5215 /* Scrolling up. Make sure we don't copy part of the mode
5216 line at the bottom. */
5217 if (from_y + run->height > bottom_y)
5218 height = bottom_y - from_y;
5219 else
5220 height = run->height;
5222 else
5224 /* Scolling down. Make sure we don't copy over the mode line.
5225 at the bottom. */
5226 if (to_y + run->height > bottom_y)
5227 height = bottom_y - to_y;
5228 else
5229 height = run->height;
5232 BLOCK_INPUT;
5234 /* Cursor off. Will be switched on again in x_update_window_end. */
5235 updated_window = w;
5236 x_clear_cursor (w);
5238 XCopyArea (FRAME_X_DISPLAY (f),
5239 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5240 f->output_data.x->normal_gc,
5241 x, from_y,
5242 width, height,
5243 x, to_y);
5245 UNBLOCK_INPUT;
5250 /***********************************************************************
5251 Exposure Events
5252 ***********************************************************************/
5254 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5255 corner of the exposed rectangle. W and H are width and height of
5256 the exposed area. All are pixel values. W or H zero means redraw
5257 the entire frame. */
5259 static void
5260 expose_frame (f, x, y, w, h)
5261 struct frame *f;
5262 int x, y, w, h;
5264 XRectangle r;
5266 TRACE ((stderr, "expose_frame "));
5268 /* No need to redraw if frame will be redrawn soon. */
5269 if (FRAME_GARBAGED_P (f))
5271 TRACE ((stderr, " garbaged\n"));
5272 return;
5275 /* If basic faces haven't been realized yet, there is no point in
5276 trying to redraw anything. This can happen when we get an expose
5277 event while Emacs is starting, e.g. by moving another window. */
5278 if (FRAME_FACE_CACHE (f) == NULL
5279 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5281 TRACE ((stderr, " no faces\n"));
5282 return;
5285 if (w == 0 || h == 0)
5287 r.x = r.y = 0;
5288 r.width = CANON_X_UNIT (f) * f->width;
5289 r.height = CANON_Y_UNIT (f) * f->height;
5291 else
5293 r.x = x;
5294 r.y = y;
5295 r.width = w;
5296 r.height = h;
5299 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5300 expose_window_tree (XWINDOW (f->root_window), &r);
5302 if (WINDOWP (f->tool_bar_window))
5304 struct window *w = XWINDOW (f->tool_bar_window);
5305 XRectangle window_rect;
5306 XRectangle intersection_rect;
5307 int window_x, window_y, window_width, window_height;
5310 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5311 window_rect.x = window_x;
5312 window_rect.y = window_y;
5313 window_rect.width = window_width;
5314 window_rect.height = window_height;
5316 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5317 expose_window (w, &intersection_rect);
5320 #ifndef USE_X_TOOLKIT
5321 if (WINDOWP (f->menu_bar_window))
5323 struct window *w = XWINDOW (f->menu_bar_window);
5324 XRectangle window_rect;
5325 XRectangle intersection_rect;
5326 int window_x, window_y, window_width, window_height;
5329 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5330 window_rect.x = window_x;
5331 window_rect.y = window_y;
5332 window_rect.width = window_width;
5333 window_rect.height = window_height;
5335 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5336 expose_window (w, &intersection_rect);
5338 #endif /* not USE_X_TOOLKIT */
5342 /* Redraw (parts) of all windows in the window tree rooted at W that
5343 intersect R. R contains frame pixel coordinates. */
5345 static void
5346 expose_window_tree (w, r)
5347 struct window *w;
5348 XRectangle *r;
5350 while (w)
5352 if (!NILP (w->hchild))
5353 expose_window_tree (XWINDOW (w->hchild), r);
5354 else if (!NILP (w->vchild))
5355 expose_window_tree (XWINDOW (w->vchild), r);
5356 else
5358 XRectangle window_rect;
5359 XRectangle intersection_rect;
5360 struct frame *f = XFRAME (w->frame);
5361 int window_x, window_y, window_width, window_height;
5363 /* Frame-relative pixel rectangle of W. */
5364 window_box (w, -1, &window_x, &window_y, &window_width,
5365 &window_height);
5366 window_rect.x
5367 = (window_x
5368 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5369 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5370 window_rect.y = window_y;
5371 window_rect.width
5372 = (window_width
5373 + FRAME_X_FLAGS_AREA_WIDTH (f)
5374 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5375 window_rect.height
5376 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5378 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5379 expose_window (w, &intersection_rect);
5382 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5387 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5388 which intersects rectangle R. R is in window-relative coordinates. */
5390 static void
5391 expose_area (w, row, r, area)
5392 struct window *w;
5393 struct glyph_row *row;
5394 XRectangle *r;
5395 enum glyph_row_area area;
5397 int x;
5398 struct glyph *first = row->glyphs[area];
5399 struct glyph *end = row->glyphs[area] + row->used[area];
5400 struct glyph *last;
5401 int first_x;
5403 /* Set x to the window-relative start position for drawing glyphs of
5404 AREA. The first glyph of the text area can be partially visible.
5405 The first glyphs of other areas cannot. */
5406 if (area == LEFT_MARGIN_AREA)
5407 x = 0;
5408 else if (area == TEXT_AREA)
5409 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5410 else
5411 x = (window_box_width (w, LEFT_MARGIN_AREA)
5412 + window_box_width (w, TEXT_AREA));
5414 if (area == TEXT_AREA && row->fill_line_p)
5415 /* If row extends face to end of line write the whole line. */
5416 x_draw_glyphs (w, x, row, area,
5417 0, row->used[area],
5418 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5419 NULL, NULL, 0);
5420 else
5422 /* Find the first glyph that must be redrawn. */
5423 while (first < end
5424 && x + first->pixel_width < r->x)
5426 x += first->pixel_width;
5427 ++first;
5430 /* Find the last one. */
5431 last = first;
5432 first_x = x;
5433 while (last < end
5434 && x < r->x + r->width)
5436 x += last->pixel_width;
5437 ++last;
5440 /* Repaint. */
5441 if (last > first)
5442 x_draw_glyphs (w, first_x, row, area,
5443 first - row->glyphs[area],
5444 last - row->glyphs[area],
5445 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5446 NULL, NULL, 0);
5451 /* Redraw the parts of the glyph row ROW on window W intersecting
5452 rectangle R. R is in window-relative coordinates. */
5454 static void
5455 expose_line (w, row, r)
5456 struct window *w;
5457 struct glyph_row *row;
5458 XRectangle *r;
5460 xassert (row->enabled_p);
5462 if (row->mode_line_p || w->pseudo_window_p)
5463 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5464 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5465 NULL, NULL, 0);
5466 else
5468 if (row->used[LEFT_MARGIN_AREA])
5469 expose_area (w, row, r, LEFT_MARGIN_AREA);
5470 if (row->used[TEXT_AREA])
5471 expose_area (w, row, r, TEXT_AREA);
5472 if (row->used[RIGHT_MARGIN_AREA])
5473 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5474 x_draw_row_bitmaps (w, row);
5479 /* Return non-zero if W's cursor intersects rectangle R. */
5481 static int
5482 x_phys_cursor_in_rect_p (w, r)
5483 struct window *w;
5484 XRectangle *r;
5486 XRectangle cr, result;
5487 struct glyph *cursor_glyph;
5489 cursor_glyph = get_phys_cursor_glyph (w);
5490 if (cursor_glyph)
5492 cr.x = w->phys_cursor.x;
5493 cr.y = w->phys_cursor.y;
5494 cr.width = cursor_glyph->pixel_width;
5495 cr.height = w->phys_cursor_height;
5496 return x_intersect_rectangles (&cr, r, &result);
5498 else
5499 return 0;
5503 /* Redraw a rectangle of window W. R is a rectangle in window
5504 relative coordinates. Call this function with input blocked. */
5506 static void
5507 expose_window (w, r)
5508 struct window *w;
5509 XRectangle *r;
5511 struct glyph_row *row;
5512 int y;
5513 int yb = window_text_bottom_y (w);
5514 int cursor_cleared_p;
5516 /* If window is not yet fully initialized, do nothing. This can
5517 happen when toolkit scroll bars are used and a window is split.
5518 Reconfiguring the scroll bar will generate an expose for a newly
5519 created window. */
5520 if (w->current_matrix == NULL)
5521 return;
5523 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5524 r->x, r->y, r->width, r->height));
5526 /* Convert to window coordinates. */
5527 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5528 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5530 /* Turn off the cursor. */
5531 if (!w->pseudo_window_p
5532 && x_phys_cursor_in_rect_p (w, r))
5534 x_clear_cursor (w);
5535 cursor_cleared_p = 1;
5537 else
5538 cursor_cleared_p = 0;
5540 /* Find the first row intersecting the rectangle R. */
5541 row = w->current_matrix->rows;
5542 y = 0;
5543 while (row->enabled_p
5544 && y < yb
5545 && y + row->height < r->y)
5547 y += row->height;
5548 ++row;
5551 /* Display the text in the rectangle, one text line at a time. */
5552 while (row->enabled_p
5553 && y < yb
5554 && y < r->y + r->height)
5556 expose_line (w, row, r);
5557 y += row->height;
5558 ++row;
5561 /* Display the mode line if there is one. */
5562 if (WINDOW_WANTS_MODELINE_P (w)
5563 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5564 row->enabled_p)
5565 && row->y < r->y + r->height)
5566 expose_line (w, row, r);
5568 if (!w->pseudo_window_p)
5570 /* Draw border between windows. */
5571 x_draw_vertical_border (w);
5573 /* Turn the cursor on again. */
5574 if (cursor_cleared_p)
5575 x_update_window_cursor (w, 1);
5580 /* Determine the intersection of two rectangles R1 and R2. Return
5581 the intersection in *RESULT. Value is non-zero if RESULT is not
5582 empty. */
5584 static int
5585 x_intersect_rectangles (r1, r2, result)
5586 XRectangle *r1, *r2, *result;
5588 XRectangle *left, *right;
5589 XRectangle *upper, *lower;
5590 int intersection_p = 0;
5592 /* Rearrange so that R1 is the left-most rectangle. */
5593 if (r1->x < r2->x)
5594 left = r1, right = r2;
5595 else
5596 left = r2, right = r1;
5598 /* X0 of the intersection is right.x0, if this is inside R1,
5599 otherwise there is no intersection. */
5600 if (right->x <= left->x + left->width)
5602 result->x = right->x;
5604 /* The right end of the intersection is the minimum of the
5605 the right ends of left and right. */
5606 result->width = (min (left->x + left->width, right->x + right->width)
5607 - result->x);
5609 /* Same game for Y. */
5610 if (r1->y < r2->y)
5611 upper = r1, lower = r2;
5612 else
5613 upper = r2, lower = r1;
5615 /* The upper end of the intersection is lower.y0, if this is inside
5616 of upper. Otherwise, there is no intersection. */
5617 if (lower->y <= upper->y + upper->height)
5619 result->y = lower->y;
5621 /* The lower end of the intersection is the minimum of the lower
5622 ends of upper and lower. */
5623 result->height = (min (lower->y + lower->height,
5624 upper->y + upper->height)
5625 - result->y);
5626 intersection_p = 1;
5630 return intersection_p;
5637 static void
5638 frame_highlight (f)
5639 struct frame *f;
5641 /* We used to only do this if Vx_no_window_manager was non-nil, but
5642 the ICCCM (section 4.1.6) says that the window's border pixmap
5643 and border pixel are window attributes which are "private to the
5644 client", so we can always change it to whatever we want. */
5645 BLOCK_INPUT;
5646 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5647 f->output_data.x->border_pixel);
5648 UNBLOCK_INPUT;
5649 x_update_cursor (f, 1);
5652 static void
5653 frame_unhighlight (f)
5654 struct frame *f;
5656 /* We used to only do this if Vx_no_window_manager was non-nil, but
5657 the ICCCM (section 4.1.6) says that the window's border pixmap
5658 and border pixel are window attributes which are "private to the
5659 client", so we can always change it to whatever we want. */
5660 BLOCK_INPUT;
5661 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5662 f->output_data.x->border_tile);
5663 UNBLOCK_INPUT;
5664 x_update_cursor (f, 1);
5667 /* The focus has changed. Update the frames as necessary to reflect
5668 the new situation. Note that we can't change the selected frame
5669 here, because the Lisp code we are interrupting might become confused.
5670 Each event gets marked with the frame in which it occurred, so the
5671 Lisp code can tell when the switch took place by examining the events. */
5673 static void
5674 x_new_focus_frame (dpyinfo, frame)
5675 struct x_display_info *dpyinfo;
5676 struct frame *frame;
5678 struct frame *old_focus = dpyinfo->x_focus_frame;
5680 if (frame != dpyinfo->x_focus_frame)
5682 /* Set this before calling other routines, so that they see
5683 the correct value of x_focus_frame. */
5684 dpyinfo->x_focus_frame = frame;
5686 if (old_focus && old_focus->auto_lower)
5687 x_lower_frame (old_focus);
5689 #if 0
5690 selected_frame = frame;
5691 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5692 selected_frame);
5693 Fselect_window (selected_frame->selected_window);
5694 choose_minibuf_frame ();
5695 #endif /* ! 0 */
5697 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5698 pending_autoraise_frame = dpyinfo->x_focus_frame;
5699 else
5700 pending_autoraise_frame = 0;
5703 x_frame_rehighlight (dpyinfo);
5706 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5708 void
5709 x_mouse_leave (dpyinfo)
5710 struct x_display_info *dpyinfo;
5712 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5715 /* The focus has changed, or we have redirected a frame's focus to
5716 another frame (this happens when a frame uses a surrogate
5717 mini-buffer frame). Shift the highlight as appropriate.
5719 The FRAME argument doesn't necessarily have anything to do with which
5720 frame is being highlighted or un-highlighted; we only use it to find
5721 the appropriate X display info. */
5723 static void
5724 XTframe_rehighlight (frame)
5725 struct frame *frame;
5727 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5730 static void
5731 x_frame_rehighlight (dpyinfo)
5732 struct x_display_info *dpyinfo;
5734 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5736 if (dpyinfo->x_focus_frame)
5738 dpyinfo->x_highlight_frame
5739 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5740 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5741 : dpyinfo->x_focus_frame);
5742 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5744 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5745 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5748 else
5749 dpyinfo->x_highlight_frame = 0;
5751 if (dpyinfo->x_highlight_frame != old_highlight)
5753 if (old_highlight)
5754 frame_unhighlight (old_highlight);
5755 if (dpyinfo->x_highlight_frame)
5756 frame_highlight (dpyinfo->x_highlight_frame);
5762 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5764 /* Initialize mode_switch_bit and modifier_meaning. */
5765 static void
5766 x_find_modifier_meanings (dpyinfo)
5767 struct x_display_info *dpyinfo;
5769 int min_code, max_code;
5770 KeySym *syms;
5771 int syms_per_code;
5772 XModifierKeymap *mods;
5774 dpyinfo->meta_mod_mask = 0;
5775 dpyinfo->shift_lock_mask = 0;
5776 dpyinfo->alt_mod_mask = 0;
5777 dpyinfo->super_mod_mask = 0;
5778 dpyinfo->hyper_mod_mask = 0;
5780 #ifdef HAVE_X11R4
5781 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5782 #else
5783 min_code = dpyinfo->display->min_keycode;
5784 max_code = dpyinfo->display->max_keycode;
5785 #endif
5787 syms = XGetKeyboardMapping (dpyinfo->display,
5788 min_code, max_code - min_code + 1,
5789 &syms_per_code);
5790 mods = XGetModifierMapping (dpyinfo->display);
5792 /* Scan the modifier table to see which modifier bits the Meta and
5793 Alt keysyms are on. */
5795 int row, col; /* The row and column in the modifier table. */
5797 for (row = 3; row < 8; row++)
5798 for (col = 0; col < mods->max_keypermod; col++)
5800 KeyCode code
5801 = mods->modifiermap[(row * mods->max_keypermod) + col];
5803 /* Zeroes are used for filler. Skip them. */
5804 if (code == 0)
5805 continue;
5807 /* Are any of this keycode's keysyms a meta key? */
5809 int code_col;
5811 for (code_col = 0; code_col < syms_per_code; code_col++)
5813 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5815 switch (sym)
5817 case XK_Meta_L:
5818 case XK_Meta_R:
5819 dpyinfo->meta_mod_mask |= (1 << row);
5820 break;
5822 case XK_Alt_L:
5823 case XK_Alt_R:
5824 dpyinfo->alt_mod_mask |= (1 << row);
5825 break;
5827 case XK_Hyper_L:
5828 case XK_Hyper_R:
5829 dpyinfo->hyper_mod_mask |= (1 << row);
5830 break;
5832 case XK_Super_L:
5833 case XK_Super_R:
5834 dpyinfo->super_mod_mask |= (1 << row);
5835 break;
5837 case XK_Shift_Lock:
5838 /* Ignore this if it's not on the lock modifier. */
5839 if ((1 << row) == LockMask)
5840 dpyinfo->shift_lock_mask = LockMask;
5841 break;
5848 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5849 if (! dpyinfo->meta_mod_mask)
5851 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5852 dpyinfo->alt_mod_mask = 0;
5855 /* If some keys are both alt and meta,
5856 make them just meta, not alt. */
5857 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5859 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5862 XFree ((char *) syms);
5863 XFreeModifiermap (mods);
5866 /* Convert between the modifier bits X uses and the modifier bits
5867 Emacs uses. */
5869 static unsigned int
5870 x_x_to_emacs_modifiers (dpyinfo, state)
5871 struct x_display_info *dpyinfo;
5872 unsigned int state;
5874 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5875 | ((state & ControlMask) ? ctrl_modifier : 0)
5876 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5877 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5878 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5879 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
5882 static unsigned int
5883 x_emacs_to_x_modifiers (dpyinfo, state)
5884 struct x_display_info *dpyinfo;
5885 unsigned int state;
5887 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5888 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5889 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5890 | ((state & shift_modifier) ? ShiftMask : 0)
5891 | ((state & ctrl_modifier) ? ControlMask : 0)
5892 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
5895 /* Convert a keysym to its name. */
5897 char *
5898 x_get_keysym_name (keysym)
5899 KeySym keysym;
5901 char *value;
5903 BLOCK_INPUT;
5904 value = XKeysymToString (keysym);
5905 UNBLOCK_INPUT;
5907 return value;
5912 /* Mouse clicks and mouse movement. Rah. */
5914 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5915 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5916 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5917 not force the value into range. */
5919 void
5920 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5921 FRAME_PTR f;
5922 register int pix_x, pix_y;
5923 register int *x, *y;
5924 XRectangle *bounds;
5925 int noclip;
5927 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5928 even for negative values. */
5929 if (pix_x < 0)
5930 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
5931 if (pix_y < 0)
5932 pix_y -= (f)->output_data.x->line_height - 1;
5934 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5935 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5937 if (bounds)
5939 bounds->width = FONT_WIDTH (f->output_data.x->font);
5940 bounds->height = f->output_data.x->line_height;
5941 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5942 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5945 if (!noclip)
5947 if (pix_x < 0)
5948 pix_x = 0;
5949 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5950 pix_x = FRAME_WINDOW_WIDTH (f);
5952 if (pix_y < 0)
5953 pix_y = 0;
5954 else if (pix_y > f->height)
5955 pix_y = f->height;
5958 *x = pix_x;
5959 *y = pix_y;
5963 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5964 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5965 can't tell the positions because W's display is not up to date,
5966 return 0. */
5969 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5970 struct window *w;
5971 int hpos, vpos;
5972 int *frame_x, *frame_y;
5974 int success_p;
5976 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5977 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5979 if (display_completed)
5981 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5982 struct glyph *glyph = row->glyphs[TEXT_AREA];
5983 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5985 *frame_y = row->y;
5986 *frame_x = row->x;
5987 while (glyph < end)
5989 *frame_x += glyph->pixel_width;
5990 ++glyph;
5993 success_p = 1;
5995 else
5997 *frame_y = *frame_x = 0;
5998 success_p = 0;
6001 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6002 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6003 return success_p;
6007 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6009 If the event is a button press, then note that we have grabbed
6010 the mouse. */
6012 static Lisp_Object
6013 construct_mouse_click (result, event, f)
6014 struct input_event *result;
6015 XButtonEvent *event;
6016 struct frame *f;
6018 /* Make the event type no_event; we'll change that when we decide
6019 otherwise. */
6020 result->kind = mouse_click;
6021 result->code = event->button - Button1;
6022 result->timestamp = event->time;
6023 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6024 event->state)
6025 | (event->type == ButtonRelease
6026 ? up_modifier
6027 : down_modifier));
6029 XSETINT (result->x, event->x);
6030 XSETINT (result->y, event->y);
6031 XSETFRAME (result->frame_or_window, f);
6032 return Qnil;
6035 #if 0 /* This function isn't called. --gerd */
6037 /* Prepare a menu-event in *RESULT for placement in the input queue. */
6039 static Lisp_Object
6040 construct_menu_click (result, event, f)
6041 struct input_event *result;
6042 XButtonEvent *event;
6043 struct frame *f;
6045 /* Make the event type no_event; we'll change that when we decide
6046 otherwise. */
6047 result->kind = mouse_click;
6048 result->code = event->button - Button1;
6049 result->timestamp = event->time;
6050 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6051 event->state)
6052 | (event->type == ButtonRelease
6053 ? up_modifier
6054 : down_modifier));
6056 XSETINT (result->x, event->x);
6057 XSETINT (result->y, -1);
6058 XSETFRAME (result->frame_or_window, f);
6061 #endif /* 0 */
6064 /* Function to report a mouse movement to the mainstream Emacs code.
6065 The input handler calls this.
6067 We have received a mouse movement event, which is given in *event.
6068 If the mouse is over a different glyph than it was last time, tell
6069 the mainstream emacs code by setting mouse_moved. If not, ask for
6070 another motion event, so we can check again the next time it moves. */
6072 static XMotionEvent last_mouse_motion_event;
6073 static Lisp_Object last_mouse_motion_frame;
6075 static void
6076 note_mouse_movement (frame, event)
6077 FRAME_PTR frame;
6078 XMotionEvent *event;
6080 last_mouse_movement_time = event->time;
6081 last_mouse_motion_event = *event;
6082 XSETFRAME (last_mouse_motion_frame, frame);
6084 if (event->window != FRAME_X_WINDOW (frame))
6086 frame->mouse_moved = 1;
6087 last_mouse_scroll_bar = Qnil;
6088 note_mouse_highlight (frame, -1, -1);
6091 /* Has the mouse moved off the glyph it was on at the last sighting? */
6092 else if (event->x < last_mouse_glyph.x
6093 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6094 || event->y < last_mouse_glyph.y
6095 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6097 frame->mouse_moved = 1;
6098 last_mouse_scroll_bar = Qnil;
6099 note_mouse_highlight (frame, event->x, event->y);
6103 /* This is used for debugging, to turn off note_mouse_highlight. */
6105 int disable_mouse_highlight;
6109 /************************************************************************
6110 Mouse Face
6111 ************************************************************************/
6113 /* Find the glyph under window-relative coordinates X/Y in window W.
6114 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6115 strings. Return in *HPOS and *VPOS the row and column number of
6116 the glyph found. Return in *AREA the glyph area containing X.
6117 Value is a pointer to the glyph found or null if X/Y is not on
6118 text, or we can't tell because W's current matrix is not up to
6119 date. */
6121 static struct glyph *
6122 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6123 struct window *w;
6124 int x, y;
6125 int *hpos, *vpos, *area;
6127 struct glyph *glyph, *end;
6128 struct glyph_row *row;
6129 int x0, i, left_area_width;
6131 /* Find row containing Y. Give up if some row is not enabled. */
6132 for (i = 0; i < w->current_matrix->nrows; ++i)
6134 row = MATRIX_ROW (w->current_matrix, i);
6135 if (!row->enabled_p)
6136 return NULL;
6137 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6138 break;
6141 *vpos = i;
6142 *hpos = 0;
6144 /* Give up if Y is not in the window. */
6145 if (i == w->current_matrix->nrows)
6146 return NULL;
6148 /* Get the glyph area containing X. */
6149 if (w->pseudo_window_p)
6151 *area = TEXT_AREA;
6152 x0 = 0;
6154 else
6156 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6157 if (x < left_area_width)
6159 *area = LEFT_MARGIN_AREA;
6160 x0 = 0;
6162 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6164 *area = TEXT_AREA;
6165 x0 = row->x + left_area_width;
6167 else
6169 *area = RIGHT_MARGIN_AREA;
6170 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6174 /* Find glyph containing X. */
6175 glyph = row->glyphs[*area];
6176 end = glyph + row->used[*area];
6177 while (glyph < end)
6179 if (x < x0 + glyph->pixel_width)
6181 if (w->pseudo_window_p)
6182 break;
6183 else if (BUFFERP (glyph->object))
6184 break;
6187 x0 += glyph->pixel_width;
6188 ++glyph;
6191 if (glyph == end)
6192 return NULL;
6194 *hpos = glyph - row->glyphs[*area];
6195 return glyph;
6199 /* Convert frame-relative x/y to coordinates relative to window W.
6200 Takes pseudo-windows into account. */
6202 static void
6203 frame_to_window_pixel_xy (w, x, y)
6204 struct window *w;
6205 int *x, *y;
6207 if (w->pseudo_window_p)
6209 /* A pseudo-window is always full-width, and starts at the
6210 left edge of the frame, plus a frame border. */
6211 struct frame *f = XFRAME (w->frame);
6212 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6213 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6215 else
6217 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6218 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6223 /* Take proper action when mouse has moved to the mode or top line of
6224 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6225 mode line. X is relative to the start of the text display area of
6226 W, so the width of bitmap areas and scroll bars must be subtracted
6227 to get a position relative to the start of the mode line. */
6229 static void
6230 note_mode_line_highlight (w, x, mode_line_p)
6231 struct window *w;
6232 int x, mode_line_p;
6234 struct frame *f = XFRAME (w->frame);
6235 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6236 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6237 struct glyph_row *row;
6239 if (mode_line_p)
6240 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6241 else
6242 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6244 if (row->enabled_p)
6246 struct glyph *glyph, *end;
6247 Lisp_Object help, map;
6248 int x0;
6250 /* Find the glyph under X. */
6251 glyph = row->glyphs[TEXT_AREA];
6252 end = glyph + row->used[TEXT_AREA];
6253 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6254 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6255 while (glyph < end
6256 && x >= x0 + glyph->pixel_width)
6258 x0 += glyph->pixel_width;
6259 ++glyph;
6262 if (glyph < end
6263 && STRINGP (glyph->object)
6264 && XSTRING (glyph->object)->intervals
6265 && glyph->charpos >= 0
6266 && glyph->charpos < XSTRING (glyph->object)->size)
6268 /* If we're on a string with `help-echo' text property,
6269 arrange for the help to be displayed. This is done by
6270 setting the global variable help_echo to the help string. */
6271 help = Fget_text_property (make_number (glyph->charpos),
6272 Qhelp_echo, glyph->object);
6273 if (STRINGP (help))
6274 help_echo = help;
6276 /* Change the mouse pointer according to what is under X/Y. */
6277 map = Fget_text_property (make_number (glyph->charpos),
6278 Qlocal_map, glyph->object);
6279 if (!NILP (Fkeymapp (map)))
6280 cursor = f->output_data.x->nontext_cursor;
6284 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6288 /* Take proper action when the mouse has moved to position X, Y on
6289 frame F as regards highlighting characters that have mouse-face
6290 properties. Also de-highlighting chars where the mouse was before.
6291 X and Y can be negative or out of range. */
6293 static void
6294 note_mouse_highlight (f, x, y)
6295 struct frame *f;
6296 int x, y;
6298 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6299 int portion;
6300 Lisp_Object window;
6301 struct window *w;
6303 /* When a menu is active, don't highlight because this looks odd. */
6304 #ifdef USE_X_TOOLKIT
6305 if (popup_activated ())
6306 return;
6307 #endif
6309 if (disable_mouse_highlight
6310 || !f->glyphs_initialized_p)
6311 return;
6313 dpyinfo->mouse_face_mouse_x = x;
6314 dpyinfo->mouse_face_mouse_y = y;
6315 dpyinfo->mouse_face_mouse_frame = f;
6317 if (dpyinfo->mouse_face_defer)
6318 return;
6320 if (gc_in_progress)
6322 dpyinfo->mouse_face_deferred_gc = 1;
6323 return;
6326 /* Which window is that in? */
6327 window = window_from_coordinates (f, x, y, &portion, 1);
6329 /* If we were displaying active text in another window, clear that. */
6330 if (! EQ (window, dpyinfo->mouse_face_window))
6331 clear_mouse_face (dpyinfo);
6333 /* Not on a window -> return. */
6334 if (!WINDOWP (window))
6335 return;
6337 /* Convert to window-relative pixel coordinates. */
6338 w = XWINDOW (window);
6339 frame_to_window_pixel_xy (w, &x, &y);
6341 /* Handle tool-bar window differently since it doesn't display a
6342 buffer. */
6343 if (EQ (window, f->tool_bar_window))
6345 note_tool_bar_highlight (f, x, y);
6346 return;
6349 if (portion == 1 || portion == 3)
6351 /* Mouse is on the mode or top line. */
6352 note_mode_line_highlight (w, x, portion == 1);
6353 return;
6355 else
6356 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6357 f->output_data.x->text_cursor);
6359 /* Are we in a window whose display is up to date?
6360 And verify the buffer's text has not changed. */
6361 if (/* Within text portion of the window. */
6362 portion == 0
6363 && EQ (w->window_end_valid, w->buffer)
6364 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6365 && (XFASTINT (w->last_overlay_modified)
6366 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6368 int hpos, vpos, pos, i, area;
6369 struct glyph *glyph;
6371 /* Find the glyph under X/Y. */
6372 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6374 /* Clear mouse face if X/Y not over text. */
6375 if (glyph == NULL
6376 || area != TEXT_AREA
6377 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6379 clear_mouse_face (dpyinfo);
6380 return;
6383 pos = glyph->charpos;
6384 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6386 /* Check for mouse-face and help-echo. */
6388 Lisp_Object mouse_face, overlay, position;
6389 Lisp_Object *overlay_vec;
6390 int len, noverlays;
6391 struct buffer *obuf;
6392 int obegv, ozv;
6394 /* If we get an out-of-range value, return now; avoid an error. */
6395 if (pos > BUF_Z (XBUFFER (w->buffer)))
6396 return;
6398 /* Make the window's buffer temporarily current for
6399 overlays_at and compute_char_face. */
6400 obuf = current_buffer;
6401 current_buffer = XBUFFER (w->buffer);
6402 obegv = BEGV;
6403 ozv = ZV;
6404 BEGV = BEG;
6405 ZV = Z;
6407 /* Is this char mouse-active or does it have help-echo? */
6408 XSETINT (position, pos);
6410 /* Put all the overlays we want in a vector in overlay_vec.
6411 Store the length in len. If there are more than 10, make
6412 enough space for all, and try again. */
6413 len = 10;
6414 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6415 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6416 if (noverlays > len)
6418 len = noverlays;
6419 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6420 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6423 noverlays = sort_overlays (overlay_vec, noverlays, w);
6425 /* Check mouse-face highlighting. */
6426 if (! (EQ (window, dpyinfo->mouse_face_window)
6427 && vpos >= dpyinfo->mouse_face_beg_row
6428 && vpos <= dpyinfo->mouse_face_end_row
6429 && (vpos > dpyinfo->mouse_face_beg_row
6430 || hpos >= dpyinfo->mouse_face_beg_col)
6431 && (vpos < dpyinfo->mouse_face_end_row
6432 || hpos < dpyinfo->mouse_face_end_col
6433 || dpyinfo->mouse_face_past_end)))
6435 /* Clear the display of the old active region, if any. */
6436 clear_mouse_face (dpyinfo);
6438 /* Find the highest priority overlay that has a mouse-face prop. */
6439 overlay = Qnil;
6440 for (i = 0; i < noverlays; i++)
6442 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6443 if (!NILP (mouse_face))
6445 overlay = overlay_vec[i];
6446 break;
6450 /* If no overlay applies, get a text property. */
6451 if (NILP (overlay))
6452 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6454 /* Handle the overlay case. */
6455 if (! NILP (overlay))
6457 /* Find the range of text around this char that
6458 should be active. */
6459 Lisp_Object before, after;
6460 int ignore;
6462 before = Foverlay_start (overlay);
6463 after = Foverlay_end (overlay);
6464 /* Record this as the current active region. */
6465 fast_find_position (w, XFASTINT (before),
6466 &dpyinfo->mouse_face_beg_col,
6467 &dpyinfo->mouse_face_beg_row,
6468 &dpyinfo->mouse_face_beg_x,
6469 &dpyinfo->mouse_face_beg_y);
6470 dpyinfo->mouse_face_past_end
6471 = !fast_find_position (w, XFASTINT (after),
6472 &dpyinfo->mouse_face_end_col,
6473 &dpyinfo->mouse_face_end_row,
6474 &dpyinfo->mouse_face_end_x,
6475 &dpyinfo->mouse_face_end_y);
6476 dpyinfo->mouse_face_window = window;
6477 dpyinfo->mouse_face_face_id
6478 = face_at_buffer_position (w, pos, 0, 0,
6479 &ignore, pos + 1, 1);
6481 /* Display it as active. */
6482 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6484 /* Handle the text property case. */
6485 else if (! NILP (mouse_face))
6487 /* Find the range of text around this char that
6488 should be active. */
6489 Lisp_Object before, after, beginning, end;
6490 int ignore;
6492 beginning = Fmarker_position (w->start);
6493 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6494 - XFASTINT (w->window_end_pos)));
6495 before
6496 = Fprevious_single_property_change (make_number (pos + 1),
6497 Qmouse_face,
6498 w->buffer, beginning);
6499 after
6500 = Fnext_single_property_change (position, Qmouse_face,
6501 w->buffer, end);
6502 /* Record this as the current active region. */
6503 fast_find_position (w, XFASTINT (before),
6504 &dpyinfo->mouse_face_beg_col,
6505 &dpyinfo->mouse_face_beg_row,
6506 &dpyinfo->mouse_face_beg_x,
6507 &dpyinfo->mouse_face_beg_y);
6508 dpyinfo->mouse_face_past_end
6509 = !fast_find_position (w, XFASTINT (after),
6510 &dpyinfo->mouse_face_end_col,
6511 &dpyinfo->mouse_face_end_row,
6512 &dpyinfo->mouse_face_end_x,
6513 &dpyinfo->mouse_face_end_y);
6514 dpyinfo->mouse_face_window = window;
6515 dpyinfo->mouse_face_face_id
6516 = face_at_buffer_position (w, pos, 0, 0,
6517 &ignore, pos + 1, 1);
6519 /* Display it as active. */
6520 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6524 /* Look for a `help-echo' property. */
6526 Lisp_Object help;
6528 /* Check overlays first. */
6529 help = Qnil;
6530 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6531 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6533 /* Try text properties. */
6534 if (!STRINGP (help)
6535 && ((STRINGP (glyph->object)
6536 && glyph->charpos >= 0
6537 && glyph->charpos < XSTRING (glyph->object)->size)
6538 || (BUFFERP (glyph->object)
6539 && glyph->charpos >= BEGV
6540 && glyph->charpos < ZV)))
6541 help = Fget_text_property (make_number (glyph->charpos),
6542 Qhelp_echo, glyph->object);
6544 if (STRINGP (help))
6545 help_echo = help;
6548 BEGV = obegv;
6549 ZV = ozv;
6550 current_buffer = obuf;
6555 static void
6556 redo_mouse_highlight ()
6558 if (!NILP (last_mouse_motion_frame)
6559 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6560 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6561 last_mouse_motion_event.x,
6562 last_mouse_motion_event.y);
6567 /***********************************************************************
6568 Tool-bars
6569 ***********************************************************************/
6571 static int x_tool_bar_item P_ ((struct frame *, int, int,
6572 struct glyph **, int *, int *, int *));
6574 /* Tool-bar item index of the item on which a mouse button was pressed
6575 or -1. */
6577 static int last_tool_bar_item;
6580 /* Get information about the tool-bar item at position X/Y on frame F.
6581 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6582 the current matrix of the tool-bar window of F, or NULL if not
6583 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6584 item in F->current_tool_bar_items. Value is
6586 -1 if X/Y is not on a tool-bar item
6587 0 if X/Y is on the same item that was highlighted before.
6588 1 otherwise. */
6590 static int
6591 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6592 struct frame *f;
6593 int x, y;
6594 struct glyph **glyph;
6595 int *hpos, *vpos, *prop_idx;
6597 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6598 struct window *w = XWINDOW (f->tool_bar_window);
6599 int area;
6601 /* Find the glyph under X/Y. */
6602 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6603 if (*glyph == NULL)
6604 return -1;
6606 /* Get the start of this tool-bar item's properties in
6607 f->current_tool_bar_items. */
6608 if (!tool_bar_item_info (f, *glyph, prop_idx))
6609 return -1;
6611 /* Is mouse on the highlighted item? */
6612 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6613 && *vpos >= dpyinfo->mouse_face_beg_row
6614 && *vpos <= dpyinfo->mouse_face_end_row
6615 && (*vpos > dpyinfo->mouse_face_beg_row
6616 || *hpos >= dpyinfo->mouse_face_beg_col)
6617 && (*vpos < dpyinfo->mouse_face_end_row
6618 || *hpos < dpyinfo->mouse_face_end_col
6619 || dpyinfo->mouse_face_past_end))
6620 return 0;
6622 return 1;
6626 /* Handle mouse button event on the tool-bar of frame F, at
6627 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6628 or ButtonRelase. */
6630 static void
6631 x_handle_tool_bar_click (f, button_event)
6632 struct frame *f;
6633 XButtonEvent *button_event;
6635 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6636 struct window *w = XWINDOW (f->tool_bar_window);
6637 int hpos, vpos, prop_idx;
6638 struct glyph *glyph;
6639 Lisp_Object enabled_p;
6640 int x = button_event->x;
6641 int y = button_event->y;
6643 /* If not on the highlighted tool-bar item, return. */
6644 frame_to_window_pixel_xy (w, &x, &y);
6645 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6646 return;
6648 /* If item is disabled, do nothing. */
6649 enabled_p = (XVECTOR (f->current_tool_bar_items)
6650 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6651 if (NILP (enabled_p))
6652 return;
6654 if (button_event->type == ButtonPress)
6656 /* Show item in pressed state. */
6657 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6658 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6659 last_tool_bar_item = prop_idx;
6661 else
6663 Lisp_Object key, frame;
6664 struct input_event event;
6666 /* Show item in released state. */
6667 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6668 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6670 key = (XVECTOR (f->current_tool_bar_items)
6671 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6673 XSETFRAME (frame, f);
6674 event.kind = TOOL_BAR_EVENT;
6675 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6676 kbd_buffer_store_event (&event);
6678 event.kind = TOOL_BAR_EVENT;
6679 event.frame_or_window = Fcons (frame, key);
6680 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6681 button_event->state);
6682 kbd_buffer_store_event (&event);
6683 last_tool_bar_item = -1;
6688 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6689 tool-bar window-relative coordinates X/Y. Called from
6690 note_mouse_highlight. */
6692 static void
6693 note_tool_bar_highlight (f, x, y)
6694 struct frame *f;
6695 int x, y;
6697 Lisp_Object window = f->tool_bar_window;
6698 struct window *w = XWINDOW (window);
6699 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6700 int hpos, vpos;
6701 struct glyph *glyph;
6702 struct glyph_row *row;
6703 int i;
6704 Lisp_Object enabled_p;
6705 int prop_idx;
6706 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6707 int mouse_down_p, rc;
6709 /* Function note_mouse_highlight is called with negative x(y
6710 values when mouse moves outside of the frame. */
6711 if (x <= 0 || y <= 0)
6713 clear_mouse_face (dpyinfo);
6714 return;
6717 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6718 if (rc < 0)
6720 /* Not on tool-bar item. */
6721 clear_mouse_face (dpyinfo);
6722 return;
6724 else if (rc == 0)
6725 /* On same tool-bar item as before. */
6726 goto set_help_echo;
6728 clear_mouse_face (dpyinfo);
6730 /* Mouse is down, but on different tool-bar item? */
6731 mouse_down_p = (dpyinfo->grabbed
6732 && f == last_mouse_frame
6733 && FRAME_LIVE_P (f));
6734 if (mouse_down_p
6735 && last_tool_bar_item != prop_idx)
6736 return;
6738 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6739 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6741 /* If tool-bar item is not enabled, don't highlight it. */
6742 enabled_p = (XVECTOR (f->current_tool_bar_items)
6743 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6744 if (!NILP (enabled_p))
6746 /* Compute the x-position of the glyph. In front and past the
6747 image is a space. We include this is the highlighted area. */
6748 row = MATRIX_ROW (w->current_matrix, vpos);
6749 for (i = x = 0; i < hpos; ++i)
6750 x += row->glyphs[TEXT_AREA][i].pixel_width;
6752 /* Record this as the current active region. */
6753 dpyinfo->mouse_face_beg_col = hpos;
6754 dpyinfo->mouse_face_beg_row = vpos;
6755 dpyinfo->mouse_face_beg_x = x;
6756 dpyinfo->mouse_face_beg_y = row->y;
6757 dpyinfo->mouse_face_past_end = 0;
6759 dpyinfo->mouse_face_end_col = hpos + 1;
6760 dpyinfo->mouse_face_end_row = vpos;
6761 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6762 dpyinfo->mouse_face_end_y = row->y;
6763 dpyinfo->mouse_face_window = window;
6764 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6766 /* Display it as active. */
6767 show_mouse_face (dpyinfo, draw);
6768 dpyinfo->mouse_face_image_state = draw;
6771 set_help_echo:
6773 /* Set help_echo to a help string.to display for this tool-bar item.
6774 XTread_socket does the rest. */
6775 help_echo = (XVECTOR (f->current_tool_bar_items)
6776 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6777 if (!STRINGP (help_echo))
6778 help_echo = (XVECTOR (f->current_tool_bar_items)
6779 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6784 /* Find the glyph matrix position of buffer position POS in window W.
6785 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6786 current glyphs must be up to date. If POS is above window start
6787 return (0, 0, 0, 0). If POS is after end of W, return end of
6788 last line in W. */
6790 static int
6791 fast_find_position (w, pos, hpos, vpos, x, y)
6792 struct window *w;
6793 int pos;
6794 int *hpos, *vpos, *x, *y;
6796 int i;
6797 int lastcol;
6798 int maybe_next_line_p = 0;
6799 int line_start_position;
6800 int yb = window_text_bottom_y (w);
6801 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6802 struct glyph_row *best_row = row;
6803 int row_vpos = 0, best_row_vpos = 0;
6804 int current_x;
6806 while (row->y < yb)
6808 if (row->used[TEXT_AREA])
6809 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6810 else
6811 line_start_position = 0;
6813 if (line_start_position > pos)
6814 break;
6815 /* If the position sought is the end of the buffer,
6816 don't include the blank lines at the bottom of the window. */
6817 else if (line_start_position == pos
6818 && pos == BUF_ZV (XBUFFER (w->buffer)))
6820 maybe_next_line_p = 1;
6821 break;
6823 else if (line_start_position > 0)
6825 best_row = row;
6826 best_row_vpos = row_vpos;
6829 ++row;
6830 ++row_vpos;
6833 /* Find the right column within BEST_ROW. */
6834 lastcol = 0;
6835 current_x = best_row->x;
6836 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6838 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6839 int charpos;
6841 charpos = glyph->charpos;
6842 if (charpos == pos)
6844 *hpos = i;
6845 *vpos = best_row_vpos;
6846 *x = current_x;
6847 *y = best_row->y;
6848 return 1;
6850 else if (charpos > pos)
6851 break;
6852 else if (charpos > 0)
6853 lastcol = i;
6855 current_x += glyph->pixel_width;
6858 /* If we're looking for the end of the buffer,
6859 and we didn't find it in the line we scanned,
6860 use the start of the following line. */
6861 if (maybe_next_line_p)
6863 ++best_row;
6864 ++best_row_vpos;
6865 lastcol = 0;
6866 current_x = best_row->x;
6869 *vpos = best_row_vpos;
6870 *hpos = lastcol + 1;
6871 *x = current_x;
6872 *y = best_row->y;
6873 return 0;
6877 /* Display the active region described by mouse_face_*
6878 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6880 static void
6881 show_mouse_face (dpyinfo, draw)
6882 struct x_display_info *dpyinfo;
6883 enum draw_glyphs_face draw;
6885 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6886 struct frame *f = XFRAME (WINDOW_FRAME (w));
6887 int i;
6888 int cursor_off_p = 0;
6889 struct cursor_pos saved_cursor;
6891 saved_cursor = output_cursor;
6893 /* If window is in the process of being destroyed, don't bother
6894 to do anything. */
6895 if (w->current_matrix == NULL)
6896 goto set_x_cursor;
6898 /* Recognize when we are called to operate on rows that don't exist
6899 anymore. This can happen when a window is split. */
6900 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6901 goto set_x_cursor;
6903 set_output_cursor (&w->phys_cursor);
6905 /* Note that mouse_face_beg_row etc. are window relative. */
6906 for (i = dpyinfo->mouse_face_beg_row;
6907 i <= dpyinfo->mouse_face_end_row;
6908 i++)
6910 int start_hpos, end_hpos, start_x;
6911 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6913 /* Don't do anything if row doesn't have valid contents. */
6914 if (!row->enabled_p)
6915 continue;
6917 /* For all but the first row, the highlight starts at column 0. */
6918 if (i == dpyinfo->mouse_face_beg_row)
6920 start_hpos = dpyinfo->mouse_face_beg_col;
6921 start_x = dpyinfo->mouse_face_beg_x;
6923 else
6925 start_hpos = 0;
6926 start_x = 0;
6929 if (i == dpyinfo->mouse_face_end_row)
6930 end_hpos = dpyinfo->mouse_face_end_col;
6931 else
6932 end_hpos = row->used[TEXT_AREA];
6934 /* If the cursor's in the text we are about to rewrite, turn the
6935 cursor off. */
6936 if (!w->pseudo_window_p
6937 && i == output_cursor.vpos
6938 && output_cursor.hpos >= start_hpos - 1
6939 && output_cursor.hpos <= end_hpos)
6941 x_update_window_cursor (w, 0);
6942 cursor_off_p = 1;
6945 if (end_hpos > start_hpos)
6946 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6947 start_hpos, end_hpos, draw, NULL, NULL, 0);
6950 /* If we turned the cursor off, turn it back on. */
6951 if (cursor_off_p)
6952 x_display_cursor (w, 1,
6953 output_cursor.hpos, output_cursor.vpos,
6954 output_cursor.x, output_cursor.y);
6956 output_cursor = saved_cursor;
6958 set_x_cursor:
6960 /* Change the mouse cursor. */
6961 if (draw == DRAW_NORMAL_TEXT)
6962 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6963 f->output_data.x->text_cursor);
6964 else if (draw == DRAW_MOUSE_FACE)
6965 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6966 f->output_data.x->cross_cursor);
6967 else
6968 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6969 f->output_data.x->nontext_cursor);
6972 /* Clear out the mouse-highlighted active region.
6973 Redraw it un-highlighted first. */
6975 void
6976 clear_mouse_face (dpyinfo)
6977 struct x_display_info *dpyinfo;
6979 if (tip_frame)
6980 return;
6982 if (! NILP (dpyinfo->mouse_face_window))
6983 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6985 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6986 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6987 dpyinfo->mouse_face_window = Qnil;
6990 /* Just discard the mouse face information for frame F, if any.
6991 This is used when the size of F is changed. */
6993 void
6994 cancel_mouse_face (f)
6995 FRAME_PTR f;
6997 Lisp_Object window;
6998 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7000 window = dpyinfo->mouse_face_window;
7001 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7003 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7004 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7005 dpyinfo->mouse_face_window = Qnil;
7009 static struct scroll_bar *x_window_to_scroll_bar ();
7010 static void x_scroll_bar_report_motion ();
7012 /* Return the current position of the mouse.
7013 *fp should be a frame which indicates which display to ask about.
7015 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7016 and *part to the frame, window, and scroll bar part that the mouse
7017 is over. Set *x and *y to the portion and whole of the mouse's
7018 position on the scroll bar.
7020 If the mouse movement started elsewhere, set *fp to the frame the
7021 mouse is on, *bar_window to nil, and *x and *y to the character cell
7022 the mouse is over.
7024 Set *time to the server time-stamp for the time at which the mouse
7025 was at this position.
7027 Don't store anything if we don't have a valid set of values to report.
7029 This clears the mouse_moved flag, so we can wait for the next mouse
7030 movement. */
7032 static void
7033 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7034 FRAME_PTR *fp;
7035 int insist;
7036 Lisp_Object *bar_window;
7037 enum scroll_bar_part *part;
7038 Lisp_Object *x, *y;
7039 unsigned long *time;
7041 FRAME_PTR f1;
7043 BLOCK_INPUT;
7045 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7046 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7047 else
7049 Window root;
7050 int root_x, root_y;
7052 Window dummy_window;
7053 int dummy;
7055 Lisp_Object frame, tail;
7057 /* Clear the mouse-moved flag for every frame on this display. */
7058 FOR_EACH_FRAME (tail, frame)
7059 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7060 XFRAME (frame)->mouse_moved = 0;
7062 last_mouse_scroll_bar = Qnil;
7064 /* Figure out which root window we're on. */
7065 XQueryPointer (FRAME_X_DISPLAY (*fp),
7066 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7068 /* The root window which contains the pointer. */
7069 &root,
7071 /* Trash which we can't trust if the pointer is on
7072 a different screen. */
7073 &dummy_window,
7075 /* The position on that root window. */
7076 &root_x, &root_y,
7078 /* More trash we can't trust. */
7079 &dummy, &dummy,
7081 /* Modifier keys and pointer buttons, about which
7082 we don't care. */
7083 (unsigned int *) &dummy);
7085 /* Now we have a position on the root; find the innermost window
7086 containing the pointer. */
7088 Window win, child;
7089 int win_x, win_y;
7090 int parent_x = 0, parent_y = 0;
7091 int count;
7093 win = root;
7095 /* XTranslateCoordinates can get errors if the window
7096 structure is changing at the same time this function
7097 is running. So at least we must not crash from them. */
7099 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7101 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7102 && FRAME_LIVE_P (last_mouse_frame))
7104 /* If mouse was grabbed on a frame, give coords for that frame
7105 even if the mouse is now outside it. */
7106 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7108 /* From-window, to-window. */
7109 root, FRAME_X_WINDOW (last_mouse_frame),
7111 /* From-position, to-position. */
7112 root_x, root_y, &win_x, &win_y,
7114 /* Child of win. */
7115 &child);
7116 f1 = last_mouse_frame;
7118 else
7120 while (1)
7122 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7124 /* From-window, to-window. */
7125 root, win,
7127 /* From-position, to-position. */
7128 root_x, root_y, &win_x, &win_y,
7130 /* Child of win. */
7131 &child);
7133 if (child == None || child == win)
7134 break;
7136 win = child;
7137 parent_x = win_x;
7138 parent_y = win_y;
7141 /* Now we know that:
7142 win is the innermost window containing the pointer
7143 (XTC says it has no child containing the pointer),
7144 win_x and win_y are the pointer's position in it
7145 (XTC did this the last time through), and
7146 parent_x and parent_y are the pointer's position in win's parent.
7147 (They are what win_x and win_y were when win was child.
7148 If win is the root window, it has no parent, and
7149 parent_{x,y} are invalid, but that's okay, because we'll
7150 never use them in that case.) */
7152 /* Is win one of our frames? */
7153 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7156 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7157 f1 = 0;
7159 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7161 /* If not, is it one of our scroll bars? */
7162 if (! f1)
7164 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7166 if (bar)
7168 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7169 win_x = parent_x;
7170 win_y = parent_y;
7174 if (f1 == 0 && insist > 0)
7175 f1 = SELECTED_FRAME ();
7177 if (f1)
7179 /* Ok, we found a frame. Store all the values.
7180 last_mouse_glyph is a rectangle used to reduce the
7181 generation of mouse events. To not miss any motion
7182 events, we must divide the frame into rectangles of the
7183 size of the smallest character that could be displayed
7184 on it, i.e. into the same rectangles that matrices on
7185 the frame are divided into. */
7187 #if OLD_REDISPLAY_CODE
7188 int ignore1, ignore2;
7189 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7190 &last_mouse_glyph,
7191 FRAME_X_DISPLAY_INFO (f1)->grabbed
7192 || insist);
7193 #else
7195 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7196 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7197 int x = win_x;
7198 int y = win_y;
7200 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7201 round down even for negative values. */
7202 if (x < 0)
7203 x -= width - 1;
7204 if (y < 0)
7205 y -= height - 1;
7207 last_mouse_glyph.width = width;
7208 last_mouse_glyph.height = height;
7209 last_mouse_glyph.x = (x + width - 1) / width * width;
7210 last_mouse_glyph.y = (y + height - 1) / height * height;
7212 #endif
7214 *bar_window = Qnil;
7215 *part = 0;
7216 *fp = f1;
7217 XSETINT (*x, win_x);
7218 XSETINT (*y, win_y);
7219 *time = last_mouse_movement_time;
7224 UNBLOCK_INPUT;
7228 #ifdef USE_X_TOOLKIT
7230 /* Atimer callback function for TIMER. Called every 0.1s to process
7231 Xt timeouts, if needed. We must avoid calling XtAppPending as
7232 much as possible because that function does an implicit XFlush
7233 that slows us down. */
7235 static void
7236 x_process_timeouts (timer)
7237 struct atimer *timer;
7239 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7241 BLOCK_INPUT;
7242 while (XtAppPending (Xt_app_con) & XtIMTimer)
7243 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7244 UNBLOCK_INPUT;
7248 #endif /* USE_X_TOOLKIT */
7251 /* Scroll bar support. */
7253 /* Given an X window ID, find the struct scroll_bar which manages it.
7254 This can be called in GC, so we have to make sure to strip off mark
7255 bits. */
7257 static struct scroll_bar *
7258 x_window_to_scroll_bar (window_id)
7259 Window window_id;
7261 Lisp_Object tail;
7263 for (tail = Vframe_list;
7264 XGCTYPE (tail) == Lisp_Cons;
7265 tail = XCDR (tail))
7267 Lisp_Object frame, bar, condemned;
7269 frame = XCAR (tail);
7270 /* All elements of Vframe_list should be frames. */
7271 if (! GC_FRAMEP (frame))
7272 abort ();
7274 /* Scan this frame's scroll bar list for a scroll bar with the
7275 right window ID. */
7276 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7277 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7278 /* This trick allows us to search both the ordinary and
7279 condemned scroll bar lists with one loop. */
7280 ! GC_NILP (bar) || (bar = condemned,
7281 condemned = Qnil,
7282 ! GC_NILP (bar));
7283 bar = XSCROLL_BAR (bar)->next)
7284 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7285 return XSCROLL_BAR (bar);
7288 return 0;
7293 /************************************************************************
7294 Toolkit scroll bars
7295 ************************************************************************/
7297 #if USE_TOOLKIT_SCROLL_BARS
7299 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7300 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7301 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7302 struct scroll_bar *));
7303 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7304 int, int, int));
7307 /* Id of action hook installed for scroll bars. */
7309 static XtActionHookId action_hook_id;
7311 /* Lisp window being scrolled. Set when starting to interact with
7312 a toolkit scroll bar, reset to nil when ending the interaction. */
7314 static Lisp_Object window_being_scrolled;
7316 /* Last scroll bar part sent in xm_scroll_callback. */
7318 static int last_scroll_bar_part;
7320 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7321 that movements of 1/20 of the screen size are mapped to up/down. */
7323 static Boolean xaw3d_arrow_scroll;
7325 /* Whether the drag scrolling maintains the mouse at the top of the
7326 thumb. If not, resizing the thumb needs to be done more carefully
7327 to avoid jerkyness. */
7329 static Boolean xaw3d_pick_top;
7332 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7333 bars are used.. The hook is responsible for detecting when
7334 the user ends an interaction with the scroll bar, and generates
7335 a `end-scroll' scroll_bar_click' event if so. */
7337 static void
7338 xt_action_hook (widget, client_data, action_name, event, params,
7339 num_params)
7340 Widget widget;
7341 XtPointer client_data;
7342 String action_name;
7343 XEvent *event;
7344 String *params;
7345 Cardinal *num_params;
7347 int scroll_bar_p;
7348 char *end_action;
7350 #ifdef USE_MOTIF
7351 scroll_bar_p = XmIsScrollBar (widget);
7352 end_action = "Release";
7353 #else /* !USE_MOTIF i.e. use Xaw */
7354 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7355 end_action = "EndScroll";
7356 #endif /* USE_MOTIF */
7358 if (scroll_bar_p
7359 && strcmp (action_name, end_action) == 0
7360 && WINDOWP (window_being_scrolled))
7362 struct window *w;
7364 x_send_scroll_bar_event (window_being_scrolled,
7365 scroll_bar_end_scroll, 0, 0);
7366 w = XWINDOW (window_being_scrolled);
7367 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7368 window_being_scrolled = Qnil;
7369 last_scroll_bar_part = -1;
7371 /* Xt timeouts no longer needed. */
7372 toolkit_scroll_bar_interaction = 0;
7377 /* Send a client message with message type Xatom_Scrollbar for a
7378 scroll action to the frame of WINDOW. PART is a value identifying
7379 the part of the scroll bar that was clicked on. PORTION is the
7380 amount to scroll of a whole of WHOLE. */
7382 static void
7383 x_send_scroll_bar_event (window, part, portion, whole)
7384 Lisp_Object window;
7385 int part, portion, whole;
7387 XEvent event;
7388 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7389 struct frame *f = XFRAME (XWINDOW (window)->frame);
7391 /* Construct a ClientMessage event to send to the frame. */
7392 ev->type = ClientMessage;
7393 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7394 ev->display = FRAME_X_DISPLAY (f);
7395 ev->window = FRAME_X_WINDOW (f);
7396 ev->format = 32;
7397 ev->data.l[0] = (long) window;
7398 ev->data.l[1] = (long) part;
7399 ev->data.l[2] = (long) 0;
7400 ev->data.l[3] = (long) portion;
7401 ev->data.l[4] = (long) whole;
7403 /* Make Xt timeouts work while the scroll bar is active. */
7404 toolkit_scroll_bar_interaction = 1;
7406 /* Setting the event mask to zero means that the message will
7407 be sent to the client that created the window, and if that
7408 window no longer exists, no event will be sent. */
7409 BLOCK_INPUT;
7410 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7411 UNBLOCK_INPUT;
7415 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7416 in *IEVENT. */
7418 static void
7419 x_scroll_bar_to_input_event (event, ievent)
7420 XEvent *event;
7421 struct input_event *ievent;
7423 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7424 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7425 struct frame *f = XFRAME (XWINDOW (window)->frame);
7427 ievent->kind = scroll_bar_click;
7428 ievent->frame_or_window = window;
7429 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7430 ievent->part = ev->data.l[1];
7431 ievent->code = ev->data.l[2];
7432 ievent->x = make_number ((int) ev->data.l[3]);
7433 ievent->y = make_number ((int) ev->data.l[4]);
7434 ievent->modifiers = 0;
7438 #ifdef USE_MOTIF
7440 /* Minimum and maximum values used for Motif scroll bars. */
7442 #define XM_SB_MIN 1
7443 #define XM_SB_MAX 10000000
7444 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7447 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7448 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7449 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7451 static void
7452 xm_scroll_callback (widget, client_data, call_data)
7453 Widget widget;
7454 XtPointer client_data, call_data;
7456 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7457 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7458 double percent;
7459 int part = -1, whole = 0, portion = 0;
7461 switch (cs->reason)
7463 case XmCR_DECREMENT:
7464 bar->dragging = Qnil;
7465 part = scroll_bar_up_arrow;
7466 break;
7468 case XmCR_INCREMENT:
7469 bar->dragging = Qnil;
7470 part = scroll_bar_down_arrow;
7471 break;
7473 case XmCR_PAGE_DECREMENT:
7474 bar->dragging = Qnil;
7475 part = scroll_bar_above_handle;
7476 break;
7478 case XmCR_PAGE_INCREMENT:
7479 bar->dragging = Qnil;
7480 part = scroll_bar_below_handle;
7481 break;
7483 case XmCR_TO_TOP:
7484 bar->dragging = Qnil;
7485 part = scroll_bar_to_top;
7486 break;
7488 case XmCR_TO_BOTTOM:
7489 bar->dragging = Qnil;
7490 part = scroll_bar_to_bottom;
7491 break;
7493 case XmCR_DRAG:
7495 int slider_size;
7496 int dragging_down_p = (INTEGERP (bar->dragging)
7497 && XINT (bar->dragging) <= cs->value);
7499 /* Get the slider size. */
7500 BLOCK_INPUT;
7501 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7502 UNBLOCK_INPUT;
7504 /* At the max position of the scroll bar, do a line-wise
7505 movement. Without doing anything, the LessTif scroll bar
7506 calls us with the same cs->value again and again. If we
7507 want to make sure that we can reach the end of the buffer,
7508 we have to do something.
7510 Implementation note: setting bar->dragging always to
7511 cs->value gives a smoother movement at the max position.
7512 Setting it to nil when doing line-wise movement gives
7513 a better slider behavior. */
7515 if (cs->value + slider_size == XM_SB_MAX
7516 || (dragging_down_p
7517 && last_scroll_bar_part == scroll_bar_down_arrow))
7519 part = scroll_bar_down_arrow;
7520 bar->dragging = Qnil;
7522 else
7524 whole = XM_SB_RANGE;
7525 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7526 part = scroll_bar_handle;
7527 bar->dragging = make_number (cs->value);
7530 break;
7532 case XmCR_VALUE_CHANGED:
7533 break;
7536 if (part >= 0)
7538 window_being_scrolled = bar->window;
7539 last_scroll_bar_part = part;
7540 x_send_scroll_bar_event (bar->window, part, portion, whole);
7545 #else /* !USE_MOTIF, i.e. Xaw. */
7548 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7549 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7550 scroll bar struct. CALL_DATA is a pointer to a float saying where
7551 the thumb is. */
7553 static void
7554 xaw_jump_callback (widget, client_data, call_data)
7555 Widget widget;
7556 XtPointer client_data, call_data;
7558 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7559 float top = *(float *) call_data;
7560 float shown;
7561 int whole, portion, height;
7562 int part;
7564 /* Get the size of the thumb, a value between 0 and 1. */
7565 BLOCK_INPUT;
7566 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7567 UNBLOCK_INPUT;
7569 whole = 10000000;
7570 portion = shown < 1 ? top * whole : 0;
7572 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7573 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7574 the bottom, so we force the scrolling whenever we see that we're
7575 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7576 we try to ensure that we always stay two pixels away from the
7577 bottom). */
7578 part = scroll_bar_down_arrow;
7579 else
7580 part = scroll_bar_handle;
7582 window_being_scrolled = bar->window;
7583 bar->dragging = make_number (portion);
7584 last_scroll_bar_part = part;
7585 x_send_scroll_bar_event (bar->window, part, portion, whole);
7589 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7590 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7591 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7592 the scroll bar. CALL_DATA is an integer specifying the action that
7593 has taken place. It's magnitude is in the range 0..height of the
7594 scroll bar. Negative values mean scroll towards buffer start.
7595 Values < height of scroll bar mean line-wise movement. */
7597 static void
7598 xaw_scroll_callback (widget, client_data, call_data)
7599 Widget widget;
7600 XtPointer client_data, call_data;
7602 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7603 int position = (int) call_data;
7604 Dimension height;
7605 int part;
7607 /* Get the height of the scroll bar. */
7608 BLOCK_INPUT;
7609 XtVaGetValues (widget, XtNheight, &height, NULL);
7610 UNBLOCK_INPUT;
7612 if (abs (position) >= height)
7613 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7615 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7616 it maps line-movement to call_data = max(5, height/20). */
7617 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7618 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7619 else
7620 part = scroll_bar_move_ratio;
7622 window_being_scrolled = bar->window;
7623 bar->dragging = Qnil;
7624 last_scroll_bar_part = part;
7625 x_send_scroll_bar_event (bar->window, part, position, height);
7629 #endif /* not USE_MOTIF */
7632 /* Create the widget for scroll bar BAR on frame F. Record the widget
7633 and X window of the scroll bar in BAR. */
7635 static void
7636 x_create_toolkit_scroll_bar (f, bar)
7637 struct frame *f;
7638 struct scroll_bar *bar;
7640 Window xwindow;
7641 Widget widget;
7642 Arg av[20];
7643 int ac = 0;
7644 char *scroll_bar_name = "verticalScrollBar";
7645 unsigned long pixel;
7647 BLOCK_INPUT;
7649 #ifdef USE_MOTIF
7650 /* LessTif 0.85, problems:
7652 1. When the mouse if over the scroll bar, the scroll bar will
7653 get keyboard events. I didn't find a way to turn this off.
7655 2. Do we have to explicitly set the cursor to get an arrow
7656 cursor (see below)? */
7658 /* Set resources. Create the widget. */
7659 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7660 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7661 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7662 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7663 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7664 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7665 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7667 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7668 if (pixel != -1)
7670 XtSetArg (av[ac], XmNforeground, pixel);
7671 ++ac;
7674 pixel = f->output_data.x->scroll_bar_background_pixel;
7675 if (pixel != -1)
7677 XtSetArg (av[ac], XmNbackground, pixel);
7678 ++ac;
7681 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7682 scroll_bar_name, av, ac);
7684 /* Add one callback for everything that can happen. */
7685 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7686 (XtPointer) bar);
7687 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7688 (XtPointer) bar);
7689 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7690 (XtPointer) bar);
7691 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7692 (XtPointer) bar);
7693 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7694 (XtPointer) bar);
7695 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7696 (XtPointer) bar);
7697 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7698 (XtPointer) bar);
7700 /* Realize the widget. Only after that is the X window created. */
7701 XtRealizeWidget (widget);
7703 /* Set the cursor to an arrow. I didn't find a resource to do that.
7704 And I'm wondering why it hasn't an arrow cursor by default. */
7705 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7706 f->output_data.x->nontext_cursor);
7708 #else /* !USE_MOTIF i.e. use Xaw */
7710 /* Set resources. Create the widget. The background of the
7711 Xaw3d scroll bar widget is a little bit light for my taste.
7712 We don't alter it here to let users change it according
7713 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7714 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7715 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7716 /* For smoother scrolling with Xaw3d -sm */
7717 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7718 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7720 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7721 if (pixel != -1)
7723 XtSetArg (av[ac], XtNforeground, pixel);
7724 ++ac;
7727 pixel = f->output_data.x->scroll_bar_background_pixel;
7728 if (pixel != -1)
7730 XtSetArg (av[ac], XtNbackground, pixel);
7731 ++ac;
7734 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7735 f->output_data.x->edit_widget, av, ac);
7738 char *initial = "";
7739 char *val = initial;
7740 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7741 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7742 if (val == initial)
7743 { /* ARROW_SCROLL */
7744 xaw3d_arrow_scroll = True;
7745 /* Isn't that just a personal preference ? -sm */
7746 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7750 /* Define callbacks. */
7751 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7752 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
7753 (XtPointer) bar);
7755 /* Realize the widget. Only after that is the X window created. */
7756 XtRealizeWidget (widget);
7758 #endif /* !USE_MOTIF */
7760 /* Install an action hook that let's us detect when the user
7761 finishes interacting with a scroll bar. */
7762 if (action_hook_id == 0)
7763 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7765 /* Remember X window and widget in the scroll bar vector. */
7766 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7767 xwindow = XtWindow (widget);
7768 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7770 UNBLOCK_INPUT;
7774 /* Set the thumb size and position of scroll bar BAR. We are currently
7775 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7777 static void
7778 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7779 struct scroll_bar *bar;
7780 int portion, position, whole;
7782 float top, shown;
7783 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7785 if (whole == 0)
7786 top = 0, shown = 1;
7787 else
7789 top = (float) position / whole;
7790 shown = (float) portion / whole;
7793 BLOCK_INPUT;
7795 #ifdef USE_MOTIF
7797 int size, value;
7798 Boolean arrow1_selected, arrow2_selected;
7799 unsigned char flags;
7800 XmScrollBarWidget sb;
7802 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7803 is the scroll bar's maximum and MIN is the scroll bar's minimum
7804 value. */
7805 size = shown * XM_SB_RANGE;
7806 size = min (size, XM_SB_RANGE);
7807 size = max (size, 1);
7809 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7810 value = top * XM_SB_RANGE;
7811 value = min (value, XM_SB_MAX - size);
7812 value = max (value, XM_SB_MIN);
7814 /* LessTif: Calling XmScrollBarSetValues after an increment or
7815 decrement turns off auto-repeat LessTif-internally. This can
7816 be seen in ScrollBar.c which resets Arrow1Selected and
7817 Arrow2Selected. It also sets internal flags so that LessTif
7818 believes the mouse is in the slider. We either have to change
7819 our code, or work around that by accessing private data. */
7821 sb = (XmScrollBarWidget) widget;
7822 arrow1_selected = sb->scrollBar.arrow1_selected;
7823 arrow2_selected = sb->scrollBar.arrow2_selected;
7824 flags = sb->scrollBar.flags;
7826 if (NILP (bar->dragging))
7827 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7828 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7829 /* This has the negative side effect that the slider value is
7830 not what it would be if we scrolled here using line-wise or
7831 page-wise movement. */
7832 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7833 else
7835 /* If currently dragging, only update the slider size.
7836 This reduces flicker effects. */
7837 int old_value, old_size, increment, page_increment;
7839 XmScrollBarGetValues (widget, &old_value, &old_size,
7840 &increment, &page_increment);
7841 XmScrollBarSetValues (widget, old_value,
7842 min (size, XM_SB_RANGE - old_value),
7843 0, 0, False);
7846 sb->scrollBar.arrow1_selected = arrow1_selected;
7847 sb->scrollBar.arrow2_selected = arrow2_selected;
7848 sb->scrollBar.flags = flags;
7850 #else /* !USE_MOTIF i.e. use Xaw */
7852 float old_top, old_shown;
7853 Dimension height;
7854 XtVaGetValues (widget,
7855 XtNtopOfThumb, &old_top,
7856 XtNshown, &old_shown,
7857 XtNheight, &height,
7858 NULL);
7860 /* Massage the top+shown values. */
7861 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7862 top = max (0, min (1, top));
7863 else
7864 top = old_top;
7865 /* Keep two pixels available for moving the thumb down. */
7866 shown = max (0, min (1 - top - (2.0 / height), shown));
7868 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7869 check that your system's configuration file contains a define
7870 for `NARROWPROTO'. See s/freebsd.h for an example. */
7871 if (top != old_top || shown != old_shown)
7873 if (NILP (bar->dragging))
7874 XawScrollbarSetThumb (widget, top, shown);
7875 else
7877 #ifdef HAVE_XAW3D
7878 ScrollbarWidget sb = (ScrollbarWidget) widget;
7879 int scroll_mode;
7881 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7882 if (xaw3d_arrow_scroll)
7884 /* Xaw3d stupidly ignores resize requests while dragging
7885 so we have to make it believe it's not in dragging mode. */
7886 scroll_mode = sb->scrollbar.scroll_mode;
7887 if (scroll_mode == 2)
7888 sb->scrollbar.scroll_mode = 0;
7890 #endif
7891 /* Try to make the scrolling a tad smoother. */
7892 if (!xaw3d_pick_top)
7893 shown = min (shown, old_shown);
7895 XawScrollbarSetThumb (widget, top, shown);
7897 #ifdef HAVE_XAW3D
7898 if (xaw3d_arrow_scroll && scroll_mode == 2)
7899 sb->scrollbar.scroll_mode = scroll_mode;
7900 #endif
7904 #endif /* !USE_MOTIF */
7906 UNBLOCK_INPUT;
7909 #endif /* USE_TOOLKIT_SCROLL_BARS */
7913 /************************************************************************
7914 Scroll bars, general
7915 ************************************************************************/
7917 /* Create a scroll bar and return the scroll bar vector for it. W is
7918 the Emacs window on which to create the scroll bar. TOP, LEFT,
7919 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7920 scroll bar. */
7922 static struct scroll_bar *
7923 x_scroll_bar_create (w, top, left, width, height)
7924 struct window *w;
7925 int top, left, width, height;
7927 struct frame *f = XFRAME (w->frame);
7928 struct scroll_bar *bar
7929 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7931 BLOCK_INPUT;
7933 #if USE_TOOLKIT_SCROLL_BARS
7934 x_create_toolkit_scroll_bar (f, bar);
7935 #else /* not USE_TOOLKIT_SCROLL_BARS */
7937 XSetWindowAttributes a;
7938 unsigned long mask;
7939 Window window;
7941 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7942 if (a.background_pixel == -1)
7943 a.background_pixel = f->output_data.x->background_pixel;
7945 a.event_mask = (ButtonPressMask | ButtonReleaseMask
7946 | ButtonMotionMask | PointerMotionHintMask
7947 | ExposureMask);
7948 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
7950 mask = (CWBackPixel | CWEventMask | CWCursor);
7952 /* Clear the area of W that will serve as a scroll bar. This is
7953 for the case that a window has been split horizontally. In
7954 this case, no clear_frame is generated to reduce flickering. */
7955 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7956 left, top, width,
7957 window_box_height (w), False);
7959 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7960 /* Position and size of scroll bar. */
7961 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7962 top,
7963 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7964 height,
7965 /* Border width, depth, class, and visual. */
7967 CopyFromParent,
7968 CopyFromParent,
7969 CopyFromParent,
7970 /* Attributes. */
7971 mask, &a);
7972 SET_SCROLL_BAR_X_WINDOW (bar, window);
7974 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7976 XSETWINDOW (bar->window, w);
7977 XSETINT (bar->top, top);
7978 XSETINT (bar->left, left);
7979 XSETINT (bar->width, width);
7980 XSETINT (bar->height, height);
7981 XSETINT (bar->start, 0);
7982 XSETINT (bar->end, 0);
7983 bar->dragging = Qnil;
7985 /* Add bar to its frame's list of scroll bars. */
7986 bar->next = FRAME_SCROLL_BARS (f);
7987 bar->prev = Qnil;
7988 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7989 if (!NILP (bar->next))
7990 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7992 /* Map the window/widget. */
7993 #if USE_TOOLKIT_SCROLL_BARS
7994 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
7995 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7996 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7997 top,
7998 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7999 height, 0);
8000 #else /* not USE_TOOLKIT_SCROLL_BARS */
8001 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8002 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8004 UNBLOCK_INPUT;
8005 return bar;
8009 /* Draw BAR's handle in the proper position.
8011 If the handle is already drawn from START to END, don't bother
8012 redrawing it, unless REBUILD is non-zero; in that case, always
8013 redraw it. (REBUILD is handy for drawing the handle after expose
8014 events.)
8016 Normally, we want to constrain the start and end of the handle to
8017 fit inside its rectangle, but if the user is dragging the scroll
8018 bar handle, we want to let them drag it down all the way, so that
8019 the bar's top is as far down as it goes; otherwise, there's no way
8020 to move to the very end of the buffer. */
8022 #ifndef USE_TOOLKIT_SCROLL_BARS
8024 static void
8025 x_scroll_bar_set_handle (bar, start, end, rebuild)
8026 struct scroll_bar *bar;
8027 int start, end;
8028 int rebuild;
8030 int dragging = ! NILP (bar->dragging);
8031 Window w = SCROLL_BAR_X_WINDOW (bar);
8032 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8033 GC gc = f->output_data.x->normal_gc;
8035 /* If the display is already accurate, do nothing. */
8036 if (! rebuild
8037 && start == XINT (bar->start)
8038 && end == XINT (bar->end))
8039 return;
8041 BLOCK_INPUT;
8044 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8045 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8046 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8048 /* Make sure the values are reasonable, and try to preserve
8049 the distance between start and end. */
8051 int length = end - start;
8053 if (start < 0)
8054 start = 0;
8055 else if (start > top_range)
8056 start = top_range;
8057 end = start + length;
8059 if (end < start)
8060 end = start;
8061 else if (end > top_range && ! dragging)
8062 end = top_range;
8065 /* Store the adjusted setting in the scroll bar. */
8066 XSETINT (bar->start, start);
8067 XSETINT (bar->end, end);
8069 /* Clip the end position, just for display. */
8070 if (end > top_range)
8071 end = top_range;
8073 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8074 below top positions, to make sure the handle is always at least
8075 that many pixels tall. */
8076 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8078 /* Draw the empty space above the handle. Note that we can't clear
8079 zero-height areas; that means "clear to end of window." */
8080 if (0 < start)
8081 XClearArea (FRAME_X_DISPLAY (f), w,
8083 /* x, y, width, height, and exposures. */
8084 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8085 VERTICAL_SCROLL_BAR_TOP_BORDER,
8086 inside_width, start,
8087 False);
8089 /* Change to proper foreground color if one is specified. */
8090 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8091 XSetForeground (FRAME_X_DISPLAY (f), gc,
8092 f->output_data.x->scroll_bar_foreground_pixel);
8094 /* Draw the handle itself. */
8095 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8097 /* x, y, width, height */
8098 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8099 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8100 inside_width, end - start);
8102 /* Restore the foreground color of the GC if we changed it above. */
8103 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8104 XSetForeground (FRAME_X_DISPLAY (f), gc,
8105 f->output_data.x->foreground_pixel);
8107 /* Draw the empty space below the handle. Note that we can't
8108 clear zero-height areas; that means "clear to end of window." */
8109 if (end < inside_height)
8110 XClearArea (FRAME_X_DISPLAY (f), w,
8112 /* x, y, width, height, and exposures. */
8113 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8114 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8115 inside_width, inside_height - end,
8116 False);
8120 UNBLOCK_INPUT;
8123 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8125 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8126 nil. */
8128 static void
8129 x_scroll_bar_remove (bar)
8130 struct scroll_bar *bar;
8132 BLOCK_INPUT;
8134 #if USE_TOOLKIT_SCROLL_BARS
8135 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8136 #else /* not USE_TOOLKIT_SCROLL_BARS */
8138 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8139 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8141 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8143 /* Disassociate this scroll bar from its window. */
8144 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8146 UNBLOCK_INPUT;
8150 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8151 that we are displaying PORTION characters out of a total of WHOLE
8152 characters, starting at POSITION. If WINDOW has no scroll bar,
8153 create one. */
8155 static void
8156 XTset_vertical_scroll_bar (w, portion, whole, position)
8157 struct window *w;
8158 int portion, whole, position;
8160 struct frame *f = XFRAME (w->frame);
8161 struct scroll_bar *bar;
8162 int top, height, left, sb_left, width, sb_width;
8163 int window_x, window_y, window_width, window_height;
8165 /* Get window dimensions. */
8166 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8167 top = window_y;
8168 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8169 height = window_height;
8171 /* Compute the left edge of the scroll bar area. */
8172 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8173 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8174 else
8175 left = XFASTINT (w->left);
8176 left *= CANON_X_UNIT (f);
8177 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8179 /* Compute the width of the scroll bar which might be less than
8180 the width of the area reserved for the scroll bar. */
8181 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8182 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8183 else
8184 sb_width = width;
8186 /* Compute the left edge of the scroll bar. */
8187 #ifdef USE_TOOLKIT_SCROLL_BARS
8188 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8189 sb_left = left + width - sb_width - (width - sb_width) / 2;
8190 else
8191 sb_left = left + (width - sb_width) / 2;
8192 #else
8193 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8194 sb_left = left + width - sb_width;
8195 else
8196 sb_left = left;
8197 #endif
8199 /* Does the scroll bar exist yet? */
8200 if (NILP (w->vertical_scroll_bar))
8202 BLOCK_INPUT;
8203 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8204 left, top, width, height, False);
8205 UNBLOCK_INPUT;
8206 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8208 else
8210 /* It may just need to be moved and resized. */
8211 unsigned int mask = 0;
8213 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8215 BLOCK_INPUT;
8217 if (sb_left != XINT (bar->left))
8218 mask |= CWX;
8219 if (top != XINT (bar->top))
8220 mask |= CWY;
8221 if (sb_width != XINT (bar->width))
8222 mask |= CWWidth;
8223 if (height != XINT (bar->height))
8224 mask |= CWHeight;
8226 #ifdef USE_TOOLKIT_SCROLL_BARS
8228 /* Since toolkit scroll bars are smaller than the space reserved
8229 for them on the frame, we have to clear "under" them. */
8230 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8231 left, top, width, height, False);
8233 /* Move/size the scroll bar widget. */
8234 if (mask)
8235 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8236 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8237 top,
8238 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8239 height, 0);
8241 #else /* not USE_TOOLKIT_SCROLL_BARS */
8243 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8245 /* Clear areas not covered by the scroll bar. This makes sure a
8246 previous mode line display is cleared after C-x 2 C-x 1, for
8247 example. Non-toolkit scroll bars are as wide as the area
8248 reserved for scroll bars - trim at both sides. */
8249 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8250 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8251 height, False);
8252 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8253 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8254 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8255 height, False);
8258 /* Move/size the scroll bar window. */
8259 if (mask)
8261 XWindowChanges wc;
8263 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8264 wc.y = top;
8265 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8266 wc.height = height;
8267 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8268 mask, &wc);
8271 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8273 /* Remember new settings. */
8274 XSETINT (bar->left, sb_left);
8275 XSETINT (bar->top, top);
8276 XSETINT (bar->width, sb_width);
8277 XSETINT (bar->height, height);
8279 UNBLOCK_INPUT;
8282 #if USE_TOOLKIT_SCROLL_BARS
8283 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8284 #else /* not USE_TOOLKIT_SCROLL_BARS */
8285 /* Set the scroll bar's current state, unless we're currently being
8286 dragged. */
8287 if (NILP (bar->dragging))
8289 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8291 if (whole == 0)
8292 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8293 else
8295 int start = ((double) position * top_range) / whole;
8296 int end = ((double) (position + portion) * top_range) / whole;
8297 x_scroll_bar_set_handle (bar, start, end, 0);
8300 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8302 XSETVECTOR (w->vertical_scroll_bar, bar);
8306 /* The following three hooks are used when we're doing a thorough
8307 redisplay of the frame. We don't explicitly know which scroll bars
8308 are going to be deleted, because keeping track of when windows go
8309 away is a real pain - "Can you say set-window-configuration, boys
8310 and girls?" Instead, we just assert at the beginning of redisplay
8311 that *all* scroll bars are to be removed, and then save a scroll bar
8312 from the fiery pit when we actually redisplay its window. */
8314 /* Arrange for all scroll bars on FRAME to be removed at the next call
8315 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8316 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8318 static void
8319 XTcondemn_scroll_bars (frame)
8320 FRAME_PTR frame;
8322 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8323 while (! NILP (FRAME_SCROLL_BARS (frame)))
8325 Lisp_Object bar;
8326 bar = FRAME_SCROLL_BARS (frame);
8327 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8328 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8329 XSCROLL_BAR (bar)->prev = Qnil;
8330 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8331 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8332 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8336 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8337 Note that WINDOW isn't necessarily condemned at all. */
8338 static void
8339 XTredeem_scroll_bar (window)
8340 struct window *window;
8342 struct scroll_bar *bar;
8344 /* We can't redeem this window's scroll bar if it doesn't have one. */
8345 if (NILP (window->vertical_scroll_bar))
8346 abort ();
8348 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8350 /* Unlink it from the condemned list. */
8352 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8354 if (NILP (bar->prev))
8356 /* If the prev pointer is nil, it must be the first in one of
8357 the lists. */
8358 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8359 /* It's not condemned. Everything's fine. */
8360 return;
8361 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8362 window->vertical_scroll_bar))
8363 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8364 else
8365 /* If its prev pointer is nil, it must be at the front of
8366 one or the other! */
8367 abort ();
8369 else
8370 XSCROLL_BAR (bar->prev)->next = bar->next;
8372 if (! NILP (bar->next))
8373 XSCROLL_BAR (bar->next)->prev = bar->prev;
8375 bar->next = FRAME_SCROLL_BARS (f);
8376 bar->prev = Qnil;
8377 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8378 if (! NILP (bar->next))
8379 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8383 /* Remove all scroll bars on FRAME that haven't been saved since the
8384 last call to `*condemn_scroll_bars_hook'. */
8386 static void
8387 XTjudge_scroll_bars (f)
8388 FRAME_PTR f;
8390 Lisp_Object bar, next;
8392 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8394 /* Clear out the condemned list now so we won't try to process any
8395 more events on the hapless scroll bars. */
8396 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8398 for (; ! NILP (bar); bar = next)
8400 struct scroll_bar *b = XSCROLL_BAR (bar);
8402 x_scroll_bar_remove (b);
8404 next = b->next;
8405 b->next = b->prev = Qnil;
8408 /* Now there should be no references to the condemned scroll bars,
8409 and they should get garbage-collected. */
8413 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8414 is a no-op when using toolkit scroll bars.
8416 This may be called from a signal handler, so we have to ignore GC
8417 mark bits. */
8419 static void
8420 x_scroll_bar_expose (bar, event)
8421 struct scroll_bar *bar;
8422 XEvent *event;
8424 #ifndef USE_TOOLKIT_SCROLL_BARS
8426 Window w = SCROLL_BAR_X_WINDOW (bar);
8427 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8428 GC gc = f->output_data.x->normal_gc;
8429 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8431 BLOCK_INPUT;
8433 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8435 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8436 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8438 /* x, y, width, height */
8439 0, 0,
8440 XINT (bar->width) - 1 - width_trim - width_trim,
8441 XINT (bar->height) - 1);
8443 UNBLOCK_INPUT;
8445 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8448 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8449 is set to something other than no_event, it is enqueued.
8451 This may be called from a signal handler, so we have to ignore GC
8452 mark bits. */
8454 #ifndef USE_TOOLKIT_SCROLL_BARS
8456 static void
8457 x_scroll_bar_handle_click (bar, event, emacs_event)
8458 struct scroll_bar *bar;
8459 XEvent *event;
8460 struct input_event *emacs_event;
8462 if (! GC_WINDOWP (bar->window))
8463 abort ();
8465 emacs_event->kind = scroll_bar_click;
8466 emacs_event->code = event->xbutton.button - Button1;
8467 emacs_event->modifiers
8468 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8469 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8470 event->xbutton.state)
8471 | (event->type == ButtonRelease
8472 ? up_modifier
8473 : down_modifier));
8474 emacs_event->frame_or_window = bar->window;
8475 emacs_event->timestamp = event->xbutton.time;
8477 #if 0
8478 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8479 int internal_height
8480 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8481 #endif
8482 int top_range
8483 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8484 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8486 if (y < 0) y = 0;
8487 if (y > top_range) y = top_range;
8489 if (y < XINT (bar->start))
8490 emacs_event->part = scroll_bar_above_handle;
8491 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8492 emacs_event->part = scroll_bar_handle;
8493 else
8494 emacs_event->part = scroll_bar_below_handle;
8496 /* Just because the user has clicked on the handle doesn't mean
8497 they want to drag it. Lisp code needs to be able to decide
8498 whether or not we're dragging. */
8499 #if 0
8500 /* If the user has just clicked on the handle, record where they're
8501 holding it. */
8502 if (event->type == ButtonPress
8503 && emacs_event->part == scroll_bar_handle)
8504 XSETINT (bar->dragging, y - XINT (bar->start));
8505 #endif
8507 /* If the user has released the handle, set it to its final position. */
8508 if (event->type == ButtonRelease
8509 && ! NILP (bar->dragging))
8511 int new_start = y - XINT (bar->dragging);
8512 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8514 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8515 bar->dragging = Qnil;
8518 /* Same deal here as the other #if 0. */
8519 #if 0
8520 /* Clicks on the handle are always reported as occurring at the top of
8521 the handle. */
8522 if (emacs_event->part == scroll_bar_handle)
8523 emacs_event->x = bar->start;
8524 else
8525 XSETINT (emacs_event->x, y);
8526 #else
8527 XSETINT (emacs_event->x, y);
8528 #endif
8530 XSETINT (emacs_event->y, top_range);
8534 /* Handle some mouse motion while someone is dragging the scroll bar.
8536 This may be called from a signal handler, so we have to ignore GC
8537 mark bits. */
8539 static void
8540 x_scroll_bar_note_movement (bar, event)
8541 struct scroll_bar *bar;
8542 XEvent *event;
8544 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8546 last_mouse_movement_time = event->xmotion.time;
8548 f->mouse_moved = 1;
8549 XSETVECTOR (last_mouse_scroll_bar, bar);
8551 /* If we're dragging the bar, display it. */
8552 if (! GC_NILP (bar->dragging))
8554 /* Where should the handle be now? */
8555 int new_start = event->xmotion.y - XINT (bar->dragging);
8557 if (new_start != XINT (bar->start))
8559 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8561 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8566 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8568 /* Return information to the user about the current position of the mouse
8569 on the scroll bar. */
8571 static void
8572 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8573 FRAME_PTR *fp;
8574 Lisp_Object *bar_window;
8575 enum scroll_bar_part *part;
8576 Lisp_Object *x, *y;
8577 unsigned long *time;
8579 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8580 Window w = SCROLL_BAR_X_WINDOW (bar);
8581 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8582 int win_x, win_y;
8583 Window dummy_window;
8584 int dummy_coord;
8585 unsigned int dummy_mask;
8587 BLOCK_INPUT;
8589 /* Get the mouse's position relative to the scroll bar window, and
8590 report that. */
8591 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8593 /* Root, child, root x and root y. */
8594 &dummy_window, &dummy_window,
8595 &dummy_coord, &dummy_coord,
8597 /* Position relative to scroll bar. */
8598 &win_x, &win_y,
8600 /* Mouse buttons and modifier keys. */
8601 &dummy_mask))
8603 else
8605 #if 0
8606 int inside_height
8607 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8608 #endif
8609 int top_range
8610 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8612 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8614 if (! NILP (bar->dragging))
8615 win_y -= XINT (bar->dragging);
8617 if (win_y < 0)
8618 win_y = 0;
8619 if (win_y > top_range)
8620 win_y = top_range;
8622 *fp = f;
8623 *bar_window = bar->window;
8625 if (! NILP (bar->dragging))
8626 *part = scroll_bar_handle;
8627 else if (win_y < XINT (bar->start))
8628 *part = scroll_bar_above_handle;
8629 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8630 *part = scroll_bar_handle;
8631 else
8632 *part = scroll_bar_below_handle;
8634 XSETINT (*x, win_y);
8635 XSETINT (*y, top_range);
8637 f->mouse_moved = 0;
8638 last_mouse_scroll_bar = Qnil;
8641 *time = last_mouse_movement_time;
8643 UNBLOCK_INPUT;
8647 /* The screen has been cleared so we may have changed foreground or
8648 background colors, and the scroll bars may need to be redrawn.
8649 Clear out the scroll bars, and ask for expose events, so we can
8650 redraw them. */
8652 void
8653 x_scroll_bar_clear (f)
8654 FRAME_PTR f;
8656 #ifndef USE_TOOLKIT_SCROLL_BARS
8657 Lisp_Object bar;
8659 /* We can have scroll bars even if this is 0,
8660 if we just turned off scroll bar mode.
8661 But in that case we should not clear them. */
8662 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8663 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8664 bar = XSCROLL_BAR (bar)->next)
8665 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8666 0, 0, 0, 0, True);
8667 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8670 /* This processes Expose events from the menu-bar specific X event
8671 loop in xmenu.c. This allows to redisplay the frame if necessary
8672 when handling menu-bar or pop-up items. */
8675 process_expose_from_menu (event)
8676 XEvent event;
8678 FRAME_PTR f;
8679 struct x_display_info *dpyinfo;
8680 int frame_exposed_p = 0;
8682 BLOCK_INPUT;
8684 dpyinfo = x_display_info_for_display (event.xexpose.display);
8685 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8686 if (f)
8688 if (f->async_visible == 0)
8690 f->async_visible = 1;
8691 f->async_iconified = 0;
8692 f->output_data.x->has_been_visible = 1;
8693 SET_FRAME_GARBAGED (f);
8695 else
8697 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8698 event.xexpose.x, event.xexpose.y,
8699 event.xexpose.width, event.xexpose.height);
8700 frame_exposed_p = 1;
8703 else
8705 struct scroll_bar *bar
8706 = x_window_to_scroll_bar (event.xexpose.window);
8708 if (bar)
8709 x_scroll_bar_expose (bar, &event);
8712 UNBLOCK_INPUT;
8713 return frame_exposed_p;
8716 /* Define a queue to save up SelectionRequest events for later handling. */
8718 struct selection_event_queue
8720 XEvent event;
8721 struct selection_event_queue *next;
8724 static struct selection_event_queue *queue;
8726 /* Nonzero means queue up certain events--don't process them yet. */
8728 static int x_queue_selection_requests;
8730 /* Queue up an X event *EVENT, to be processed later. */
8732 static void
8733 x_queue_event (f, event)
8734 FRAME_PTR f;
8735 XEvent *event;
8737 struct selection_event_queue *queue_tmp
8738 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8740 if (queue_tmp != NULL)
8742 queue_tmp->event = *event;
8743 queue_tmp->next = queue;
8744 queue = queue_tmp;
8748 /* Take all the queued events and put them back
8749 so that they get processed afresh. */
8751 static void
8752 x_unqueue_events (display)
8753 Display *display;
8755 while (queue != NULL)
8757 struct selection_event_queue *queue_tmp = queue;
8758 XPutBackEvent (display, &queue_tmp->event);
8759 queue = queue_tmp->next;
8760 xfree ((char *)queue_tmp);
8764 /* Start queuing SelectionRequest events. */
8766 void
8767 x_start_queuing_selection_requests (display)
8768 Display *display;
8770 x_queue_selection_requests++;
8773 /* Stop queuing SelectionRequest events. */
8775 void
8776 x_stop_queuing_selection_requests (display)
8777 Display *display;
8779 x_queue_selection_requests--;
8780 x_unqueue_events (display);
8783 /* The main X event-reading loop - XTread_socket. */
8785 /* Time stamp of enter window event. This is only used by XTread_socket,
8786 but we have to put it out here, since static variables within functions
8787 sometimes don't work. */
8789 static Time enter_timestamp;
8791 /* This holds the state XLookupString needs to implement dead keys
8792 and other tricks known as "compose processing". _X Window System_
8793 says that a portable program can't use this, but Stephen Gildea assures
8794 me that letting the compiler initialize it to zeros will work okay.
8796 This must be defined outside of XTread_socket, for the same reasons
8797 given for enter_time stamp, above. */
8799 static XComposeStatus compose_status;
8801 /* Record the last 100 characters stored
8802 to help debug the loss-of-chars-during-GC problem. */
8804 static int temp_index;
8805 static short temp_buffer[100];
8807 /* Set this to nonzero to fake an "X I/O error"
8808 on a particular display. */
8810 struct x_display_info *XTread_socket_fake_io_error;
8812 /* When we find no input here, we occasionally do a no-op command
8813 to verify that the X server is still running and we can still talk with it.
8814 We try all the open displays, one by one.
8815 This variable is used for cycling thru the displays. */
8817 static struct x_display_info *next_noop_dpyinfo;
8819 #define SET_SAVED_MENU_EVENT(size) \
8820 do \
8822 if (f->output_data.x->saved_menu_event == 0) \
8823 f->output_data.x->saved_menu_event \
8824 = (XEvent *) xmalloc (sizeof (XEvent)); \
8825 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8826 if (numchars >= 1) \
8828 bufp->kind = menu_bar_activate_event; \
8829 XSETFRAME (bufp->frame_or_window, f); \
8830 bufp++; \
8831 count++; \
8832 numchars--; \
8835 while (0)
8837 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8838 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8840 /* Read events coming from the X server.
8841 This routine is called by the SIGIO handler.
8842 We return as soon as there are no more events to be read.
8844 Events representing keys are stored in buffer BUFP,
8845 which can hold up to NUMCHARS characters.
8846 We return the number of characters stored into the buffer,
8847 thus pretending to be `read'.
8849 EXPECTED is nonzero if the caller knows input is available. */
8852 XTread_socket (sd, bufp, numchars, expected)
8853 register int sd;
8854 /* register */ struct input_event *bufp;
8855 /* register */ int numchars;
8856 int expected;
8858 int count = 0;
8859 int nbytes = 0;
8860 XEvent event;
8861 struct frame *f;
8862 int event_found = 0;
8863 struct x_display_info *dpyinfo;
8865 if (interrupt_input_blocked)
8867 interrupt_input_pending = 1;
8868 return -1;
8871 interrupt_input_pending = 0;
8872 BLOCK_INPUT;
8874 /* So people can tell when we have read the available input. */
8875 input_signal_count++;
8877 if (numchars <= 0)
8878 abort (); /* Don't think this happens. */
8880 /* Find the display we are supposed to read input for.
8881 It's the one communicating on descriptor SD. */
8882 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8884 #if 0 /* This ought to be unnecessary; let's verify it. */
8885 #ifdef FIOSNBIO
8886 /* If available, Xlib uses FIOSNBIO to make the socket
8887 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8888 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8889 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8890 fcntl (dpyinfo->connection, F_SETFL, 0);
8891 #endif /* ! defined (FIOSNBIO) */
8892 #endif
8894 #if 0 /* This code can't be made to work, with multiple displays,
8895 and appears not to be used on any system any more.
8896 Also keyboard.c doesn't turn O_NDELAY on and off
8897 for X connections. */
8898 #ifndef SIGIO
8899 #ifndef HAVE_SELECT
8900 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8902 extern int read_alarm_should_throw;
8903 read_alarm_should_throw = 1;
8904 XPeekEvent (dpyinfo->display, &event);
8905 read_alarm_should_throw = 0;
8907 #endif /* HAVE_SELECT */
8908 #endif /* SIGIO */
8909 #endif
8911 /* For debugging, this gives a way to fake an I/O error. */
8912 if (dpyinfo == XTread_socket_fake_io_error)
8914 XTread_socket_fake_io_error = 0;
8915 x_io_error_quitter (dpyinfo->display);
8918 while (XPending (dpyinfo->display))
8920 XNextEvent (dpyinfo->display, &event);
8922 #ifdef HAVE_X_I18N
8924 /* Filter events for the current X input method.
8925 XFilterEvent returns non-zero if the input method has
8926 consumed the event. We pass the frame's X window to
8927 XFilterEvent because that's the one for which the IC
8928 was created. */
8929 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8930 event.xclient.window);
8931 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
8932 break;
8934 #endif
8935 event_found = 1;
8937 switch (event.type)
8939 case ClientMessage:
8941 if (event.xclient.message_type
8942 == dpyinfo->Xatom_wm_protocols
8943 && event.xclient.format == 32)
8945 if (event.xclient.data.l[0]
8946 == dpyinfo->Xatom_wm_take_focus)
8948 /* Use x_any_window_to_frame because this
8949 could be the shell widget window
8950 if the frame has no title bar. */
8951 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
8952 #ifdef HAVE_X_I18N
8953 /* Not quite sure this is needed -pd */
8954 if (f && FRAME_XIC (f))
8955 XSetICFocus (FRAME_XIC (f));
8956 #endif
8957 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8958 instructs the WM to set the input focus automatically for
8959 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8960 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8961 it has set the focus. So, XSetInputFocus below is not
8962 needed.
8964 The call to XSetInputFocus below has also caused trouble. In
8965 cases where the XSetInputFocus done by the WM and the one
8966 below are temporally close (on a fast machine), the call
8967 below can generate additional FocusIn events which confuse
8968 Emacs. */
8970 /* Since we set WM_TAKE_FOCUS, we must call
8971 XSetInputFocus explicitly. But not if f is null,
8972 since that might be an event for a deleted frame. */
8973 if (f)
8975 Display *d = event.xclient.display;
8976 /* Catch and ignore errors, in case window has been
8977 iconified by a window manager such as GWM. */
8978 int count = x_catch_errors (d);
8979 XSetInputFocus (d, event.xclient.window,
8980 /* The ICCCM says this is
8981 the only valid choice. */
8982 RevertToParent,
8983 event.xclient.data.l[1]);
8984 /* This is needed to detect the error
8985 if there is an error. */
8986 XSync (d, False);
8987 x_uncatch_errors (d, count);
8989 /* Not certain about handling scroll bars here */
8990 #endif /* 0 */
8992 else if (event.xclient.data.l[0]
8993 == dpyinfo->Xatom_wm_save_yourself)
8995 /* Save state modify the WM_COMMAND property to
8996 something which can reinstate us. This notifies
8997 the session manager, who's looking for such a
8998 PropertyNotify. Can restart processing when
8999 a keyboard or mouse event arrives. */
9000 if (numchars > 0)
9002 f = x_top_window_to_frame (dpyinfo,
9003 event.xclient.window);
9005 /* This is just so we only give real data once
9006 for a single Emacs process. */
9007 if (f == SELECTED_FRAME ())
9008 XSetCommand (FRAME_X_DISPLAY (f),
9009 event.xclient.window,
9010 initial_argv, initial_argc);
9011 else if (f)
9012 XSetCommand (FRAME_X_DISPLAY (f),
9013 event.xclient.window,
9014 0, 0);
9017 else if (event.xclient.data.l[0]
9018 == dpyinfo->Xatom_wm_delete_window)
9020 struct frame *f
9021 = x_any_window_to_frame (dpyinfo,
9022 event.xclient.window);
9024 if (f)
9026 if (numchars == 0)
9027 abort ();
9029 bufp->kind = delete_window_event;
9030 XSETFRAME (bufp->frame_or_window, f);
9031 bufp++;
9033 count += 1;
9034 numchars -= 1;
9038 else if (event.xclient.message_type
9039 == dpyinfo->Xatom_wm_configure_denied)
9042 else if (event.xclient.message_type
9043 == dpyinfo->Xatom_wm_window_moved)
9045 int new_x, new_y;
9046 struct frame *f
9047 = x_window_to_frame (dpyinfo, event.xclient.window);
9049 new_x = event.xclient.data.s[0];
9050 new_y = event.xclient.data.s[1];
9052 if (f)
9054 f->output_data.x->left_pos = new_x;
9055 f->output_data.x->top_pos = new_y;
9058 #ifdef HACK_EDITRES
9059 else if (event.xclient.message_type
9060 == dpyinfo->Xatom_editres)
9062 struct frame *f
9063 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9064 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9065 &event, NULL);
9067 #endif /* HACK_EDITRES */
9068 else if ((event.xclient.message_type
9069 == dpyinfo->Xatom_DONE)
9070 || (event.xclient.message_type
9071 == dpyinfo->Xatom_PAGE))
9073 /* Ghostview job completed. Kill it. We could
9074 reply with "Next" if we received "Page", but we
9075 currently never do because we are interested in
9076 images, only, which should have 1 page. */
9077 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9078 struct frame *f
9079 = x_window_to_frame (dpyinfo, event.xclient.window);
9080 x_kill_gs_process (pixmap, f);
9081 expose_frame (f, 0, 0, 0, 0);
9083 #ifdef USE_TOOLKIT_SCROLL_BARS
9084 /* Scroll bar callbacks send a ClientMessage from which
9085 we construct an input_event. */
9086 else if (event.xclient.message_type
9087 == dpyinfo->Xatom_Scrollbar)
9089 x_scroll_bar_to_input_event (&event, bufp);
9090 ++bufp, ++count, --numchars;
9091 goto out;
9093 #endif /* USE_TOOLKIT_SCROLL_BARS */
9094 else
9095 goto OTHER;
9097 break;
9099 case SelectionNotify:
9100 #ifdef USE_X_TOOLKIT
9101 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9102 goto OTHER;
9103 #endif /* not USE_X_TOOLKIT */
9104 x_handle_selection_notify (&event.xselection);
9105 break;
9107 case SelectionClear: /* Someone has grabbed ownership. */
9108 #ifdef USE_X_TOOLKIT
9109 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9110 goto OTHER;
9111 #endif /* USE_X_TOOLKIT */
9113 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9115 if (numchars == 0)
9116 abort ();
9118 bufp->kind = selection_clear_event;
9119 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9120 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9121 SELECTION_EVENT_TIME (bufp) = eventp->time;
9122 bufp->frame_or_window = Qnil;
9123 bufp++;
9125 count += 1;
9126 numchars -= 1;
9128 break;
9130 case SelectionRequest: /* Someone wants our selection. */
9131 #ifdef USE_X_TOOLKIT
9132 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9133 goto OTHER;
9134 #endif /* USE_X_TOOLKIT */
9135 if (x_queue_selection_requests)
9136 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9137 &event);
9138 else
9140 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9142 if (numchars == 0)
9143 abort ();
9145 bufp->kind = selection_request_event;
9146 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9147 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9148 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9149 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9150 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9151 SELECTION_EVENT_TIME (bufp) = eventp->time;
9152 bufp->frame_or_window = Qnil;
9153 bufp++;
9155 count += 1;
9156 numchars -= 1;
9158 break;
9160 case PropertyNotify:
9161 #ifdef USE_X_TOOLKIT
9162 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9163 goto OTHER;
9164 #endif /* not USE_X_TOOLKIT */
9165 x_handle_property_notify (&event.xproperty);
9166 break;
9168 case ReparentNotify:
9169 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9170 if (f)
9172 int x, y;
9173 f->output_data.x->parent_desc = event.xreparent.parent;
9174 x_real_positions (f, &x, &y);
9175 f->output_data.x->left_pos = x;
9176 f->output_data.x->top_pos = y;
9178 break;
9180 case Expose:
9181 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9182 if (f)
9184 if (f->async_visible == 0)
9186 f->async_visible = 1;
9187 f->async_iconified = 0;
9188 f->output_data.x->has_been_visible = 1;
9189 SET_FRAME_GARBAGED (f);
9191 else
9192 expose_frame (x_window_to_frame (dpyinfo,
9193 event.xexpose.window),
9194 event.xexpose.x, event.xexpose.y,
9195 event.xexpose.width, event.xexpose.height);
9197 else
9199 #ifdef USE_TOOLKIT_SCROLL_BARS
9200 /* Dispatch event to the widget. */
9201 goto OTHER;
9202 #else /* not USE_TOOLKIT_SCROLL_BARS */
9203 struct scroll_bar *bar
9204 = x_window_to_scroll_bar (event.xexpose.window);
9206 if (bar)
9207 x_scroll_bar_expose (bar, &event);
9208 #ifdef USE_X_TOOLKIT
9209 else
9210 goto OTHER;
9211 #endif /* USE_X_TOOLKIT */
9212 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9214 break;
9216 case GraphicsExpose: /* This occurs when an XCopyArea's
9217 source area was obscured or not
9218 available.*/
9219 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9220 if (f)
9222 expose_frame (f,
9223 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9224 event.xgraphicsexpose.width,
9225 event.xgraphicsexpose.height);
9227 #ifdef USE_X_TOOLKIT
9228 else
9229 goto OTHER;
9230 #endif /* USE_X_TOOLKIT */
9231 break;
9233 case NoExpose: /* This occurs when an XCopyArea's
9234 source area was completely
9235 available */
9236 break;
9238 case UnmapNotify:
9239 /* Redo the mouse-highlight after the tooltip has gone. */
9240 if (event.xmap.window == tip_window)
9242 tip_window = 0;
9243 redo_mouse_highlight ();
9246 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9247 if (f) /* F may no longer exist if
9248 the frame was deleted. */
9250 /* While a frame is unmapped, display generation is
9251 disabled; you don't want to spend time updating a
9252 display that won't ever be seen. */
9253 f->async_visible = 0;
9254 /* We can't distinguish, from the event, whether the window
9255 has become iconified or invisible. So assume, if it
9256 was previously visible, than now it is iconified.
9257 But x_make_frame_invisible clears both
9258 the visible flag and the iconified flag;
9259 and that way, we know the window is not iconified now. */
9260 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9262 f->async_iconified = 1;
9264 bufp->kind = iconify_event;
9265 XSETFRAME (bufp->frame_or_window, f);
9266 bufp++;
9267 count++;
9268 numchars--;
9271 goto OTHER;
9273 case MapNotify:
9274 if (event.xmap.window == tip_window)
9275 /* The tooltip has been drawn already. Avoid
9276 the SET_FRAME_GARBAGED below. */
9277 goto OTHER;
9279 /* We use x_top_window_to_frame because map events can
9280 come for sub-windows and they don't mean that the
9281 frame is visible. */
9282 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9283 if (f)
9285 f->async_visible = 1;
9286 f->async_iconified = 0;
9287 f->output_data.x->has_been_visible = 1;
9289 /* wait_reading_process_input will notice this and update
9290 the frame's display structures. */
9291 SET_FRAME_GARBAGED (f);
9293 if (f->iconified)
9295 bufp->kind = deiconify_event;
9296 XSETFRAME (bufp->frame_or_window, f);
9297 bufp++;
9298 count++;
9299 numchars--;
9301 else if (! NILP (Vframe_list)
9302 && ! NILP (XCDR (Vframe_list)))
9303 /* Force a redisplay sooner or later
9304 to update the frame titles
9305 in case this is the second frame. */
9306 record_asynch_buffer_change ();
9308 goto OTHER;
9310 case KeyPress:
9311 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9313 #ifdef USE_MOTIF
9314 /* I couldn't find a way to prevent LessTif scroll bars
9315 from consuming key events. */
9316 if (f == 0)
9318 Widget widget = XtWindowToWidget (dpyinfo->display,
9319 event.xkey.window);
9320 if (widget && XmIsScrollBar (widget))
9322 widget = XtParent (widget);
9323 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9326 #endif /* USE_MOTIF */
9328 if (f != 0)
9330 KeySym keysym, orig_keysym;
9331 /* al%imercury@uunet.uu.net says that making this 81 instead of
9332 80 fixed a bug whereby meta chars made his Emacs hang. */
9333 unsigned char copy_buffer[81];
9334 int modifiers;
9336 event.xkey.state
9337 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9338 extra_keyboard_modifiers);
9339 modifiers = event.xkey.state;
9341 /* This will have to go some day... */
9343 /* make_lispy_event turns chars into control chars.
9344 Don't do it here because XLookupString is too eager. */
9345 event.xkey.state &= ~ControlMask;
9346 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9347 | dpyinfo->super_mod_mask
9348 | dpyinfo->hyper_mod_mask
9349 | dpyinfo->alt_mod_mask);
9351 /* In case Meta is ComposeCharacter,
9352 clear its status. According to Markus Ehrnsperger
9353 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9354 this enables ComposeCharacter to work whether or
9355 not it is combined with Meta. */
9356 if (modifiers & dpyinfo->meta_mod_mask)
9357 bzero (&compose_status, sizeof (compose_status));
9359 #ifdef HAVE_X_I18N
9360 if (FRAME_XIC (f))
9362 unsigned char *copy_bufptr = copy_buffer;
9363 int copy_bufsiz = sizeof (copy_buffer);
9364 Status status_return;
9366 nbytes = XmbLookupString (FRAME_XIC (f),
9367 &event.xkey, copy_bufptr,
9368 copy_bufsiz, &keysym,
9369 &status_return);
9370 if (status_return == XBufferOverflow)
9372 copy_bufsiz = nbytes + 1;
9373 copy_bufptr = (char *) alloca (copy_bufsiz);
9374 nbytes = XmbLookupString (FRAME_XIC (f),
9375 &event.xkey, copy_bufptr,
9376 copy_bufsiz, &keysym,
9377 &status_return);
9380 if (status_return == XLookupNone)
9381 break;
9382 else if (status_return == XLookupChars)
9383 keysym = NoSymbol;
9384 else if (status_return != XLookupKeySym
9385 && status_return != XLookupBoth)
9386 abort ();
9388 else
9389 nbytes = XLookupString (&event.xkey, copy_buffer,
9390 80, &keysym, &compose_status);
9391 #else
9392 nbytes = XLookupString (&event.xkey, copy_buffer,
9393 80, &keysym, &compose_status);
9394 #endif
9396 orig_keysym = keysym;
9398 if (numchars > 1)
9400 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9401 || keysym == XK_Delete
9402 #ifdef XK_ISO_Left_Tab
9403 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9404 #endif
9405 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9406 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9407 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9408 #ifdef HPUX
9409 /* This recognizes the "extended function keys".
9410 It seems there's no cleaner way.
9411 Test IsModifierKey to avoid handling mode_switch
9412 incorrectly. */
9413 || ((unsigned) (keysym) >= XK_Select
9414 && (unsigned)(keysym) < XK_KP_Space)
9415 #endif
9416 #ifdef XK_dead_circumflex
9417 || orig_keysym == XK_dead_circumflex
9418 #endif
9419 #ifdef XK_dead_grave
9420 || orig_keysym == XK_dead_grave
9421 #endif
9422 #ifdef XK_dead_tilde
9423 || orig_keysym == XK_dead_tilde
9424 #endif
9425 #ifdef XK_dead_diaeresis
9426 || orig_keysym == XK_dead_diaeresis
9427 #endif
9428 #ifdef XK_dead_macron
9429 || orig_keysym == XK_dead_macron
9430 #endif
9431 #ifdef XK_dead_degree
9432 || orig_keysym == XK_dead_degree
9433 #endif
9434 #ifdef XK_dead_acute
9435 || orig_keysym == XK_dead_acute
9436 #endif
9437 #ifdef XK_dead_cedilla
9438 || orig_keysym == XK_dead_cedilla
9439 #endif
9440 #ifdef XK_dead_breve
9441 || orig_keysym == XK_dead_breve
9442 #endif
9443 #ifdef XK_dead_ogonek
9444 || orig_keysym == XK_dead_ogonek
9445 #endif
9446 #ifdef XK_dead_caron
9447 || orig_keysym == XK_dead_caron
9448 #endif
9449 #ifdef XK_dead_doubleacute
9450 || orig_keysym == XK_dead_doubleacute
9451 #endif
9452 #ifdef XK_dead_abovedot
9453 || orig_keysym == XK_dead_abovedot
9454 #endif
9455 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9456 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9457 /* Any "vendor-specific" key is ok. */
9458 || (orig_keysym & (1 << 28)))
9459 && ! (IsModifierKey (orig_keysym)
9460 #ifndef HAVE_X11R5
9461 #ifdef XK_Mode_switch
9462 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9463 #endif
9464 #ifdef XK_Num_Lock
9465 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9466 #endif
9467 #endif /* not HAVE_X11R5 */
9470 if (temp_index == sizeof temp_buffer / sizeof (short))
9471 temp_index = 0;
9472 temp_buffer[temp_index++] = keysym;
9473 bufp->kind = non_ascii_keystroke;
9474 bufp->code = keysym;
9475 XSETFRAME (bufp->frame_or_window, f);
9476 bufp->modifiers
9477 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9478 modifiers);
9479 bufp->timestamp = event.xkey.time;
9480 bufp++;
9481 count++;
9482 numchars--;
9484 else if (numchars > nbytes)
9486 register int i;
9488 for (i = 0; i < nbytes; i++)
9490 if (temp_index == sizeof temp_buffer / sizeof (short))
9491 temp_index = 0;
9492 temp_buffer[temp_index++] = copy_buffer[i];
9493 bufp->kind = ascii_keystroke;
9494 bufp->code = copy_buffer[i];
9495 XSETFRAME (bufp->frame_or_window, f);
9496 bufp->modifiers
9497 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9498 modifiers);
9499 bufp->timestamp = event.xkey.time;
9500 bufp++;
9503 count += nbytes;
9504 numchars -= nbytes;
9506 if (keysym == NoSymbol)
9507 break;
9509 else
9510 abort ();
9512 else
9513 abort ();
9515 #ifdef HAVE_X_I18N
9516 /* Don't dispatch this event since XtDispatchEvent calls
9517 XFilterEvent, and two calls in a row may freeze the
9518 client. */
9519 break;
9520 #else
9521 goto OTHER;
9522 #endif
9524 case KeyRelease:
9525 #ifdef HAVE_X_I18N
9526 /* Don't dispatch this event since XtDispatchEvent calls
9527 XFilterEvent, and two calls in a row may freeze the
9528 client. */
9529 break;
9530 #else
9531 goto OTHER;
9532 #endif
9534 /* Here's a possible interpretation of the whole
9535 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9536 you get a FocusIn event, you have to get a FocusOut
9537 event before you relinquish the focus. If you
9538 haven't received a FocusIn event, then a mere
9539 LeaveNotify is enough to free you. */
9541 case EnterNotify:
9543 int from_menu_bar_p = 0;
9545 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9547 #ifdef LESSTIF_VERSION
9548 /* When clicking outside of a menu bar popup to close
9549 it, we get a FocusIn/ EnterNotify sequence of
9550 events. The flag event.xcrossing.focus is not set
9551 in the EnterNotify event of that sequence because
9552 the focus is in the menu bar,
9553 event.xcrossing.window is the frame's X window.
9554 Unconditionally setting the focus frame to null in
9555 this case is not the right thing, because no event
9556 follows that could set the focus frame to the right
9557 value.
9559 This could be a LessTif bug, but I wasn't able to
9560 reproduce the behavior in a simple test program.
9562 (gerd, LessTif 0.88.1). */
9564 if (!event.xcrossing.focus
9565 && f
9566 && f->output_data.x->menubar_widget)
9568 Window focus;
9569 int revert;
9571 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9572 if (focus == XtWindow (f->output_data.x->menubar_widget))
9573 from_menu_bar_p = 1;
9575 #endif /* LESSTIF_VERSION */
9577 if (event.xcrossing.focus || from_menu_bar_p)
9579 /* Avoid nasty pop/raise loops. */
9580 if (f && (!(f->auto_raise)
9581 || !(f->auto_lower)
9582 || (event.xcrossing.time - enter_timestamp) > 500))
9584 x_new_focus_frame (dpyinfo, f);
9585 enter_timestamp = event.xcrossing.time;
9588 else if (f == dpyinfo->x_focus_frame)
9589 x_new_focus_frame (dpyinfo, 0);
9591 /* EnterNotify counts as mouse movement,
9592 so update things that depend on mouse position. */
9593 if (f && !f->output_data.x->busy_p)
9594 note_mouse_movement (f, &event.xmotion);
9595 goto OTHER;
9598 case FocusIn:
9599 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9600 if (event.xfocus.detail != NotifyPointer)
9601 dpyinfo->x_focus_event_frame = f;
9602 if (f)
9603 x_new_focus_frame (dpyinfo, f);
9605 #ifdef HAVE_X_I18N
9606 if (f && FRAME_XIC (f))
9607 XSetICFocus (FRAME_XIC (f));
9608 #endif
9610 goto OTHER;
9612 case LeaveNotify:
9613 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9614 if (f)
9616 Lisp_Object frame;
9617 int from_menu_bar_p = 0;
9619 if (f == dpyinfo->mouse_face_mouse_frame)
9621 /* If we move outside the frame, then we're
9622 certainly no longer on any text in the frame. */
9623 clear_mouse_face (dpyinfo);
9624 dpyinfo->mouse_face_mouse_frame = 0;
9627 /* Generate a nil HELP_EVENT to cancel a help-echo.
9628 Do it only if there's something to cancel.
9629 Otherwise, the startup message is cleared when
9630 the mouse leaves the frame. */
9631 if (any_help_event_p)
9633 XSETFRAME (frame, f);
9634 bufp->kind = HELP_EVENT;
9635 bufp->frame_or_window = Fcons (frame, Qnil);
9636 ++bufp, ++count, --numchars;
9639 #ifdef LESSTIF_VERSION
9640 /* Please see the comment at the start of the
9641 EnterNotify case. */
9642 if (!event.xcrossing.focus
9643 && f->output_data.x->menubar_widget)
9645 Window focus;
9646 int revert;
9647 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9648 if (focus == XtWindow (f->output_data.x->menubar_widget))
9649 from_menu_bar_p = 1;
9651 #endif /* LESSTIF_VERSION */
9653 if (event.xcrossing.focus || from_menu_bar_p)
9654 x_mouse_leave (dpyinfo);
9655 else
9657 if (f == dpyinfo->x_focus_event_frame)
9658 dpyinfo->x_focus_event_frame = 0;
9659 if (f == dpyinfo->x_focus_frame)
9660 x_new_focus_frame (dpyinfo, 0);
9663 goto OTHER;
9665 case FocusOut:
9666 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9667 if (event.xfocus.detail != NotifyPointer
9668 && f == dpyinfo->x_focus_event_frame)
9669 dpyinfo->x_focus_event_frame = 0;
9670 if (f && f == dpyinfo->x_focus_frame)
9671 x_new_focus_frame (dpyinfo, 0);
9673 #ifdef HAVE_X_I18N
9674 if (f && FRAME_XIC (f))
9675 XUnsetICFocus (FRAME_XIC (f));
9676 #endif
9678 goto OTHER;
9680 case MotionNotify:
9682 previous_help_echo = help_echo;
9683 help_echo = Qnil;
9685 if (dpyinfo->grabbed && last_mouse_frame
9686 && FRAME_LIVE_P (last_mouse_frame))
9687 f = last_mouse_frame;
9688 else
9689 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9691 if (f)
9692 note_mouse_movement (f, &event.xmotion);
9693 else
9695 #ifndef USE_TOOLKIT_SCROLL_BARS
9696 struct scroll_bar *bar
9697 = x_window_to_scroll_bar (event.xmotion.window);
9699 if (bar)
9700 x_scroll_bar_note_movement (bar, &event);
9701 #endif /* USE_TOOLKIT_SCROLL_BARS */
9703 /* If we move outside the frame, then we're
9704 certainly no longer on any text in the frame. */
9705 clear_mouse_face (dpyinfo);
9708 /* If the contents of the global variable help_echo
9709 has changed, generate a HELP_EVENT. */
9710 if (STRINGP (help_echo)
9711 || STRINGP (previous_help_echo))
9713 Lisp_Object frame;
9715 if (f)
9716 XSETFRAME (frame, f);
9717 else
9718 frame = Qnil;
9720 any_help_event_p = 1;
9721 bufp->kind = HELP_EVENT;
9722 bufp->frame_or_window = Fcons (frame, help_echo);
9723 ++bufp, ++count, --numchars;
9726 goto OTHER;
9729 case ConfigureNotify:
9730 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9731 if (f)
9733 #ifndef USE_X_TOOLKIT
9734 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9735 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
9737 /* In the toolkit version, change_frame_size
9738 is called by the code that handles resizing
9739 of the EmacsFrame widget. */
9741 /* Even if the number of character rows and columns has
9742 not changed, the font size may have changed, so we need
9743 to check the pixel dimensions as well. */
9744 if (columns != f->width
9745 || rows != f->height
9746 || event.xconfigure.width != f->output_data.x->pixel_width
9747 || event.xconfigure.height != f->output_data.x->pixel_height)
9749 change_frame_size (f, rows, columns, 0, 1, 0);
9750 SET_FRAME_GARBAGED (f);
9751 cancel_mouse_face (f);
9753 #endif
9755 f->output_data.x->pixel_width = event.xconfigure.width;
9756 f->output_data.x->pixel_height = event.xconfigure.height;
9758 /* What we have now is the position of Emacs's own window.
9759 Convert that to the position of the window manager window. */
9760 x_real_positions (f, &f->output_data.x->left_pos,
9761 &f->output_data.x->top_pos);
9763 #ifdef HAVE_X_I18N
9764 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9765 xic_set_statusarea (f);
9766 #endif
9768 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9770 /* Since the WM decorations come below top_pos now,
9771 we must put them below top_pos in the future. */
9772 f->output_data.x->win_gravity = NorthWestGravity;
9773 x_wm_set_size_hint (f, (long) 0, 0);
9775 #ifdef USE_MOTIF
9776 /* Some window managers pass (0,0) as the location of
9777 the window, and the Motif event handler stores it
9778 in the emacs widget, which messes up Motif menus. */
9779 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9781 event.xconfigure.x = f->output_data.x->widget->core.x;
9782 event.xconfigure.y = f->output_data.x->widget->core.y;
9784 #endif /* USE_MOTIF */
9786 goto OTHER;
9788 case ButtonPress:
9789 case ButtonRelease:
9791 /* If we decide we want to generate an event to be seen
9792 by the rest of Emacs, we put it here. */
9793 struct input_event emacs_event;
9794 int tool_bar_p = 0;
9796 emacs_event.kind = no_event;
9797 bzero (&compose_status, sizeof (compose_status));
9799 if (dpyinfo->grabbed
9800 && last_mouse_frame
9801 && FRAME_LIVE_P (last_mouse_frame))
9802 f = last_mouse_frame;
9803 else
9804 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9806 if (f)
9808 /* Is this in the tool-bar? */
9809 if (WINDOWP (f->tool_bar_window)
9810 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
9812 Lisp_Object window;
9813 int p, x, y;
9815 x = event.xbutton.x;
9816 y = event.xbutton.y;
9818 /* Set x and y. */
9819 window = window_from_coordinates (f, x, y, &p, 1);
9820 if (EQ (window, f->tool_bar_window))
9822 x_handle_tool_bar_click (f, &event.xbutton);
9823 tool_bar_p = 1;
9827 if (!tool_bar_p)
9828 if (!dpyinfo->x_focus_frame
9829 || f == dpyinfo->x_focus_frame)
9830 construct_mouse_click (&emacs_event, &event, f);
9832 else
9834 #ifndef USE_TOOLKIT_SCROLL_BARS
9835 struct scroll_bar *bar
9836 = x_window_to_scroll_bar (event.xbutton.window);
9838 if (bar)
9839 x_scroll_bar_handle_click (bar, &event, &emacs_event);
9840 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9843 if (event.type == ButtonPress)
9845 dpyinfo->grabbed |= (1 << event.xbutton.button);
9846 last_mouse_frame = f;
9847 /* Ignore any mouse motion that happened
9848 before this event; any subsequent mouse-movement
9849 Emacs events should reflect only motion after
9850 the ButtonPress. */
9851 if (f != 0)
9852 f->mouse_moved = 0;
9854 if (!tool_bar_p)
9855 last_tool_bar_item = -1;
9857 else
9859 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
9862 if (numchars >= 1 && emacs_event.kind != no_event)
9864 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9865 bufp++;
9866 count++;
9867 numchars--;
9870 #ifdef USE_X_TOOLKIT
9871 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9872 /* For a down-event in the menu bar,
9873 don't pass it to Xt right now.
9874 Instead, save it away
9875 and we will pass it to Xt from kbd_buffer_get_event.
9876 That way, we can run some Lisp code first. */
9877 if (f && event.type == ButtonPress
9878 /* Verify the event is really within the menu bar
9879 and not just sent to it due to grabbing. */
9880 && event.xbutton.x >= 0
9881 && event.xbutton.x < f->output_data.x->pixel_width
9882 && event.xbutton.y >= 0
9883 && event.xbutton.y < f->output_data.x->menubar_height
9884 && event.xbutton.same_screen)
9886 SET_SAVED_BUTTON_EVENT;
9887 XSETFRAME (last_mouse_press_frame, f);
9889 else if (event.type == ButtonPress)
9891 last_mouse_press_frame = Qnil;
9892 goto OTHER;
9895 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9896 but I am trying to be cautious. */
9897 else if (event.type == ButtonRelease)
9899 if (!NILP (last_mouse_press_frame))
9901 f = XFRAME (last_mouse_press_frame);
9902 if (f->output_data.x)
9903 SET_SAVED_BUTTON_EVENT;
9905 else
9906 goto OTHER;
9908 #endif /* USE_MOTIF */
9909 else
9910 goto OTHER;
9911 #endif /* USE_X_TOOLKIT */
9913 break;
9915 case CirculateNotify:
9916 goto OTHER;
9918 case CirculateRequest:
9919 goto OTHER;
9921 case VisibilityNotify:
9922 goto OTHER;
9924 case MappingNotify:
9925 /* Someone has changed the keyboard mapping - update the
9926 local cache. */
9927 switch (event.xmapping.request)
9929 case MappingModifier:
9930 x_find_modifier_meanings (dpyinfo);
9931 /* This is meant to fall through. */
9932 case MappingKeyboard:
9933 XRefreshKeyboardMapping (&event.xmapping);
9935 goto OTHER;
9937 default:
9938 OTHER:
9939 #ifdef USE_X_TOOLKIT
9940 BLOCK_INPUT;
9941 XtDispatchEvent (&event);
9942 UNBLOCK_INPUT;
9943 #endif /* USE_X_TOOLKIT */
9944 break;
9949 out:;
9951 /* On some systems, an X bug causes Emacs to get no more events
9952 when the window is destroyed. Detect that. (1994.) */
9953 if (! event_found)
9955 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9956 One XNOOP in 100 loops will make Emacs terminate.
9957 B. Bretthauer, 1994 */
9958 x_noop_count++;
9959 if (x_noop_count >= 100)
9961 x_noop_count=0;
9963 if (next_noop_dpyinfo == 0)
9964 next_noop_dpyinfo = x_display_list;
9966 XNoOp (next_noop_dpyinfo->display);
9968 /* Each time we get here, cycle through the displays now open. */
9969 next_noop_dpyinfo = next_noop_dpyinfo->next;
9973 /* If the focus was just given to an auto-raising frame,
9974 raise it now. */
9975 /* ??? This ought to be able to handle more than one such frame. */
9976 if (pending_autoraise_frame)
9978 x_raise_frame (pending_autoraise_frame);
9979 pending_autoraise_frame = 0;
9982 UNBLOCK_INPUT;
9983 return count;
9989 /***********************************************************************
9990 Text Cursor
9991 ***********************************************************************/
9993 /* Note if the text cursor of window W has been overwritten by a
9994 drawing operation that outputs N glyphs starting at HPOS in the
9995 line given by output_cursor.vpos. N < 0 means all the rest of the
9996 line after HPOS has been written. */
9998 static void
9999 note_overwritten_text_cursor (w, hpos, n)
10000 struct window *w;
10001 int hpos, n;
10003 if (updated_area == TEXT_AREA
10004 && output_cursor.vpos == w->phys_cursor.vpos
10005 && hpos <= w->phys_cursor.hpos
10006 && (n < 0
10007 || hpos + n > w->phys_cursor.hpos))
10008 w->phys_cursor_on_p = 0;
10012 /* Set clipping for output in glyph row ROW. W is the window in which
10013 we operate. GC is the graphics context to set clipping in.
10014 WHOLE_LINE_P non-zero means include the areas used for truncation
10015 mark display and alike in the clipping rectangle.
10017 ROW may be a text row or, e.g., a mode line. Text rows must be
10018 clipped to the interior of the window dedicated to text display,
10019 mode lines must be clipped to the whole window. */
10021 static void
10022 x_clip_to_row (w, row, gc, whole_line_p)
10023 struct window *w;
10024 struct glyph_row *row;
10025 GC gc;
10026 int whole_line_p;
10028 struct frame *f = XFRAME (WINDOW_FRAME (w));
10029 XRectangle clip_rect;
10030 int window_x, window_y, window_width, window_height;
10032 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10034 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10035 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10036 clip_rect.y = max (clip_rect.y, window_y);
10037 clip_rect.width = window_width;
10038 clip_rect.height = row->visible_height;
10040 /* If clipping to the whole line, including trunc marks, extend
10041 the rectangle to the left and increase its width. */
10042 if (whole_line_p)
10044 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10045 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10048 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10052 /* Draw a hollow box cursor on window W in glyph row ROW. */
10054 static void
10055 x_draw_hollow_cursor (w, row)
10056 struct window *w;
10057 struct glyph_row *row;
10059 struct frame *f = XFRAME (WINDOW_FRAME (w));
10060 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10061 Display *dpy = FRAME_X_DISPLAY (f);
10062 int x, y, wd, h;
10063 XGCValues xgcv;
10064 struct glyph *cursor_glyph;
10065 GC gc;
10067 /* Compute frame-relative coordinates from window-relative
10068 coordinates. */
10069 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10070 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10071 + row->ascent - w->phys_cursor_ascent);
10072 h = row->height - 1;
10074 /* Get the glyph the cursor is on. If we can't tell because
10075 the current matrix is invalid or such, give up. */
10076 cursor_glyph = get_phys_cursor_glyph (w);
10077 if (cursor_glyph == NULL)
10078 return;
10080 /* Compute the width of the rectangle to draw. If on a stretch
10081 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10082 rectangle as wide as the glyph, but use a canonical character
10083 width instead. */
10084 wd = cursor_glyph->pixel_width - 1;
10085 if (cursor_glyph->type == STRETCH_GLYPH
10086 && !x_stretch_cursor_p)
10087 wd = min (CANON_X_UNIT (f), wd);
10089 /* The foreground of cursor_gc is typically the same as the normal
10090 background color, which can cause the cursor box to be invisible. */
10091 xgcv.foreground = f->output_data.x->cursor_pixel;
10092 if (dpyinfo->scratch_cursor_gc)
10093 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10094 else
10095 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10096 GCForeground, &xgcv);
10097 gc = dpyinfo->scratch_cursor_gc;
10099 /* Set clipping, draw the rectangle, and reset clipping again. */
10100 x_clip_to_row (w, row, gc, 0);
10101 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10102 XSetClipMask (dpy, gc, None);
10106 /* Draw a bar cursor on window W in glyph row ROW.
10108 Implementation note: One would like to draw a bar cursor with an
10109 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10110 Unfortunately, I didn't find a font yet that has this property set.
10111 --gerd. */
10113 static void
10114 x_draw_bar_cursor (w, row)
10115 struct window *w;
10116 struct glyph_row *row;
10118 /* If cursor hpos is out of bounds, don't draw garbage. This can
10119 happen in mini-buffer windows when switching between echo area
10120 glyphs and mini-buffer. */
10121 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10123 struct frame *f = XFRAME (w->frame);
10124 struct glyph *cursor_glyph;
10125 GC gc;
10126 int x;
10127 unsigned long mask;
10128 XGCValues xgcv;
10129 Display *dpy;
10130 Window window;
10132 cursor_glyph = get_phys_cursor_glyph (w);
10133 if (cursor_glyph == NULL)
10134 return;
10136 xgcv.background = f->output_data.x->cursor_pixel;
10137 xgcv.foreground = f->output_data.x->cursor_pixel;
10138 xgcv.graphics_exposures = 0;
10139 mask = GCForeground | GCBackground | GCGraphicsExposures;
10140 dpy = FRAME_X_DISPLAY (f);
10141 window = FRAME_X_WINDOW (f);
10142 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10144 if (gc)
10145 XChangeGC (dpy, gc, mask, &xgcv);
10146 else
10148 gc = XCreateGC (dpy, window, mask, &xgcv);
10149 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10152 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10153 x_clip_to_row (w, row, gc, 0);
10154 XFillRectangle (dpy, window, gc,
10156 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10157 min (cursor_glyph->pixel_width,
10158 f->output_data.x->cursor_width),
10159 row->height);
10160 XSetClipMask (dpy, gc, None);
10165 /* Clear the cursor of window W to background color, and mark the
10166 cursor as not shown. This is used when the text where the cursor
10167 is is about to be rewritten. */
10169 static void
10170 x_clear_cursor (w)
10171 struct window *w;
10173 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10174 x_update_window_cursor (w, 0);
10178 /* Draw the cursor glyph of window W in glyph row ROW. See the
10179 comment of x_draw_glyphs for the meaning of HL. */
10181 static void
10182 x_draw_phys_cursor_glyph (w, row, hl)
10183 struct window *w;
10184 struct glyph_row *row;
10185 enum draw_glyphs_face hl;
10187 /* If cursor hpos is out of bounds, don't draw garbage. This can
10188 happen in mini-buffer windows when switching between echo area
10189 glyphs and mini-buffer. */
10190 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10192 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10193 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10194 hl, 0, 0, 0);
10196 /* When we erase the cursor, and ROW is overlapped by other
10197 rows, make sure that these overlapping parts of other rows
10198 are redrawn. */
10199 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10201 if (row > w->current_matrix->rows
10202 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10203 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10205 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10206 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10207 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10213 /* Erase the image of a cursor of window W from the screen. */
10215 static void
10216 x_erase_phys_cursor (w)
10217 struct window *w;
10219 struct frame *f = XFRAME (w->frame);
10220 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10221 int hpos = w->phys_cursor.hpos;
10222 int vpos = w->phys_cursor.vpos;
10223 int mouse_face_here_p = 0;
10224 struct glyph_matrix *active_glyphs = w->current_matrix;
10225 struct glyph_row *cursor_row;
10226 struct glyph *cursor_glyph;
10227 enum draw_glyphs_face hl;
10229 /* No cursor displayed or row invalidated => nothing to do on the
10230 screen. */
10231 if (w->phys_cursor_type == NO_CURSOR)
10232 goto mark_cursor_off;
10234 /* VPOS >= active_glyphs->nrows means that window has been resized.
10235 Don't bother to erase the cursor. */
10236 if (vpos >= active_glyphs->nrows)
10237 goto mark_cursor_off;
10239 /* If row containing cursor is marked invalid, there is nothing we
10240 can do. */
10241 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10242 if (!cursor_row->enabled_p)
10243 goto mark_cursor_off;
10245 /* This can happen when the new row is shorter than the old one.
10246 In this case, either x_draw_glyphs or clear_end_of_line
10247 should have cleared the cursor. Note that we wouldn't be
10248 able to erase the cursor in this case because we don't have a
10249 cursor glyph at hand. */
10250 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10251 goto mark_cursor_off;
10253 /* If the cursor is in the mouse face area, redisplay that when
10254 we clear the cursor. */
10255 if (w == XWINDOW (dpyinfo->mouse_face_window)
10256 && (vpos > dpyinfo->mouse_face_beg_row
10257 || (vpos == dpyinfo->mouse_face_beg_row
10258 && hpos >= dpyinfo->mouse_face_beg_col))
10259 && (vpos < dpyinfo->mouse_face_end_row
10260 || (vpos == dpyinfo->mouse_face_end_row
10261 && hpos < dpyinfo->mouse_face_end_col))
10262 /* Don't redraw the cursor's spot in mouse face if it is at the
10263 end of a line (on a newline). The cursor appears there, but
10264 mouse highlighting does not. */
10265 && cursor_row->used[TEXT_AREA] > hpos)
10266 mouse_face_here_p = 1;
10268 /* Maybe clear the display under the cursor. */
10269 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10271 int x;
10272 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10274 cursor_glyph = get_phys_cursor_glyph (w);
10275 if (cursor_glyph == NULL)
10276 goto mark_cursor_off;
10278 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10280 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10282 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10283 cursor_row->y)),
10284 cursor_glyph->pixel_width,
10285 cursor_row->visible_height,
10286 False);
10289 /* Erase the cursor by redrawing the character underneath it. */
10290 if (mouse_face_here_p)
10291 hl = DRAW_MOUSE_FACE;
10292 else if (cursor_row->inverse_p)
10293 hl = DRAW_INVERSE_VIDEO;
10294 else
10295 hl = DRAW_NORMAL_TEXT;
10296 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10298 mark_cursor_off:
10299 w->phys_cursor_on_p = 0;
10300 w->phys_cursor_type = NO_CURSOR;
10304 /* Display or clear cursor of window W. If ON is zero, clear the
10305 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10306 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10308 void
10309 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10310 struct window *w;
10311 int on, hpos, vpos, x, y;
10313 struct frame *f = XFRAME (w->frame);
10314 int new_cursor_type;
10315 struct glyph_matrix *current_glyphs;
10316 struct glyph_row *glyph_row;
10317 struct glyph *glyph;
10319 /* This is pointless on invisible frames, and dangerous on garbaged
10320 windows and frames; in the latter case, the frame or window may
10321 be in the midst of changing its size, and x and y may be off the
10322 window. */
10323 if (! FRAME_VISIBLE_P (f)
10324 || FRAME_GARBAGED_P (f)
10325 || vpos >= w->current_matrix->nrows
10326 || hpos >= w->current_matrix->matrix_w)
10327 return;
10329 /* If cursor is off and we want it off, return quickly. */
10330 if (!on && !w->phys_cursor_on_p)
10331 return;
10333 current_glyphs = w->current_matrix;
10334 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10335 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10337 /* If cursor row is not enabled, we don't really know where to
10338 display the cursor. */
10339 if (!glyph_row->enabled_p)
10341 w->phys_cursor_on_p = 0;
10342 return;
10345 xassert (interrupt_input_blocked);
10347 /* Set new_cursor_type to the cursor we want to be displayed. In a
10348 mini-buffer window, we want the cursor only to appear if we are
10349 reading input from this window. For the selected window, we want
10350 the cursor type given by the frame parameter. If explicitly
10351 marked off, draw no cursor. In all other cases, we want a hollow
10352 box cursor. */
10353 if (cursor_in_echo_area
10354 && FRAME_HAS_MINIBUF_P (f)
10355 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10357 if (w == XWINDOW (echo_area_window))
10358 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10359 else
10360 new_cursor_type = HOLLOW_BOX_CURSOR;
10362 else
10364 if (w != XWINDOW (selected_window)
10365 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10367 extern int cursor_in_non_selected_windows;
10369 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
10370 new_cursor_type = NO_CURSOR;
10371 else
10372 new_cursor_type = HOLLOW_BOX_CURSOR;
10374 else if (w->cursor_off_p)
10375 new_cursor_type = NO_CURSOR;
10376 else
10377 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10380 /* If cursor is currently being shown and we don't want it to be or
10381 it is in the wrong place, or the cursor type is not what we want,
10382 erase it. */
10383 if (w->phys_cursor_on_p
10384 && (!on
10385 || w->phys_cursor.x != x
10386 || w->phys_cursor.y != y
10387 || new_cursor_type != w->phys_cursor_type))
10388 x_erase_phys_cursor (w);
10390 /* If the cursor is now invisible and we want it to be visible,
10391 display it. */
10392 if (on && !w->phys_cursor_on_p)
10394 w->phys_cursor_ascent = glyph_row->ascent;
10395 w->phys_cursor_height = glyph_row->height;
10397 /* Set phys_cursor_.* before x_draw_.* is called because some
10398 of them may need the information. */
10399 w->phys_cursor.x = x;
10400 w->phys_cursor.y = glyph_row->y;
10401 w->phys_cursor.hpos = hpos;
10402 w->phys_cursor.vpos = vpos;
10403 w->phys_cursor_type = new_cursor_type;
10404 w->phys_cursor_on_p = 1;
10406 switch (new_cursor_type)
10408 case HOLLOW_BOX_CURSOR:
10409 x_draw_hollow_cursor (w, glyph_row);
10410 break;
10412 case FILLED_BOX_CURSOR:
10413 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10414 break;
10416 case BAR_CURSOR:
10417 x_draw_bar_cursor (w, glyph_row);
10418 break;
10420 case NO_CURSOR:
10421 break;
10423 default:
10424 abort ();
10427 #ifdef HAVE_X_I18N
10428 if (w == XWINDOW (f->selected_window))
10429 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10430 xic_set_preeditarea (w, x, y);
10431 #endif
10434 #ifndef XFlush
10435 if (updating_frame != f)
10436 XFlush (FRAME_X_DISPLAY (f));
10437 #endif
10441 /* Display the cursor on window W, or clear it. X and Y are window
10442 relative pixel coordinates. HPOS and VPOS are glyph matrix
10443 positions. If W is not the selected window, display a hollow
10444 cursor. ON non-zero means display the cursor at X, Y which
10445 correspond to HPOS, VPOS, otherwise it is cleared. */
10447 void
10448 x_display_cursor (w, on, hpos, vpos, x, y)
10449 struct window *w;
10450 int on, hpos, vpos, x, y;
10452 BLOCK_INPUT;
10453 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10454 UNBLOCK_INPUT;
10458 /* Display the cursor on window W, or clear it, according to ON_P.
10459 Don't change the cursor's position. */
10461 void
10462 x_update_cursor (f, on_p)
10463 struct frame *f;
10465 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10469 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10470 in the window tree rooted at W. */
10472 static void
10473 x_update_cursor_in_window_tree (w, on_p)
10474 struct window *w;
10475 int on_p;
10477 while (w)
10479 if (!NILP (w->hchild))
10480 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10481 else if (!NILP (w->vchild))
10482 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10483 else
10484 x_update_window_cursor (w, on_p);
10486 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10491 /* Switch the display of W's cursor on or off, according to the value
10492 of ON. */
10494 static void
10495 x_update_window_cursor (w, on)
10496 struct window *w;
10497 int on;
10499 BLOCK_INPUT;
10500 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10501 w->phys_cursor.x, w->phys_cursor.y);
10502 UNBLOCK_INPUT;
10508 /* Icons. */
10510 /* Refresh bitmap kitchen sink icon for frame F
10511 when we get an expose event for it. */
10513 void
10514 refreshicon (f)
10515 struct frame *f;
10517 /* Normally, the window manager handles this function. */
10520 /* Make the x-window of frame F use the gnu icon bitmap. */
10523 x_bitmap_icon (f, file)
10524 struct frame *f;
10525 Lisp_Object file;
10527 int bitmap_id;
10529 if (FRAME_X_WINDOW (f) == 0)
10530 return 1;
10532 /* Free up our existing icon bitmap if any. */
10533 if (f->output_data.x->icon_bitmap > 0)
10534 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10535 f->output_data.x->icon_bitmap = 0;
10537 if (STRINGP (file))
10538 bitmap_id = x_create_bitmap_from_file (f, file);
10539 else
10541 /* Create the GNU bitmap if necessary. */
10542 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10543 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10544 = x_create_bitmap_from_data (f, gnu_bits,
10545 gnu_width, gnu_height);
10547 /* The first time we create the GNU bitmap,
10548 this increments the ref-count one extra time.
10549 As a result, the GNU bitmap is never freed.
10550 That way, we don't have to worry about allocating it again. */
10551 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10553 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10556 x_wm_set_icon_pixmap (f, bitmap_id);
10557 f->output_data.x->icon_bitmap = bitmap_id;
10559 return 0;
10563 /* Make the x-window of frame F use a rectangle with text.
10564 Use ICON_NAME as the text. */
10567 x_text_icon (f, icon_name)
10568 struct frame *f;
10569 char *icon_name;
10571 if (FRAME_X_WINDOW (f) == 0)
10572 return 1;
10574 #ifdef HAVE_X11R4
10576 XTextProperty text;
10577 text.value = (unsigned char *) icon_name;
10578 text.encoding = XA_STRING;
10579 text.format = 8;
10580 text.nitems = strlen (icon_name);
10581 #ifdef USE_X_TOOLKIT
10582 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10583 &text);
10584 #else /* not USE_X_TOOLKIT */
10585 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10586 #endif /* not USE_X_TOOLKIT */
10588 #else /* not HAVE_X11R4 */
10589 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10590 #endif /* not HAVE_X11R4 */
10592 if (f->output_data.x->icon_bitmap > 0)
10593 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10594 f->output_data.x->icon_bitmap = 0;
10595 x_wm_set_icon_pixmap (f, 0);
10597 return 0;
10600 #define X_ERROR_MESSAGE_SIZE 200
10602 /* If non-nil, this should be a string.
10603 It means catch X errors and store the error message in this string. */
10605 static Lisp_Object x_error_message_string;
10607 /* An X error handler which stores the error message in
10608 x_error_message_string. This is called from x_error_handler if
10609 x_catch_errors is in effect. */
10611 static void
10612 x_error_catcher (display, error)
10613 Display *display;
10614 XErrorEvent *error;
10616 XGetErrorText (display, error->error_code,
10617 XSTRING (x_error_message_string)->data,
10618 X_ERROR_MESSAGE_SIZE);
10621 /* Begin trapping X errors for display DPY. Actually we trap X errors
10622 for all displays, but DPY should be the display you are actually
10623 operating on.
10625 After calling this function, X protocol errors no longer cause
10626 Emacs to exit; instead, they are recorded in the string
10627 stored in x_error_message_string.
10629 Calling x_check_errors signals an Emacs error if an X error has
10630 occurred since the last call to x_catch_errors or x_check_errors.
10632 Calling x_uncatch_errors resumes the normal error handling. */
10634 void x_check_errors ();
10635 static Lisp_Object x_catch_errors_unwind ();
10638 x_catch_errors (dpy)
10639 Display *dpy;
10641 int count = specpdl_ptr - specpdl;
10643 /* Make sure any errors from previous requests have been dealt with. */
10644 XSync (dpy, False);
10646 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10648 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10649 XSTRING (x_error_message_string)->data[0] = 0;
10651 return count;
10654 /* Unbind the binding that we made to check for X errors. */
10656 static Lisp_Object
10657 x_catch_errors_unwind (old_val)
10658 Lisp_Object old_val;
10660 x_error_message_string = old_val;
10661 return Qnil;
10664 /* If any X protocol errors have arrived since the last call to
10665 x_catch_errors or x_check_errors, signal an Emacs error using
10666 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10668 void
10669 x_check_errors (dpy, format)
10670 Display *dpy;
10671 char *format;
10673 /* Make sure to catch any errors incurred so far. */
10674 XSync (dpy, False);
10676 if (XSTRING (x_error_message_string)->data[0])
10677 error (format, XSTRING (x_error_message_string)->data);
10680 /* Nonzero if we had any X protocol errors
10681 since we did x_catch_errors on DPY. */
10684 x_had_errors_p (dpy)
10685 Display *dpy;
10687 /* Make sure to catch any errors incurred so far. */
10688 XSync (dpy, False);
10690 return XSTRING (x_error_message_string)->data[0] != 0;
10693 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10695 void
10696 x_clear_errors (dpy)
10697 Display *dpy;
10699 XSTRING (x_error_message_string)->data[0] = 0;
10702 /* Stop catching X protocol errors and let them make Emacs die.
10703 DPY should be the display that was passed to x_catch_errors.
10704 COUNT should be the value that was returned by
10705 the corresponding call to x_catch_errors. */
10707 void
10708 x_uncatch_errors (dpy, count)
10709 Display *dpy;
10710 int count;
10712 unbind_to (count, Qnil);
10715 #if 0
10716 static unsigned int x_wire_count;
10717 x_trace_wire ()
10719 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10721 #endif /* ! 0 */
10724 /* Handle SIGPIPE, which can happen when the connection to a server
10725 simply goes away. SIGPIPE is handled by x_connection_signal.
10726 Don't need to do anything, because the write which caused the
10727 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10728 which will do the appropriate cleanup for us. */
10730 static SIGTYPE
10731 x_connection_signal (signalnum) /* If we don't have an argument, */
10732 int signalnum; /* some compilers complain in signal calls. */
10734 #ifdef USG
10735 /* USG systems forget handlers when they are used;
10736 must reestablish each time */
10737 signal (signalnum, x_connection_signal);
10738 #endif /* USG */
10741 /* Handling X errors. */
10743 /* Handle the loss of connection to display DISPLAY. */
10745 static SIGTYPE
10746 x_connection_closed (display, error_message)
10747 Display *display;
10748 char *error_message;
10750 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10751 Lisp_Object frame, tail;
10753 /* Indicate that this display is dead. */
10755 #if 0 /* Closing the display caused a bus error on OpenWindows. */
10756 #ifdef USE_X_TOOLKIT
10757 XtCloseDisplay (display);
10758 #endif
10759 #endif
10761 dpyinfo->display = 0;
10763 /* First delete frames whose mini-buffers are on frames
10764 that are on the dead display. */
10765 FOR_EACH_FRAME (tail, frame)
10767 Lisp_Object minibuf_frame;
10768 minibuf_frame
10769 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10770 if (FRAME_X_P (XFRAME (frame))
10771 && FRAME_X_P (XFRAME (minibuf_frame))
10772 && ! EQ (frame, minibuf_frame)
10773 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10774 Fdelete_frame (frame, Qt);
10777 /* Now delete all remaining frames on the dead display.
10778 We are now sure none of these is used as the mini-buffer
10779 for another frame that we need to delete. */
10780 FOR_EACH_FRAME (tail, frame)
10781 if (FRAME_X_P (XFRAME (frame))
10782 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10784 /* Set this to t so that Fdelete_frame won't get confused
10785 trying to find a replacement. */
10786 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10787 Fdelete_frame (frame, Qt);
10790 if (dpyinfo)
10791 x_delete_display (dpyinfo);
10793 if (x_display_list == 0)
10795 fprintf (stderr, "%s\n", error_message);
10796 shut_down_emacs (0, 0, Qnil);
10797 exit (70);
10800 /* Ordinary stack unwind doesn't deal with these. */
10801 #ifdef SIGIO
10802 sigunblock (sigmask (SIGIO));
10803 #endif
10804 sigunblock (sigmask (SIGALRM));
10805 TOTALLY_UNBLOCK_INPUT;
10807 clear_waiting_for_input ();
10808 error ("%s", error_message);
10811 /* This is the usual handler for X protocol errors.
10812 It kills all frames on the display that we got the error for.
10813 If that was the only one, it prints an error message and kills Emacs. */
10815 static void
10816 x_error_quitter (display, error)
10817 Display *display;
10818 XErrorEvent *error;
10820 char buf[256], buf1[356];
10822 /* Note that there is no real way portable across R3/R4 to get the
10823 original error handler. */
10825 XGetErrorText (display, error->error_code, buf, sizeof (buf));
10826 sprintf (buf1, "X protocol error: %s on protocol request %d",
10827 buf, error->request_code);
10828 x_connection_closed (display, buf1);
10831 /* This is the first-level handler for X protocol errors.
10832 It calls x_error_quitter or x_error_catcher. */
10834 static int
10835 x_error_handler (display, error)
10836 Display *display;
10837 XErrorEvent *error;
10839 if (! NILP (x_error_message_string))
10840 x_error_catcher (display, error);
10841 else
10842 x_error_quitter (display, error);
10843 return 0;
10846 /* This is the handler for X IO errors, always.
10847 It kills all frames on the display that we lost touch with.
10848 If that was the only one, it prints an error message and kills Emacs. */
10850 static int
10851 x_io_error_quitter (display)
10852 Display *display;
10854 char buf[256];
10856 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10857 x_connection_closed (display, buf);
10858 return 0;
10861 /* Changing the font of the frame. */
10863 /* Give frame F the font named FONTNAME as its default font, and
10864 return the full name of that font. FONTNAME may be a wildcard
10865 pattern; in that case, we choose some font that fits the pattern.
10866 The return value shows which font we chose. */
10868 Lisp_Object
10869 x_new_font (f, fontname)
10870 struct frame *f;
10871 register char *fontname;
10873 struct font_info *fontp
10874 = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
10876 if (!fontp)
10877 return Qnil;
10879 f->output_data.x->font = (XFontStruct *) (fontp->font);
10880 f->output_data.x->baseline_offset = fontp->baseline_offset;
10881 f->output_data.x->fontset = -1;
10883 /* Compute the scroll bar width in character columns. */
10884 if (f->scroll_bar_pixel_width > 0)
10886 int wid = FONT_WIDTH (f->output_data.x->font);
10887 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10889 else
10891 int wid = FONT_WIDTH (f->output_data.x->font);
10892 f->scroll_bar_cols = (14 + wid - 1) / wid;
10895 /* Now make the frame display the given font. */
10896 if (FRAME_X_WINDOW (f) != 0)
10898 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10899 f->output_data.x->font->fid);
10900 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10901 f->output_data.x->font->fid);
10902 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10903 f->output_data.x->font->fid);
10905 frame_update_line_height (f);
10906 x_set_window_size (f, 0, f->width, f->height);
10908 else
10909 /* If we are setting a new frame's font for the first time,
10910 there are no faces yet, so this font's height is the line height. */
10911 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
10913 return build_string (fontp->full_name);
10916 /* Give frame F the fontset named FONTSETNAME as its default font, and
10917 return the full name of that fontset. FONTSETNAME may be a wildcard
10918 pattern; in that case, we choose some fontset that fits the pattern.
10919 The return value shows which fontset we chose. */
10921 Lisp_Object
10922 x_new_fontset (f, fontsetname)
10923 struct frame *f;
10924 char *fontsetname;
10926 int fontset = fs_query_fontset (f, fontsetname);
10927 struct fontset_info *fontsetp;
10928 Lisp_Object result;
10930 if (fontset < 0)
10931 return Qnil;
10933 if (f->output_data.x->fontset == fontset)
10934 /* This fontset is already set in frame F. There's nothing more
10935 to do. */
10936 return build_string (fontsetname);
10938 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
10940 if (!fontsetp->fontname[CHARSET_ASCII])
10941 /* This fontset doesn't contain ASCII font. */
10942 return Qnil;
10944 result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
10946 if (!STRINGP (result))
10947 /* Can't load ASCII font. */
10948 return Qnil;
10950 /* Since x_new_font doesn't update any fontset information, do it now. */
10951 f->output_data.x->fontset = fontset;
10952 FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
10953 CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
10955 #ifdef HAVE_X_I18N
10956 if (FRAME_XIC (f)
10957 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
10958 xic_set_xfontset (f, fontsetp->fontname[CHARSET_ASCII]);
10959 #endif
10961 return build_string (fontsetname);
10965 /***********************************************************************
10966 X Input Methods
10967 ***********************************************************************/
10969 #ifdef HAVE_X_I18N
10971 #ifdef HAVE_X11R6
10973 /* XIM destroy callback function, which is called whenever the
10974 connection to input method XIM dies. CLIENT_DATA contains a
10975 pointer to the x_display_info structure corresponding to XIM. */
10977 static void
10978 xim_destroy_callback (xim, client_data, call_data)
10979 XIM xim;
10980 XPointer client_data;
10981 XPointer call_data;
10983 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
10984 Lisp_Object frame, tail;
10986 BLOCK_INPUT;
10988 /* No need to call XDestroyIC.. */
10989 FOR_EACH_FRAME (tail, frame)
10991 struct frame *f = XFRAME (frame);
10992 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
10994 FRAME_XIC (f) = NULL;
10995 if (FRAME_XIC_FONTSET (f))
10997 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
10998 FRAME_XIC_FONTSET (f) = NULL;
11003 /* No need to call XCloseIM. */
11004 dpyinfo->xim = NULL;
11005 XFree (dpyinfo->xim_styles);
11006 UNBLOCK_INPUT;
11009 #endif /* HAVE_X11R6 */
11011 /* Open the connection to the XIM server on display DPYINFO.
11012 RESOURCE_NAME is the resource name Emacs uses. */
11014 static void
11015 xim_open_dpy (dpyinfo, resource_name)
11016 struct x_display_info *dpyinfo;
11017 char *resource_name;
11019 XIM xim;
11021 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11022 dpyinfo->xim = xim;
11024 if (xim)
11026 #ifdef HAVE_X11R6
11027 XIMCallback destroy;
11028 #endif
11030 /* Get supported styles and XIM values. */
11031 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11033 #ifdef HAVE_X11R6
11034 destroy.callback = xim_destroy_callback;
11035 destroy.client_data = (XPointer)dpyinfo;
11036 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11037 #endif
11042 #ifdef HAVE_X11R6
11044 struct xim_inst_t
11046 struct x_display_info *dpyinfo;
11047 char *resource_name;
11050 /* XIM instantiate callback function, which is called whenever an XIM
11051 server is available. DISPLAY is teh display of the XIM.
11052 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11053 when the callback was registered. */
11055 static void
11056 xim_instantiate_callback (display, client_data, call_data)
11057 Display *display;
11058 XPointer client_data;
11059 XPointer call_data;
11061 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11062 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11064 /* We don't support multiple XIM connections. */
11065 if (dpyinfo->xim)
11066 return;
11068 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11070 /* Create XIC for the existing frames on the same display, as long
11071 as they have no XIC. */
11072 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11074 Lisp_Object tail, frame;
11076 BLOCK_INPUT;
11077 FOR_EACH_FRAME (tail, frame)
11079 struct frame *f = XFRAME (frame);
11081 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11082 if (FRAME_XIC (f) == NULL)
11084 create_frame_xic (f);
11085 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11086 xic_set_statusarea (f);
11087 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11089 struct window *w = XWINDOW (f->selected_window);
11090 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11095 UNBLOCK_INPUT;
11099 #endif /* HAVE_X11R6 */
11102 /* Open a connection to the XIM server on display DPYINFO.
11103 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11104 connection only at the first time. On X11R6, open the connection
11105 in the XIM instantiate callback function. */
11107 static void
11108 xim_initialize (dpyinfo, resource_name)
11109 struct x_display_info *dpyinfo;
11110 char *resource_name;
11112 #ifdef HAVE_X11R6
11113 struct xim_inst_t *xim_inst;
11114 int len;
11116 dpyinfo->xim = NULL;
11117 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11118 xim_inst->dpyinfo = dpyinfo;
11119 len = strlen (resource_name);
11120 xim_inst->resource_name = (char *) xmalloc (len + 1);
11121 bcopy (resource_name, xim_inst->resource_name, len + 1);
11122 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11123 resource_name, EMACS_CLASS,
11124 xim_instantiate_callback,
11125 (XPointer)xim_inst);
11126 #else /* not HAVE_X11R6 */
11127 dpyinfo->xim = NULL;
11128 xim_open_dpy (dpyinfo, resource_name);
11129 #endif /* not HAVE_X11R6 */
11133 /* Close the connection to the XIM server on display DPYINFO. */
11135 static void
11136 xim_close_dpy (dpyinfo)
11137 struct x_display_info *dpyinfo;
11139 #ifdef HAVE_X11R6
11140 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11141 NULL, EMACS_CLASS,
11142 xim_instantiate_callback, NULL);
11143 #endif /* HAVE_X11R6 */
11144 XCloseIM (dpyinfo->xim);
11145 dpyinfo->xim = NULL;
11146 XFree (dpyinfo->xim_styles);
11149 #endif /* HAVE_X_I18N */
11153 /* Calculate the absolute position in frame F
11154 from its current recorded position values and gravity. */
11156 void
11157 x_calc_absolute_position (f)
11158 struct frame *f;
11160 Window child;
11161 int win_x = 0, win_y = 0;
11162 int flags = f->output_data.x->size_hint_flags;
11163 int this_window;
11165 /* We have nothing to do if the current position
11166 is already for the top-left corner. */
11167 if (! ((flags & XNegative) || (flags & YNegative)))
11168 return;
11170 #ifdef USE_X_TOOLKIT
11171 this_window = XtWindow (f->output_data.x->widget);
11172 #else
11173 this_window = FRAME_X_WINDOW (f);
11174 #endif
11176 /* Find the position of the outside upper-left corner of
11177 the inner window, with respect to the outer window.
11178 But do this only if we will need the results. */
11179 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11181 int count;
11183 BLOCK_INPUT;
11184 count = x_catch_errors (FRAME_X_DISPLAY (f));
11185 while (1)
11187 x_clear_errors (FRAME_X_DISPLAY (f));
11188 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11190 /* From-window, to-window. */
11191 this_window,
11192 f->output_data.x->parent_desc,
11194 /* From-position, to-position. */
11195 0, 0, &win_x, &win_y,
11197 /* Child of win. */
11198 &child);
11199 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11201 Window newroot, newparent = 0xdeadbeef;
11202 Window *newchildren;
11203 int nchildren;
11205 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11206 &newparent, &newchildren, &nchildren))
11207 break;
11209 XFree ((char *) newchildren);
11211 f->output_data.x->parent_desc = newparent;
11213 else
11214 break;
11217 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11218 UNBLOCK_INPUT;
11221 /* Treat negative positions as relative to the leftmost bottommost
11222 position that fits on the screen. */
11223 if (flags & XNegative)
11224 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11225 - 2 * f->output_data.x->border_width - win_x
11226 - PIXEL_WIDTH (f)
11227 + f->output_data.x->left_pos);
11229 if (flags & YNegative)
11231 int menubar_height = 0;
11233 #ifdef USE_X_TOOLKIT
11234 if (f->output_data.x->menubar_widget)
11235 menubar_height
11236 = (f->output_data.x->menubar_widget->core.height
11237 + f->output_data.x->menubar_widget->core.border_width);
11238 #endif
11240 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11241 - 2 * f->output_data.x->border_width
11242 - win_y
11243 - PIXEL_HEIGHT (f)
11244 - menubar_height
11245 + f->output_data.x->top_pos);
11248 /* The left_pos and top_pos
11249 are now relative to the top and left screen edges,
11250 so the flags should correspond. */
11251 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11254 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11255 to really change the position, and 0 when calling from
11256 x_make_frame_visible (in that case, XOFF and YOFF are the current
11257 position values). It is -1 when calling from x_set_frame_parameters,
11258 which means, do adjust for borders but don't change the gravity. */
11260 void
11261 x_set_offset (f, xoff, yoff, change_gravity)
11262 struct frame *f;
11263 register int xoff, yoff;
11264 int change_gravity;
11266 int modified_top, modified_left;
11268 if (change_gravity > 0)
11270 f->output_data.x->top_pos = yoff;
11271 f->output_data.x->left_pos = xoff;
11272 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11273 if (xoff < 0)
11274 f->output_data.x->size_hint_flags |= XNegative;
11275 if (yoff < 0)
11276 f->output_data.x->size_hint_flags |= YNegative;
11277 f->output_data.x->win_gravity = NorthWestGravity;
11279 x_calc_absolute_position (f);
11281 BLOCK_INPUT;
11282 x_wm_set_size_hint (f, (long) 0, 0);
11284 modified_left = f->output_data.x->left_pos;
11285 modified_top = f->output_data.x->top_pos;
11286 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11287 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11288 /* It is a mystery why we need to add the border_width here
11289 when the frame is already visible, but experiment says we do. */
11290 if (change_gravity != 0)
11292 modified_left += f->output_data.x->border_width;
11293 modified_top += f->output_data.x->border_width;
11295 #endif
11297 #ifdef USE_X_TOOLKIT
11298 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11299 modified_left, modified_top);
11300 #else /* not USE_X_TOOLKIT */
11301 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11302 modified_left, modified_top);
11303 #endif /* not USE_X_TOOLKIT */
11304 UNBLOCK_INPUT;
11307 /* Call this to change the size of frame F's x-window.
11308 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11309 for this size change and subsequent size changes.
11310 Otherwise we leave the window gravity unchanged. */
11312 void
11313 x_set_window_size (f, change_gravity, cols, rows)
11314 struct frame *f;
11315 int change_gravity;
11316 int cols, rows;
11318 #ifndef USE_X_TOOLKIT
11319 int pixelwidth, pixelheight;
11320 #endif
11322 BLOCK_INPUT;
11324 #ifdef USE_X_TOOLKIT
11326 /* The x and y position of the widget is clobbered by the
11327 call to XtSetValues within EmacsFrameSetCharSize.
11328 This is a real kludge, but I don't understand Xt so I can't
11329 figure out a correct fix. Can anyone else tell me? -- rms. */
11330 int xpos = f->output_data.x->widget->core.x;
11331 int ypos = f->output_data.x->widget->core.y;
11332 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11333 f->output_data.x->widget->core.x = xpos;
11334 f->output_data.x->widget->core.y = ypos;
11337 #else /* not USE_X_TOOLKIT */
11339 check_frame_size (f, &rows, &cols);
11340 f->output_data.x->vertical_scroll_bar_extra
11341 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11343 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11344 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11345 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11346 f->output_data.x->flags_areas_extra
11347 = FRAME_FLAGS_AREA_WIDTH (f);
11348 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11349 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11351 f->output_data.x->win_gravity = NorthWestGravity;
11352 x_wm_set_size_hint (f, (long) 0, 0);
11354 XSync (FRAME_X_DISPLAY (f), False);
11355 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11356 pixelwidth, pixelheight);
11358 /* Now, strictly speaking, we can't be sure that this is accurate,
11359 but the window manager will get around to dealing with the size
11360 change request eventually, and we'll hear how it went when the
11361 ConfigureNotify event gets here.
11363 We could just not bother storing any of this information here,
11364 and let the ConfigureNotify event set everything up, but that
11365 might be kind of confusing to the Lisp code, since size changes
11366 wouldn't be reported in the frame parameters until some random
11367 point in the future when the ConfigureNotify event arrives.
11369 We pass 1 for DELAY since we can't run Lisp code inside of
11370 a BLOCK_INPUT. */
11371 change_frame_size (f, rows, cols, 0, 1, 0);
11372 PIXEL_WIDTH (f) = pixelwidth;
11373 PIXEL_HEIGHT (f) = pixelheight;
11375 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11376 receive in the ConfigureNotify event; if we get what we asked
11377 for, then the event won't cause the screen to become garbaged, so
11378 we have to make sure to do it here. */
11379 SET_FRAME_GARBAGED (f);
11381 XFlush (FRAME_X_DISPLAY (f));
11383 #endif /* not USE_X_TOOLKIT */
11385 /* If cursor was outside the new size, mark it as off. */
11386 mark_window_cursors_off (XWINDOW (f->root_window));
11388 /* Clear out any recollection of where the mouse highlighting was,
11389 since it might be in a place that's outside the new frame size.
11390 Actually checking whether it is outside is a pain in the neck,
11391 so don't try--just let the highlighting be done afresh with new size. */
11392 cancel_mouse_face (f);
11394 UNBLOCK_INPUT;
11397 /* Mouse warping. */
11399 void
11400 x_set_mouse_position (f, x, y)
11401 struct frame *f;
11402 int x, y;
11404 int pix_x, pix_y;
11406 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11407 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11409 if (pix_x < 0) pix_x = 0;
11410 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11412 if (pix_y < 0) pix_y = 0;
11413 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11415 BLOCK_INPUT;
11417 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11418 0, 0, 0, 0, pix_x, pix_y);
11419 UNBLOCK_INPUT;
11422 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11424 void
11425 x_set_mouse_pixel_position (f, pix_x, pix_y)
11426 struct frame *f;
11427 int pix_x, pix_y;
11429 BLOCK_INPUT;
11431 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11432 0, 0, 0, 0, pix_x, pix_y);
11433 UNBLOCK_INPUT;
11436 /* focus shifting, raising and lowering. */
11438 void
11439 x_focus_on_frame (f)
11440 struct frame *f;
11442 #if 0 /* This proves to be unpleasant. */
11443 x_raise_frame (f);
11444 #endif
11445 #if 0
11446 /* I don't think that the ICCCM allows programs to do things like this
11447 without the interaction of the window manager. Whatever you end up
11448 doing with this code, do it to x_unfocus_frame too. */
11449 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11450 RevertToPointerRoot, CurrentTime);
11451 #endif /* ! 0 */
11454 void
11455 x_unfocus_frame (f)
11456 struct frame *f;
11458 #if 0
11459 /* Look at the remarks in x_focus_on_frame. */
11460 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11461 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11462 RevertToPointerRoot, CurrentTime);
11463 #endif /* ! 0 */
11466 /* Raise frame F. */
11468 void
11469 x_raise_frame (f)
11470 struct frame *f;
11472 if (f->async_visible)
11474 BLOCK_INPUT;
11475 #ifdef USE_X_TOOLKIT
11476 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11477 #else /* not USE_X_TOOLKIT */
11478 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11479 #endif /* not USE_X_TOOLKIT */
11480 XFlush (FRAME_X_DISPLAY (f));
11481 UNBLOCK_INPUT;
11485 /* Lower frame F. */
11487 void
11488 x_lower_frame (f)
11489 struct frame *f;
11491 if (f->async_visible)
11493 BLOCK_INPUT;
11494 #ifdef USE_X_TOOLKIT
11495 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11496 #else /* not USE_X_TOOLKIT */
11497 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11498 #endif /* not USE_X_TOOLKIT */
11499 XFlush (FRAME_X_DISPLAY (f));
11500 UNBLOCK_INPUT;
11504 static void
11505 XTframe_raise_lower (f, raise_flag)
11506 FRAME_PTR f;
11507 int raise_flag;
11509 if (raise_flag)
11510 x_raise_frame (f);
11511 else
11512 x_lower_frame (f);
11515 /* Change of visibility. */
11517 /* This tries to wait until the frame is really visible.
11518 However, if the window manager asks the user where to position
11519 the frame, this will return before the user finishes doing that.
11520 The frame will not actually be visible at that time,
11521 but it will become visible later when the window manager
11522 finishes with it. */
11524 void
11525 x_make_frame_visible (f)
11526 struct frame *f;
11528 Lisp_Object type;
11529 int original_top, original_left;
11531 BLOCK_INPUT;
11533 type = x_icon_type (f);
11534 if (!NILP (type))
11535 x_bitmap_icon (f, type);
11537 if (! FRAME_VISIBLE_P (f))
11539 /* We test FRAME_GARBAGED_P here to make sure we don't
11540 call x_set_offset a second time
11541 if we get to x_make_frame_visible a second time
11542 before the window gets really visible. */
11543 if (! FRAME_ICONIFIED_P (f)
11544 && ! f->output_data.x->asked_for_visible)
11545 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11547 f->output_data.x->asked_for_visible = 1;
11549 if (! EQ (Vx_no_window_manager, Qt))
11550 x_wm_set_window_state (f, NormalState);
11551 #ifdef USE_X_TOOLKIT
11552 /* This was XtPopup, but that did nothing for an iconified frame. */
11553 XtMapWidget (f->output_data.x->widget);
11554 #else /* not USE_X_TOOLKIT */
11555 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11556 #endif /* not USE_X_TOOLKIT */
11557 #if 0 /* This seems to bring back scroll bars in the wrong places
11558 if the window configuration has changed. They seem
11559 to come back ok without this. */
11560 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11561 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11562 #endif
11565 XFlush (FRAME_X_DISPLAY (f));
11567 /* Synchronize to ensure Emacs knows the frame is visible
11568 before we do anything else. We do this loop with input not blocked
11569 so that incoming events are handled. */
11571 Lisp_Object frame;
11572 int count;
11573 /* This must be before UNBLOCK_INPUT
11574 since events that arrive in response to the actions above
11575 will set it when they are handled. */
11576 int previously_visible = f->output_data.x->has_been_visible;
11578 original_left = f->output_data.x->left_pos;
11579 original_top = f->output_data.x->top_pos;
11581 /* This must come after we set COUNT. */
11582 UNBLOCK_INPUT;
11584 /* We unblock here so that arriving X events are processed. */
11586 /* Now move the window back to where it was "supposed to be".
11587 But don't do it if the gravity is negative.
11588 When the gravity is negative, this uses a position
11589 that is 3 pixels too low. Perhaps that's really the border width.
11591 Don't do this if the window has never been visible before,
11592 because the window manager may choose the position
11593 and we don't want to override it. */
11595 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11596 && f->output_data.x->win_gravity == NorthWestGravity
11597 && previously_visible)
11599 Drawable rootw;
11600 int x, y;
11601 unsigned int width, height, border, depth;
11603 BLOCK_INPUT;
11605 /* On some window managers (such as FVWM) moving an existing
11606 window, even to the same place, causes the window manager
11607 to introduce an offset. This can cause the window to move
11608 to an unexpected location. Check the geometry (a little
11609 slow here) and then verify that the window is in the right
11610 place. If the window is not in the right place, move it
11611 there, and take the potential window manager hit. */
11612 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11613 &rootw, &x, &y, &width, &height, &border, &depth);
11615 if (original_left != x || original_top != y)
11616 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11617 original_left, original_top);
11619 UNBLOCK_INPUT;
11622 XSETFRAME (frame, f);
11624 /* Wait until the frame is visible. Process X events until a
11625 MapNotify event has been seen, or until we think we won't get a
11626 MapNotify at all.. */
11627 for (count = input_signal_count + 10;
11628 input_signal_count < count && !FRAME_VISIBLE_P (f);)
11630 /* Force processing of queued events. */
11631 x_sync (f);
11633 /* Machines that do polling rather than SIGIO have been
11634 observed to go into a busy-wait here. So we'll fake an
11635 alarm signal to let the handler know that there's something
11636 to be read. We used to raise a real alarm, but it seems
11637 that the handler isn't always enabled here. This is
11638 probably a bug. */
11639 if (input_polling_used ())
11641 /* It could be confusing if a real alarm arrives while
11642 processing the fake one. Turn it off and let the
11643 handler reset it. */
11644 int old_poll_suppress_count = poll_suppress_count;
11645 poll_suppress_count = 1;
11646 poll_for_input_1 ();
11647 poll_suppress_count = old_poll_suppress_count;
11650 /* See if a MapNotify event has been processed. */
11651 FRAME_SAMPLE_VISIBILITY (f);
11656 /* Change from mapped state to withdrawn state. */
11658 /* Make the frame visible (mapped and not iconified). */
11660 void
11661 x_make_frame_invisible (f)
11662 struct frame *f;
11664 Window window;
11666 #ifdef USE_X_TOOLKIT
11667 /* Use the frame's outermost window, not the one we normally draw on. */
11668 window = XtWindow (f->output_data.x->widget);
11669 #else /* not USE_X_TOOLKIT */
11670 window = FRAME_X_WINDOW (f);
11671 #endif /* not USE_X_TOOLKIT */
11673 /* Don't keep the highlight on an invisible frame. */
11674 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11675 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11677 #if 0/* This might add unreliability; I don't trust it -- rms. */
11678 if (! f->async_visible && ! f->async_iconified)
11679 return;
11680 #endif
11682 BLOCK_INPUT;
11684 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11685 that the current position of the window is user-specified, rather than
11686 program-specified, so that when the window is mapped again, it will be
11687 placed at the same location, without forcing the user to position it
11688 by hand again (they have already done that once for this window.) */
11689 x_wm_set_size_hint (f, (long) 0, 1);
11691 #ifdef HAVE_X11R4
11693 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11694 DefaultScreen (FRAME_X_DISPLAY (f))))
11696 UNBLOCK_INPUT_RESIGNAL;
11697 error ("Can't notify window manager of window withdrawal");
11699 #else /* ! defined (HAVE_X11R4) */
11701 /* Tell the window manager what we're going to do. */
11702 if (! EQ (Vx_no_window_manager, Qt))
11704 XEvent unmap;
11706 unmap.xunmap.type = UnmapNotify;
11707 unmap.xunmap.window = window;
11708 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
11709 unmap.xunmap.from_configure = False;
11710 if (! XSendEvent (FRAME_X_DISPLAY (f),
11711 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11712 False,
11713 SubstructureRedirectMaskSubstructureNotifyMask,
11714 &unmap))
11716 UNBLOCK_INPUT_RESIGNAL;
11717 error ("Can't notify window manager of withdrawal");
11721 /* Unmap the window ourselves. Cheeky! */
11722 XUnmapWindow (FRAME_X_DISPLAY (f), window);
11723 #endif /* ! defined (HAVE_X11R4) */
11725 /* We can't distinguish this from iconification
11726 just by the event that we get from the server.
11727 So we can't win using the usual strategy of letting
11728 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11729 and synchronize with the server to make sure we agree. */
11730 f->visible = 0;
11731 FRAME_ICONIFIED_P (f) = 0;
11732 f->async_visible = 0;
11733 f->async_iconified = 0;
11735 x_sync (f);
11737 UNBLOCK_INPUT;
11740 /* Change window state from mapped to iconified. */
11742 void
11743 x_iconify_frame (f)
11744 struct frame *f;
11746 int result;
11747 Lisp_Object type;
11749 /* Don't keep the highlight on an invisible frame. */
11750 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11751 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11753 if (f->async_iconified)
11754 return;
11756 BLOCK_INPUT;
11758 FRAME_SAMPLE_VISIBILITY (f);
11760 type = x_icon_type (f);
11761 if (!NILP (type))
11762 x_bitmap_icon (f, type);
11764 #ifdef USE_X_TOOLKIT
11766 if (! FRAME_VISIBLE_P (f))
11768 if (! EQ (Vx_no_window_manager, Qt))
11769 x_wm_set_window_state (f, IconicState);
11770 /* This was XtPopup, but that did nothing for an iconified frame. */
11771 XtMapWidget (f->output_data.x->widget);
11772 /* The server won't give us any event to indicate
11773 that an invisible frame was changed to an icon,
11774 so we have to record it here. */
11775 f->iconified = 1;
11776 f->visible = 1;
11777 f->async_iconified = 1;
11778 f->async_visible = 0;
11779 UNBLOCK_INPUT;
11780 return;
11783 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11784 XtWindow (f->output_data.x->widget),
11785 DefaultScreen (FRAME_X_DISPLAY (f)));
11786 UNBLOCK_INPUT;
11788 if (!result)
11789 error ("Can't notify window manager of iconification");
11791 f->async_iconified = 1;
11792 f->async_visible = 0;
11795 BLOCK_INPUT;
11796 XFlush (FRAME_X_DISPLAY (f));
11797 UNBLOCK_INPUT;
11798 #else /* not USE_X_TOOLKIT */
11800 /* Make sure the X server knows where the window should be positioned,
11801 in case the user deiconifies with the window manager. */
11802 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
11803 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11805 /* Since we don't know which revision of X we're running, we'll use both
11806 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11808 /* X11R4: send a ClientMessage to the window manager using the
11809 WM_CHANGE_STATE type. */
11811 XEvent message;
11813 message.xclient.window = FRAME_X_WINDOW (f);
11814 message.xclient.type = ClientMessage;
11815 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
11816 message.xclient.format = 32;
11817 message.xclient.data.l[0] = IconicState;
11819 if (! XSendEvent (FRAME_X_DISPLAY (f),
11820 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11821 False,
11822 SubstructureRedirectMask | SubstructureNotifyMask,
11823 &message))
11825 UNBLOCK_INPUT_RESIGNAL;
11826 error ("Can't notify window manager of iconification");
11830 /* X11R3: set the initial_state field of the window manager hints to
11831 IconicState. */
11832 x_wm_set_window_state (f, IconicState);
11834 if (!FRAME_VISIBLE_P (f))
11836 /* If the frame was withdrawn, before, we must map it. */
11837 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11840 f->async_iconified = 1;
11841 f->async_visible = 0;
11843 XFlush (FRAME_X_DISPLAY (f));
11844 UNBLOCK_INPUT;
11845 #endif /* not USE_X_TOOLKIT */
11848 /* Destroy the X window of frame F. */
11850 void
11851 x_destroy_window (f)
11852 struct frame *f;
11854 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11856 BLOCK_INPUT;
11858 /* If a display connection is dead, don't try sending more
11859 commands to the X server. */
11860 if (dpyinfo->display != 0)
11862 if (f->output_data.x->icon_desc != 0)
11863 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
11864 #ifdef HAVE_X_I18N
11865 if (FRAME_XIC (f))
11866 free_frame_xic (f);
11867 #endif
11868 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
11869 #ifdef USE_X_TOOLKIT
11870 if (f->output_data.x->widget)
11871 XtDestroyWidget (f->output_data.x->widget);
11872 free_frame_menubar (f);
11873 #endif /* USE_X_TOOLKIT */
11875 free_frame_faces (f);
11876 XFlush (FRAME_X_DISPLAY (f));
11879 if (f->output_data.x->saved_menu_event)
11880 xfree (f->output_data.x->saved_menu_event);
11882 xfree (f->output_data.x);
11883 f->output_data.x = 0;
11884 if (f == dpyinfo->x_focus_frame)
11885 dpyinfo->x_focus_frame = 0;
11886 if (f == dpyinfo->x_focus_event_frame)
11887 dpyinfo->x_focus_event_frame = 0;
11888 if (f == dpyinfo->x_highlight_frame)
11889 dpyinfo->x_highlight_frame = 0;
11891 dpyinfo->reference_count--;
11893 if (f == dpyinfo->mouse_face_mouse_frame)
11895 dpyinfo->mouse_face_beg_row
11896 = dpyinfo->mouse_face_beg_col = -1;
11897 dpyinfo->mouse_face_end_row
11898 = dpyinfo->mouse_face_end_col = -1;
11899 dpyinfo->mouse_face_window = Qnil;
11900 dpyinfo->mouse_face_deferred_gc = 0;
11901 dpyinfo->mouse_face_mouse_frame = 0;
11904 UNBLOCK_INPUT;
11907 /* Setting window manager hints. */
11909 /* Set the normal size hints for the window manager, for frame F.
11910 FLAGS is the flags word to use--or 0 meaning preserve the flags
11911 that the window now has.
11912 If USER_POSITION is nonzero, we set the USPosition
11913 flag (this is useful when FLAGS is 0). */
11915 void
11916 x_wm_set_size_hint (f, flags, user_position)
11917 struct frame *f;
11918 long flags;
11919 int user_position;
11921 XSizeHints size_hints;
11923 #ifdef USE_X_TOOLKIT
11924 Arg al[2];
11925 int ac = 0;
11926 Dimension widget_width, widget_height;
11927 Window window = XtWindow (f->output_data.x->widget);
11928 #else /* not USE_X_TOOLKIT */
11929 Window window = FRAME_X_WINDOW (f);
11930 #endif /* not USE_X_TOOLKIT */
11932 /* Setting PMaxSize caused various problems. */
11933 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
11935 size_hints.x = f->output_data.x->left_pos;
11936 size_hints.y = f->output_data.x->top_pos;
11938 #ifdef USE_X_TOOLKIT
11939 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11940 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
11941 XtGetValues (f->output_data.x->widget, al, ac);
11942 size_hints.height = widget_height;
11943 size_hints.width = widget_width;
11944 #else /* not USE_X_TOOLKIT */
11945 size_hints.height = PIXEL_HEIGHT (f);
11946 size_hints.width = PIXEL_WIDTH (f);
11947 #endif /* not USE_X_TOOLKIT */
11949 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11950 size_hints.height_inc = f->output_data.x->line_height;
11951 size_hints.max_width
11952 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11953 size_hints.max_height
11954 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
11956 /* Calculate the base and minimum sizes.
11958 (When we use the X toolkit, we don't do it here.
11959 Instead we copy the values that the widgets are using, below.) */
11960 #ifndef USE_X_TOOLKIT
11962 int base_width, base_height;
11963 int min_rows = 0, min_cols = 0;
11965 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11966 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
11968 check_frame_size (f, &min_rows, &min_cols);
11970 /* The window manager uses the base width hints to calculate the
11971 current number of rows and columns in the frame while
11972 resizing; min_width and min_height aren't useful for this
11973 purpose, since they might not give the dimensions for a
11974 zero-row, zero-column frame.
11976 We use the base_width and base_height members if we have
11977 them; otherwise, we set the min_width and min_height members
11978 to the size for a zero x zero frame. */
11980 #ifdef HAVE_X11R4
11981 size_hints.flags |= PBaseSize;
11982 size_hints.base_width = base_width;
11983 size_hints.base_height = base_height;
11984 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
11985 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
11986 #else
11987 size_hints.min_width = base_width;
11988 size_hints.min_height = base_height;
11989 #endif
11992 /* If we don't need the old flags, we don't need the old hint at all. */
11993 if (flags)
11995 size_hints.flags |= flags;
11996 goto no_read;
11998 #endif /* not USE_X_TOOLKIT */
12001 XSizeHints hints; /* Sometimes I hate X Windows... */
12002 long supplied_return;
12003 int value;
12005 #ifdef HAVE_X11R4
12006 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12007 &supplied_return);
12008 #else
12009 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12010 #endif
12012 #ifdef USE_X_TOOLKIT
12013 size_hints.base_height = hints.base_height;
12014 size_hints.base_width = hints.base_width;
12015 size_hints.min_height = hints.min_height;
12016 size_hints.min_width = hints.min_width;
12017 #endif
12019 if (flags)
12020 size_hints.flags |= flags;
12021 else
12023 if (value == 0)
12024 hints.flags = 0;
12025 if (hints.flags & PSize)
12026 size_hints.flags |= PSize;
12027 if (hints.flags & PPosition)
12028 size_hints.flags |= PPosition;
12029 if (hints.flags & USPosition)
12030 size_hints.flags |= USPosition;
12031 if (hints.flags & USSize)
12032 size_hints.flags |= USSize;
12036 #ifndef USE_X_TOOLKIT
12037 no_read:
12038 #endif
12040 #ifdef PWinGravity
12041 size_hints.win_gravity = f->output_data.x->win_gravity;
12042 size_hints.flags |= PWinGravity;
12044 if (user_position)
12046 size_hints.flags &= ~ PPosition;
12047 size_hints.flags |= USPosition;
12049 #endif /* PWinGravity */
12051 #ifdef HAVE_X11R4
12052 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12053 #else
12054 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12055 #endif
12058 /* Used for IconicState or NormalState */
12060 void
12061 x_wm_set_window_state (f, state)
12062 struct frame *f;
12063 int state;
12065 #ifdef USE_X_TOOLKIT
12066 Arg al[1];
12068 XtSetArg (al[0], XtNinitialState, state);
12069 XtSetValues (f->output_data.x->widget, al, 1);
12070 #else /* not USE_X_TOOLKIT */
12071 Window window = FRAME_X_WINDOW (f);
12073 f->output_data.x->wm_hints.flags |= StateHint;
12074 f->output_data.x->wm_hints.initial_state = state;
12076 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12077 #endif /* not USE_X_TOOLKIT */
12080 void
12081 x_wm_set_icon_pixmap (f, pixmap_id)
12082 struct frame *f;
12083 int pixmap_id;
12085 Pixmap icon_pixmap;
12087 #ifndef USE_X_TOOLKIT
12088 Window window = FRAME_X_WINDOW (f);
12089 #endif
12091 if (pixmap_id > 0)
12093 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12094 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12096 else
12098 /* It seems there is no way to turn off use of an icon pixmap.
12099 The following line does it, only if no icon has yet been created,
12100 for some window managers. But with mwm it crashes.
12101 Some people say it should clear the IconPixmapHint bit in this case,
12102 but that doesn't work, and the X consortium said it isn't the
12103 right thing at all. Since there is no way to win,
12104 best to explicitly give up. */
12105 #if 0
12106 f->output_data.x->wm_hints.icon_pixmap = None;
12107 #else
12108 return;
12109 #endif
12112 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12115 Arg al[1];
12116 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12117 XtSetValues (f->output_data.x->widget, al, 1);
12120 #else /* not USE_X_TOOLKIT */
12122 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12123 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12125 #endif /* not USE_X_TOOLKIT */
12128 void
12129 x_wm_set_icon_position (f, icon_x, icon_y)
12130 struct frame *f;
12131 int icon_x, icon_y;
12133 #ifdef USE_X_TOOLKIT
12134 Window window = XtWindow (f->output_data.x->widget);
12135 #else
12136 Window window = FRAME_X_WINDOW (f);
12137 #endif
12139 f->output_data.x->wm_hints.flags |= IconPositionHint;
12140 f->output_data.x->wm_hints.icon_x = icon_x;
12141 f->output_data.x->wm_hints.icon_y = icon_y;
12143 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12147 /***********************************************************************
12148 Fonts
12149 ***********************************************************************/
12151 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12153 struct font_info *
12154 x_get_font_info (f, font_idx)
12155 FRAME_PTR f;
12156 int font_idx;
12158 return (FRAME_X_FONT_TABLE (f) + font_idx);
12162 /* Return a list of names of available fonts matching PATTERN on frame
12163 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12164 to be listed. Frame F NULL means we have not yet created any
12165 frame on X, and consult the first display in x_display_list.
12166 MAXNAMES sets a limit on how many fonts to match. */
12168 Lisp_Object
12169 x_list_fonts (f, pattern, size, maxnames)
12170 FRAME_PTR f;
12171 Lisp_Object pattern;
12172 int size;
12173 int maxnames;
12175 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12176 Lisp_Object tem, second_best;
12177 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12178 int try_XLoadQueryFont = 0;
12179 int count;
12181 patterns = Fassoc (pattern, Valternate_fontname_alist);
12182 if (NILP (patterns))
12183 patterns = Fcons (pattern, Qnil);
12185 if (maxnames == 1 && !size)
12186 /* We can return any single font matching PATTERN. */
12187 try_XLoadQueryFont = 1;
12189 for (; CONSP (patterns); patterns = XCDR (patterns))
12191 int num_fonts;
12192 char **names;
12194 pattern = XCAR (patterns);
12195 /* See if we cached the result for this particular query.
12196 The cache is an alist of the form:
12197 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12199 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12200 key = Fcons (pattern, make_number (maxnames)),
12201 !NILP (list = Fassoc (key, tem))))
12203 list = Fcdr_safe (list);
12204 /* We have a cashed list. Don't have to get the list again. */
12205 goto label_cached;
12208 /* At first, put PATTERN in the cache. */
12210 BLOCK_INPUT;
12211 count = x_catch_errors (dpy);
12213 if (try_XLoadQueryFont)
12215 XFontStruct *font;
12216 unsigned long value;
12218 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12219 if (x_had_errors_p (dpy))
12221 /* This error is perhaps due to insufficient memory on X
12222 server. Let's just ignore it. */
12223 font = NULL;
12224 x_clear_errors (dpy);
12227 if (font
12228 && XGetFontProperty (font, XA_FONT, &value))
12230 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12231 int len = strlen (name);
12232 char *tmp;
12234 /* If DXPC (a Differential X Protocol Compressor)
12235 Ver.3.7 is running, XGetAtomName will return null
12236 string. We must avoid such a name. */
12237 if (len == 0)
12238 try_XLoadQueryFont = 0;
12239 else
12241 num_fonts = 1;
12242 names = (char **) alloca (sizeof (char *));
12243 /* Some systems only allow alloca assigned to a
12244 simple var. */
12245 tmp = (char *) alloca (len + 1); names[0] = tmp;
12246 bcopy (name, names[0], len + 1);
12247 XFree (name);
12250 else
12251 try_XLoadQueryFont = 0;
12253 if (font)
12254 XFreeFont (dpy, font);
12257 if (!try_XLoadQueryFont)
12259 /* We try at least 10 fonts because XListFonts will return
12260 auto-scaled fonts at the head. */
12261 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12262 &num_fonts);
12263 if (x_had_errors_p (dpy))
12265 /* This error is perhaps due to insufficient memory on X
12266 server. Let's just ignore it. */
12267 names = NULL;
12268 x_clear_errors (dpy);
12272 x_uncatch_errors (dpy, count);
12273 UNBLOCK_INPUT;
12275 if (names)
12277 int i;
12279 /* Make a list of all the fonts we got back.
12280 Store that in the font cache for the display. */
12281 for (i = 0; i < num_fonts; i++)
12283 int width = 0;
12284 char *p = names[i];
12285 int average_width = -1, dashes = 0;
12287 /* Count the number of dashes in NAMES[I]. If there are
12288 14 dashes, and the field value following 12th dash
12289 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12290 is usually too ugly to be used for editing. Let's
12291 ignore it. */
12292 while (*p)
12293 if (*p++ == '-')
12295 dashes++;
12296 if (dashes == 7) /* PIXEL_SIZE field */
12297 width = atoi (p);
12298 else if (dashes == 12) /* AVERAGE_WIDTH field */
12299 average_width = atoi (p);
12301 if (dashes < 14 || average_width != 0)
12303 tem = build_string (names[i]);
12304 if (NILP (Fassoc (tem, list)))
12306 if (STRINGP (Vx_pixel_size_width_font_regexp)
12307 && ((fast_c_string_match_ignore_case
12308 (Vx_pixel_size_width_font_regexp, names[i]))
12309 >= 0))
12310 /* We can set the value of PIXEL_SIZE to the
12311 width of this font. */
12312 list = Fcons (Fcons (tem, make_number (width)), list);
12313 else
12314 /* For the moment, width is not known. */
12315 list = Fcons (Fcons (tem, Qnil), list);
12319 if (!try_XLoadQueryFont)
12320 XFreeFontNames (names);
12323 /* Now store the result in the cache. */
12324 if (f != NULL)
12325 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12326 = Fcons (Fcons (key, list),
12327 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12329 label_cached:
12330 if (NILP (list)) continue; /* Try the remaining alternatives. */
12332 newlist = second_best = Qnil;
12333 /* Make a list of the fonts that have the right width. */
12334 for (; CONSP (list); list = XCDR (list))
12336 int found_size;
12338 tem = XCAR (list);
12340 if (!CONSP (tem) || NILP (XCAR (tem)))
12341 continue;
12342 if (!size)
12344 newlist = Fcons (XCAR (tem), newlist);
12345 continue;
12348 if (!INTEGERP (XCDR (tem)))
12350 /* Since we have not yet known the size of this font, we
12351 must try slow function call XLoadQueryFont. */
12352 XFontStruct *thisinfo;
12354 BLOCK_INPUT;
12355 count = x_catch_errors (dpy);
12356 thisinfo = XLoadQueryFont (dpy,
12357 XSTRING (XCAR (tem))->data);
12358 if (x_had_errors_p (dpy))
12360 /* This error is perhaps due to insufficient memory on X
12361 server. Let's just ignore it. */
12362 thisinfo = NULL;
12363 x_clear_errors (dpy);
12365 x_uncatch_errors (dpy, count);
12366 UNBLOCK_INPUT;
12368 if (thisinfo)
12370 XCDR (tem)
12371 = (thisinfo->min_bounds.width == 0
12372 ? make_number (0)
12373 : make_number (thisinfo->max_bounds.width));
12374 XFreeFont (dpy, thisinfo);
12376 else
12377 /* For unknown reason, the previous call of XListFont had
12378 returned a font which can't be opened. Record the size
12379 as 0 not to try to open it again. */
12380 XCDR (tem) = make_number (0);
12383 found_size = XINT (XCDR (tem));
12384 if (found_size == size)
12385 newlist = Fcons (XCAR (tem), newlist);
12386 else if (found_size > 0)
12388 if (NILP (second_best))
12389 second_best = tem;
12390 else if (found_size < size)
12392 if (XINT (XCDR (second_best)) > size
12393 || XINT (XCDR (second_best)) < found_size)
12394 second_best = tem;
12396 else
12398 if (XINT (XCDR (second_best)) > size
12399 && XINT (XCDR (second_best)) > found_size)
12400 second_best = tem;
12404 if (!NILP (newlist))
12405 break;
12406 else if (!NILP (second_best))
12408 newlist = Fcons (XCAR (second_best), Qnil);
12409 break;
12413 return newlist;
12417 #if GLYPH_DEBUG
12419 /* Check that FONT is valid on frame F. It is if it can be found in F's
12420 font table. */
12422 static void
12423 x_check_font (f, font)
12424 struct frame *f;
12425 XFontStruct *font;
12427 int i;
12428 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12430 xassert (font != NULL);
12432 for (i = 0; i < dpyinfo->n_fonts; i++)
12433 if (dpyinfo->font_table[i].name
12434 && font == dpyinfo->font_table[i].font)
12435 break;
12437 xassert (i < dpyinfo->n_fonts);
12440 #endif /* GLYPH_DEBUG != 0 */
12442 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12443 Note: There are (broken) X fonts out there with invalid XFontStruct
12444 min_bounds contents. For example, handa@etl.go.jp reports that
12445 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12446 have font->min_bounds.width == 0. */
12448 static INLINE void
12449 x_font_min_bounds (font, w, h)
12450 XFontStruct *font;
12451 int *w, *h;
12453 *h = FONT_HEIGHT (font);
12454 *w = font->min_bounds.width;
12456 /* Try to handle the case where FONT->min_bounds has invalid
12457 contents. Since the only font known to have invalid min_bounds
12458 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12459 if (*w <= 0)
12460 *w = font->max_bounds.width;
12464 /* Compute the smallest character width and smallest font height over
12465 all fonts available on frame F. Set the members smallest_char_width
12466 and smallest_font_height in F's x_display_info structure to
12467 the values computed. Value is non-zero if smallest_font_height or
12468 smallest_char_width become smaller than they were before. */
12470 static int
12471 x_compute_min_glyph_bounds (f)
12472 struct frame *f;
12474 int i;
12475 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12476 XFontStruct *font;
12477 int old_width = dpyinfo->smallest_char_width;
12478 int old_height = dpyinfo->smallest_font_height;
12480 dpyinfo->smallest_font_height = 100000;
12481 dpyinfo->smallest_char_width = 100000;
12483 for (i = 0; i < dpyinfo->n_fonts; ++i)
12484 if (dpyinfo->font_table[i].name)
12486 struct font_info *fontp = dpyinfo->font_table + i;
12487 int w, h;
12489 font = (XFontStruct *) fontp->font;
12490 xassert (font != (XFontStruct *) ~0);
12491 x_font_min_bounds (font, &w, &h);
12493 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12494 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12497 xassert (dpyinfo->smallest_char_width > 0
12498 && dpyinfo->smallest_font_height > 0);
12500 return (dpyinfo->n_fonts == 1
12501 || dpyinfo->smallest_char_width < old_width
12502 || dpyinfo->smallest_font_height < old_height);
12506 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12507 pointer to the structure font_info while allocating it dynamically.
12508 If SIZE is 0, load any size of font.
12509 If loading is failed, return NULL. */
12511 struct font_info *
12512 x_load_font (f, fontname, size)
12513 struct frame *f;
12514 register char *fontname;
12515 int size;
12517 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12518 Lisp_Object font_names;
12519 int count;
12521 /* Get a list of all the fonts that match this name. Once we
12522 have a list of matching fonts, we compare them against the fonts
12523 we already have by comparing names. */
12524 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12526 if (!NILP (font_names))
12528 Lisp_Object tail;
12529 int i;
12531 for (i = 0; i < dpyinfo->n_fonts; i++)
12532 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12533 if (dpyinfo->font_table[i].name
12534 && (!strcmp (dpyinfo->font_table[i].name,
12535 XSTRING (XCAR (tail))->data)
12536 || !strcmp (dpyinfo->font_table[i].full_name,
12537 XSTRING (XCAR (tail))->data)))
12538 return (dpyinfo->font_table + i);
12541 /* Load the font and add it to the table. */
12543 char *full_name;
12544 XFontStruct *font;
12545 struct font_info *fontp;
12546 unsigned long value;
12547 int i;
12549 /* If we have found fonts by x_list_font, load one of them. If
12550 not, we still try to load a font by the name given as FONTNAME
12551 because XListFonts (called in x_list_font) of some X server has
12552 a bug of not finding a font even if the font surely exists and
12553 is loadable by XLoadQueryFont. */
12554 if (size > 0 && !NILP (font_names))
12555 fontname = (char *) XSTRING (XCAR (font_names))->data;
12557 BLOCK_INPUT;
12558 count = x_catch_errors (FRAME_X_DISPLAY (f));
12559 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12560 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12562 /* This error is perhaps due to insufficient memory on X
12563 server. Let's just ignore it. */
12564 font = NULL;
12565 x_clear_errors (FRAME_X_DISPLAY (f));
12567 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12568 UNBLOCK_INPUT;
12569 if (!font)
12570 return NULL;
12572 /* Find a free slot in the font table. */
12573 for (i = 0; i < dpyinfo->n_fonts; ++i)
12574 if (dpyinfo->font_table[i].name == NULL)
12575 break;
12577 /* If no free slot found, maybe enlarge the font table. */
12578 if (i == dpyinfo->n_fonts
12579 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12581 int sz;
12582 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12583 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12584 dpyinfo->font_table
12585 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12588 fontp = dpyinfo->font_table + i;
12589 if (i == dpyinfo->n_fonts)
12590 ++dpyinfo->n_fonts;
12592 /* Now fill in the slots of *FONTP. */
12593 BLOCK_INPUT;
12594 fontp->font = font;
12595 fontp->font_idx = i;
12596 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12597 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12599 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12600 full_name = 0;
12601 if (XGetFontProperty (font, XA_FONT, &value))
12603 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12604 char *p = name;
12605 int dashes = 0;
12607 /* Count the number of dashes in the "full name".
12608 If it is too few, this isn't really the font's full name,
12609 so don't use it.
12610 In X11R4, the fonts did not come with their canonical names
12611 stored in them. */
12612 while (*p)
12614 if (*p == '-')
12615 dashes++;
12616 p++;
12619 if (dashes >= 13)
12621 full_name = (char *) xmalloc (p - name + 1);
12622 bcopy (name, full_name, p - name + 1);
12625 XFree (name);
12628 if (full_name != 0)
12629 fontp->full_name = full_name;
12630 else
12631 fontp->full_name = fontp->name;
12633 fontp->size = font->max_bounds.width;
12634 fontp->height = FONT_HEIGHT (font);
12636 /* For some font, ascent and descent in max_bounds field is
12637 larger than the above value. */
12638 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12639 if (max_height > fontp->height)
12640 fontp->height = max_height;
12643 if (NILP (font_names))
12645 /* We come here because of a bug of XListFonts mentioned at
12646 the head of this block. Let's store this information in
12647 the cache for x_list_fonts. */
12648 Lisp_Object lispy_name = build_string (fontname);
12649 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12651 XCDR (dpyinfo->name_list_element)
12652 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12653 Fcons (Fcons (lispy_full_name,
12654 make_number (fontp->size)),
12655 Qnil)),
12656 XCDR (dpyinfo->name_list_element));
12657 if (full_name)
12658 XCDR (dpyinfo->name_list_element)
12659 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12660 Fcons (Fcons (lispy_full_name,
12661 make_number (fontp->size)),
12662 Qnil)),
12663 XCDR (dpyinfo->name_list_element));
12666 /* The slot `encoding' specifies how to map a character
12667 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12668 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12669 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12670 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12671 2:0xA020..0xFF7F). For the moment, we don't know which charset
12672 uses this font. So, we set information in fontp->encoding[1]
12673 which is never used by any charset. If mapping can't be
12674 decided, set FONT_ENCODING_NOT_DECIDED. */
12675 fontp->encoding[1]
12676 = (font->max_byte1 == 0
12677 /* 1-byte font */
12678 ? (font->min_char_or_byte2 < 0x80
12679 ? (font->max_char_or_byte2 < 0x80
12680 ? 0 /* 0x20..0x7F */
12681 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
12682 : 1) /* 0xA0..0xFF */
12683 /* 2-byte font */
12684 : (font->min_byte1 < 0x80
12685 ? (font->max_byte1 < 0x80
12686 ? (font->min_char_or_byte2 < 0x80
12687 ? (font->max_char_or_byte2 < 0x80
12688 ? 0 /* 0x2020..0x7F7F */
12689 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
12690 : 3) /* 0x20A0..0x7FFF */
12691 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
12692 : (font->min_char_or_byte2 < 0x80
12693 ? (font->max_char_or_byte2 < 0x80
12694 ? 2 /* 0xA020..0xFF7F */
12695 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
12696 : 1))); /* 0xA0A0..0xFFFF */
12698 fontp->baseline_offset
12699 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12700 ? (long) value : 0);
12701 fontp->relative_compose
12702 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12703 ? (long) value : 0);
12704 fontp->default_ascent
12705 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12706 ? (long) value : 0);
12708 /* Set global flag fonts_changed_p to non-zero if the font loaded
12709 has a character with a smaller width than any other character
12710 before, or if the font loaded has a smalle>r height than any
12711 other font loaded before. If this happens, it will make a
12712 glyph matrix reallocation necessary. */
12713 fonts_changed_p = x_compute_min_glyph_bounds (f);
12714 UNBLOCK_INPUT;
12715 return fontp;
12720 /* Return a pointer to struct font_info of a font named FONTNAME for
12721 frame F. If no such font is loaded, return NULL. */
12723 struct font_info *
12724 x_query_font (f, fontname)
12725 struct frame *f;
12726 register char *fontname;
12728 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12729 int i;
12731 for (i = 0; i < dpyinfo->n_fonts; i++)
12732 if (dpyinfo->font_table[i].name
12733 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12734 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
12735 return (dpyinfo->font_table + i);
12736 return NULL;
12740 /* Find a CCL program for a font specified by FONTP, and set the member
12741 `encoder' of the structure. */
12743 void
12744 x_find_ccl_program (fontp)
12745 struct font_info *fontp;
12747 Lisp_Object list, elt;
12749 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
12751 elt = XCAR (list);
12752 if (CONSP (elt)
12753 && STRINGP (XCAR (elt))
12754 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
12755 >= 0))
12756 break;
12758 if (! NILP (list))
12760 struct ccl_program *ccl
12761 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
12763 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
12764 xfree (ccl);
12765 else
12766 fontp->font_encoder = ccl;
12772 /***********************************************************************
12773 Initialization
12774 ***********************************************************************/
12776 #ifdef USE_X_TOOLKIT
12777 static XrmOptionDescRec emacs_options[] = {
12778 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12779 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12781 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12782 XrmoptionSepArg, NULL},
12783 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12785 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12786 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12787 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12788 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12789 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12790 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12791 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12793 #endif /* USE_X_TOOLKIT */
12795 static int x_initialized;
12797 #ifdef MULTI_KBOARD
12798 /* Test whether two display-name strings agree up to the dot that separates
12799 the screen number from the server number. */
12800 static int
12801 same_x_server (name1, name2)
12802 char *name1, *name2;
12804 int seen_colon = 0;
12805 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12806 int system_name_length = strlen (system_name);
12807 int length_until_period = 0;
12809 while (system_name[length_until_period] != 0
12810 && system_name[length_until_period] != '.')
12811 length_until_period++;
12813 /* Treat `unix' like an empty host name. */
12814 if (! strncmp (name1, "unix:", 5))
12815 name1 += 4;
12816 if (! strncmp (name2, "unix:", 5))
12817 name2 += 4;
12818 /* Treat this host's name like an empty host name. */
12819 if (! strncmp (name1, system_name, system_name_length)
12820 && name1[system_name_length] == ':')
12821 name1 += system_name_length;
12822 if (! strncmp (name2, system_name, system_name_length)
12823 && name2[system_name_length] == ':')
12824 name2 += system_name_length;
12825 /* Treat this host's domainless name like an empty host name. */
12826 if (! strncmp (name1, system_name, length_until_period)
12827 && name1[length_until_period] == ':')
12828 name1 += length_until_period;
12829 if (! strncmp (name2, system_name, length_until_period)
12830 && name2[length_until_period] == ':')
12831 name2 += length_until_period;
12833 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12835 if (*name1 == ':')
12836 seen_colon++;
12837 if (seen_colon && *name1 == '.')
12838 return 1;
12840 return (seen_colon
12841 && (*name1 == '.' || *name1 == '\0')
12842 && (*name2 == '.' || *name2 == '\0'));
12844 #endif
12846 struct x_display_info *
12847 x_term_init (display_name, xrm_option, resource_name)
12848 Lisp_Object display_name;
12849 char *xrm_option;
12850 char *resource_name;
12852 int connection;
12853 Display *dpy;
12854 struct x_display_info *dpyinfo;
12855 XrmDatabase xrdb;
12857 BLOCK_INPUT;
12859 if (!x_initialized)
12861 x_initialize ();
12862 x_initialized = 1;
12865 #ifdef USE_X_TOOLKIT
12866 /* weiner@footloose.sps.mot.com reports that this causes
12867 errors with X11R5:
12868 X protocol error: BadAtom (invalid Atom parameter)
12869 on protocol request 18skiloaf.
12870 So let's not use it until R6. */
12871 #ifdef HAVE_X11XTR6
12872 XtSetLanguageProc (NULL, NULL, NULL);
12873 #endif
12876 int argc = 0;
12877 char *argv[3];
12879 argv[0] = "";
12880 argc = 1;
12881 if (xrm_option)
12883 argv[argc++] = "-xrm";
12884 argv[argc++] = xrm_option;
12886 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12887 resource_name, EMACS_CLASS,
12888 emacs_options, XtNumber (emacs_options),
12889 &argc, argv);
12891 #ifdef HAVE_X11XTR6
12892 /* I think this is to compensate for XtSetLanguageProc. */
12893 fixup_locale ();
12894 #endif
12897 #else /* not USE_X_TOOLKIT */
12898 #ifdef HAVE_X11R5
12899 XSetLocaleModifiers ("");
12900 #endif
12901 dpy = XOpenDisplay (XSTRING (display_name)->data);
12902 #endif /* not USE_X_TOOLKIT */
12904 /* Detect failure. */
12905 if (dpy == 0)
12907 UNBLOCK_INPUT;
12908 return 0;
12911 /* We have definitely succeeded. Record the new connection. */
12913 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12915 #ifdef MULTI_KBOARD
12917 struct x_display_info *share;
12918 Lisp_Object tail;
12920 for (share = x_display_list, tail = x_display_name_list; share;
12921 share = share->next, tail = XCDR (tail))
12922 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
12923 XSTRING (display_name)->data))
12924 break;
12925 if (share)
12926 dpyinfo->kboard = share->kboard;
12927 else
12929 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12930 init_kboard (dpyinfo->kboard);
12931 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12933 char *vendor = ServerVendor (dpy);
12934 dpyinfo->kboard->Vsystem_key_alist
12935 = call1 (Qvendor_specific_keysyms,
12936 build_string (vendor ? vendor : ""));
12939 dpyinfo->kboard->next_kboard = all_kboards;
12940 all_kboards = dpyinfo->kboard;
12941 /* Don't let the initial kboard remain current longer than necessary.
12942 That would cause problems if a file loaded on startup tries to
12943 prompt in the mini-buffer. */
12944 if (current_kboard == initial_kboard)
12945 current_kboard = dpyinfo->kboard;
12947 dpyinfo->kboard->reference_count++;
12949 #endif
12951 /* Put this display on the chain. */
12952 dpyinfo->next = x_display_list;
12953 x_display_list = dpyinfo;
12955 /* Put it on x_display_name_list as well, to keep them parallel. */
12956 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12957 x_display_name_list);
12958 dpyinfo->name_list_element = XCAR (x_display_name_list);
12960 dpyinfo->display = dpy;
12962 #if 0
12963 XSetAfterFunction (x_current_display, x_trace_wire);
12964 #endif /* ! 0 */
12966 dpyinfo->x_id_name
12967 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12968 + STRING_BYTES (XSTRING (Vsystem_name))
12969 + 2);
12970 sprintf (dpyinfo->x_id_name, "%s@%s",
12971 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12973 /* Figure out which modifier bits mean what. */
12974 x_find_modifier_meanings (dpyinfo);
12976 /* Get the scroll bar cursor. */
12977 dpyinfo->vertical_scroll_bar_cursor
12978 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12980 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12981 resource_name, EMACS_CLASS);
12982 #ifdef HAVE_XRMSETDATABASE
12983 XrmSetDatabase (dpyinfo->display, xrdb);
12984 #else
12985 dpyinfo->display->db = xrdb;
12986 #endif
12987 /* Put the rdb where we can find it in a way that works on
12988 all versions. */
12989 dpyinfo->xrdb = xrdb;
12991 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12992 DefaultScreen (dpyinfo->display));
12993 select_visual (dpyinfo);
12994 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
12995 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
12996 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
12997 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12998 dpyinfo->grabbed = 0;
12999 dpyinfo->reference_count = 0;
13000 dpyinfo->icon_bitmap_id = -1;
13001 dpyinfo->font_table = NULL;
13002 dpyinfo->n_fonts = 0;
13003 dpyinfo->font_table_size = 0;
13004 dpyinfo->bitmaps = 0;
13005 dpyinfo->bitmaps_size = 0;
13006 dpyinfo->bitmaps_last = 0;
13007 dpyinfo->scratch_cursor_gc = 0;
13008 dpyinfo->mouse_face_mouse_frame = 0;
13009 dpyinfo->mouse_face_deferred_gc = 0;
13010 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13011 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13012 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13013 dpyinfo->mouse_face_window = Qnil;
13014 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13015 dpyinfo->mouse_face_defer = 0;
13016 dpyinfo->x_focus_frame = 0;
13017 dpyinfo->x_focus_event_frame = 0;
13018 dpyinfo->x_highlight_frame = 0;
13019 dpyinfo->image_cache = make_image_cache ();
13021 /* See if a private colormap is requested. */
13022 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13024 if (dpyinfo->visual->class == PseudoColor)
13026 Lisp_Object value;
13027 value = display_x_get_resource (dpyinfo,
13028 build_string ("privateColormap"),
13029 build_string ("PrivateColormap"),
13030 Qnil, Qnil);
13031 if (STRINGP (value)
13032 && (!strcmp (XSTRING (value)->data, "true")
13033 || !strcmp (XSTRING (value)->data, "on")))
13034 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13037 else
13038 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13039 dpyinfo->visual, AllocNone);
13042 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13043 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13044 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13045 dpyinfo->resy = pixels * 25.4 / mm;
13046 pixels = DisplayWidth (dpyinfo->display, screen_number);
13047 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13048 dpyinfo->resx = pixels * 25.4 / mm;
13051 dpyinfo->Xatom_wm_protocols
13052 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13053 dpyinfo->Xatom_wm_take_focus
13054 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13055 dpyinfo->Xatom_wm_save_yourself
13056 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13057 dpyinfo->Xatom_wm_delete_window
13058 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13059 dpyinfo->Xatom_wm_change_state
13060 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13061 dpyinfo->Xatom_wm_configure_denied
13062 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13063 dpyinfo->Xatom_wm_window_moved
13064 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13065 dpyinfo->Xatom_editres
13066 = XInternAtom (dpyinfo->display, "Editres", False);
13067 dpyinfo->Xatom_CLIPBOARD
13068 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13069 dpyinfo->Xatom_TIMESTAMP
13070 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13071 dpyinfo->Xatom_TEXT
13072 = XInternAtom (dpyinfo->display, "TEXT", False);
13073 dpyinfo->Xatom_COMPOUND_TEXT
13074 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13075 dpyinfo->Xatom_DELETE
13076 = XInternAtom (dpyinfo->display, "DELETE", False);
13077 dpyinfo->Xatom_MULTIPLE
13078 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13079 dpyinfo->Xatom_INCR
13080 = XInternAtom (dpyinfo->display, "INCR", False);
13081 dpyinfo->Xatom_EMACS_TMP
13082 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13083 dpyinfo->Xatom_TARGETS
13084 = XInternAtom (dpyinfo->display, "TARGETS", False);
13085 dpyinfo->Xatom_NULL
13086 = XInternAtom (dpyinfo->display, "NULL", False);
13087 dpyinfo->Xatom_ATOM_PAIR
13088 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13089 /* For properties of font. */
13090 dpyinfo->Xatom_PIXEL_SIZE
13091 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13092 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13093 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13094 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13095 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13096 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13097 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13099 /* Ghostscript support. */
13100 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13101 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13103 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13104 False);
13106 dpyinfo->cut_buffers_initialized = 0;
13108 connection = ConnectionNumber (dpyinfo->display);
13109 dpyinfo->connection = connection;
13112 char null_bits[1];
13114 null_bits[0] = 0x00;
13116 dpyinfo->null_pixel
13117 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13118 null_bits, 1, 1, (long) 0, (long) 0,
13123 extern int gray_bitmap_width, gray_bitmap_height;
13124 extern unsigned char *gray_bitmap_bits;
13125 dpyinfo->gray
13126 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13127 gray_bitmap_bits,
13128 gray_bitmap_width, gray_bitmap_height,
13129 (unsigned long) 1, (unsigned long) 0, 1);
13132 #ifdef HAVE_X_I18N
13133 xim_initialize (dpyinfo, resource_name);
13134 #endif
13136 #ifdef subprocesses
13137 /* This is only needed for distinguishing keyboard and process input. */
13138 if (connection != 0)
13139 add_keyboard_wait_descriptor (connection);
13140 #endif
13142 #ifndef F_SETOWN_BUG
13143 #ifdef F_SETOWN
13144 #ifdef F_SETOWN_SOCK_NEG
13145 /* stdin is a socket here */
13146 fcntl (connection, F_SETOWN, -getpid ());
13147 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13148 fcntl (connection, F_SETOWN, getpid ());
13149 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13150 #endif /* ! defined (F_SETOWN) */
13151 #endif /* F_SETOWN_BUG */
13153 #ifdef SIGIO
13154 if (interrupt_input)
13155 init_sigio (connection);
13156 #endif /* ! defined (SIGIO) */
13158 #ifdef USE_LUCID
13159 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13160 /* Make sure that we have a valid font for dialog boxes
13161 so that Xt does not crash. */
13163 Display *dpy = dpyinfo->display;
13164 XrmValue d, fr, to;
13165 Font font;
13166 int count;
13168 d.addr = (XPointer)&dpy;
13169 d.size = sizeof (Display *);
13170 fr.addr = XtDefaultFont;
13171 fr.size = sizeof (XtDefaultFont);
13172 to.size = sizeof (Font *);
13173 to.addr = (XPointer)&font;
13174 count = x_catch_errors (dpy);
13175 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13176 abort ();
13177 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13178 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13179 x_uncatch_errors (dpy, count);
13181 #endif
13182 #endif
13184 UNBLOCK_INPUT;
13186 return dpyinfo;
13189 /* Get rid of display DPYINFO, assuming all frames are already gone,
13190 and without sending any more commands to the X server. */
13192 void
13193 x_delete_display (dpyinfo)
13194 struct x_display_info *dpyinfo;
13196 delete_keyboard_wait_descriptor (dpyinfo->connection);
13198 /* Discard this display from x_display_name_list and x_display_list.
13199 We can't use Fdelq because that can quit. */
13200 if (! NILP (x_display_name_list)
13201 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13202 x_display_name_list = XCDR (x_display_name_list);
13203 else
13205 Lisp_Object tail;
13207 tail = x_display_name_list;
13208 while (CONSP (tail) && CONSP (XCDR (tail)))
13210 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13212 XCDR (tail) = XCDR (XCDR (tail));
13213 break;
13215 tail = XCDR (tail);
13219 if (next_noop_dpyinfo == dpyinfo)
13220 next_noop_dpyinfo = dpyinfo->next;
13222 if (x_display_list == dpyinfo)
13223 x_display_list = dpyinfo->next;
13224 else
13226 struct x_display_info *tail;
13228 for (tail = x_display_list; tail; tail = tail->next)
13229 if (tail->next == dpyinfo)
13230 tail->next = tail->next->next;
13233 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13234 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13235 XrmDestroyDatabase (dpyinfo->xrdb);
13236 #endif
13237 #endif
13238 #ifdef MULTI_KBOARD
13239 if (--dpyinfo->kboard->reference_count == 0)
13240 delete_kboard (dpyinfo->kboard);
13241 #endif
13242 #ifdef HAVE_X_I18N
13243 if (dpyinfo->xim)
13244 xim_close_dpy (dpyinfo);
13245 #endif
13247 xfree (dpyinfo->font_table);
13248 xfree (dpyinfo->x_id_name);
13249 xfree (dpyinfo);
13252 /* Set up use of X before we make the first connection. */
13254 static struct redisplay_interface x_redisplay_interface =
13256 x_produce_glyphs,
13257 x_write_glyphs,
13258 x_insert_glyphs,
13259 x_clear_end_of_line,
13260 x_scroll_run,
13261 x_after_update_window_line,
13262 x_update_window_begin,
13263 x_update_window_end,
13264 XTcursor_to,
13265 x_flush,
13266 x_get_glyph_overhangs,
13267 x_fix_overlapping_area
13270 void
13271 x_initialize ()
13273 rif = &x_redisplay_interface;
13275 clear_frame_hook = x_clear_frame;
13276 ins_del_lines_hook = x_ins_del_lines;
13277 change_line_highlight_hook = x_change_line_highlight;
13278 delete_glyphs_hook = x_delete_glyphs;
13279 ring_bell_hook = XTring_bell;
13280 reset_terminal_modes_hook = XTreset_terminal_modes;
13281 set_terminal_modes_hook = XTset_terminal_modes;
13282 update_begin_hook = x_update_begin;
13283 update_end_hook = x_update_end;
13284 set_terminal_window_hook = XTset_terminal_window;
13285 read_socket_hook = XTread_socket;
13286 frame_up_to_date_hook = XTframe_up_to_date;
13287 reassert_line_highlight_hook = XTreassert_line_highlight;
13288 mouse_position_hook = XTmouse_position;
13289 frame_rehighlight_hook = XTframe_rehighlight;
13290 frame_raise_lower_hook = XTframe_raise_lower;
13291 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13292 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13293 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13294 judge_scroll_bars_hook = XTjudge_scroll_bars;
13295 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13297 scroll_region_ok = 1; /* we'll scroll partial frames */
13298 char_ins_del_ok = 0; /* just as fast to write the line */
13299 line_ins_del_ok = 1; /* we'll just blt 'em */
13300 fast_clear_end_of_line = 1; /* X does this well */
13301 memory_below_frame = 0; /* we don't remember what scrolls
13302 off the bottom */
13303 baud_rate = 19200;
13305 x_noop_count = 0;
13306 last_tool_bar_item = -1;
13307 any_help_event_p = 0;
13309 /* Try to use interrupt input; if we can't, then start polling. */
13310 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13312 #ifdef USE_X_TOOLKIT
13313 XtToolkitInitialize ();
13314 Xt_app_con = XtCreateApplicationContext ();
13315 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13317 /* Install an asynchronous timer that processes Xt timeout events
13318 every 0.1s. This is necessary because some widget sets use
13319 timeouts internally, for example the LessTif menu bar, or the
13320 Xaw3d scroll bar. When Xt timouts aren't processed, these
13321 widgets don't behave normally. */
13323 EMACS_TIME interval;
13324 EMACS_SET_SECS_USECS (interval, 0, 100000);
13325 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13327 #endif
13329 #if USE_TOOLKIT_SCROLL_BARS
13330 xaw3d_arrow_scroll = False;
13331 xaw3d_pick_top = True;
13332 #endif
13334 /* Note that there is no real way portable across R3/R4 to get the
13335 original error handler. */
13336 XSetErrorHandler (x_error_handler);
13337 XSetIOErrorHandler (x_io_error_quitter);
13339 /* Disable Window Change signals; they are handled by X events. */
13340 #ifdef SIGWINCH
13341 signal (SIGWINCH, SIG_DFL);
13342 #endif /* ! defined (SIGWINCH) */
13344 signal (SIGPIPE, x_connection_signal);
13348 void
13349 syms_of_xterm ()
13351 staticpro (&x_error_message_string);
13352 x_error_message_string = Qnil;
13354 staticpro (&x_display_name_list);
13355 x_display_name_list = Qnil;
13357 staticpro (&last_mouse_scroll_bar);
13358 last_mouse_scroll_bar = Qnil;
13360 staticpro (&Qvendor_specific_keysyms);
13361 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13363 staticpro (&last_mouse_press_frame);
13364 last_mouse_press_frame = Qnil;
13366 staticpro (&help_echo);
13367 help_echo = Qnil;
13368 staticpro (&previous_help_echo);
13369 previous_help_echo = Qnil;
13371 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13372 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13373 For example, if a block cursor is over a tab, it will be drawn as\n\
13374 wide as that tab on the display.");
13375 x_stretch_cursor_p = 0;
13377 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13378 "If not nil, Emacs uses toolkit scroll bars.");
13379 #if USE_TOOLKIT_SCROLL_BARS
13380 x_toolkit_scroll_bars_p = 1;
13381 #else
13382 x_toolkit_scroll_bars_p = 0;
13383 #endif
13385 staticpro (&last_mouse_motion_frame);
13386 last_mouse_motion_frame = Qnil;
13389 #endif /* not HAVE_X_WINDOWS */