(esc-map): Change ; to comment-dwim and use the new function
[emacs.git] / src / xterm.c
blob28280a4bd4609f053f4e4359e87fccce96ebf364
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
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 "dispextern.h"
76 #include "fontset.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 *, int));
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 int *));
1099 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1100 int, XChar2b *, int));
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));
1111 /* Return a pointer to per-char metric information in FONT of a
1112 character pointed by B which is a pointer to an XChar2b. */
1114 #define PER_CHAR_METRIC(font, b) \
1115 ((font)->per_char \
1116 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1117 + (((font)->min_byte1 || (font)->max_byte1) \
1118 ? (((b)->byte1 - (font)->min_byte1) \
1119 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1120 : 0)) \
1121 : &((font)->max_bounds))
1124 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1125 is not contained in the font. */
1127 static INLINE XCharStruct *
1128 x_per_char_metric (font, char2b)
1129 XFontStruct *font;
1130 XChar2b *char2b;
1132 /* The result metric information. */
1133 XCharStruct *pcm = NULL;
1135 xassert (font && char2b);
1137 if (font->per_char != NULL)
1139 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1141 /* min_char_or_byte2 specifies the linear character index
1142 corresponding to the first element of the per_char array,
1143 max_char_or_byte2 is the index of the last character. A
1144 character with non-zero CHAR2B->byte1 is not in the font.
1145 A character with byte2 less than min_char_or_byte2 or
1146 greater max_char_or_byte2 is not in the font. */
1147 if (char2b->byte1 == 0
1148 && char2b->byte2 >= font->min_char_or_byte2
1149 && char2b->byte2 <= font->max_char_or_byte2)
1150 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1152 else
1154 /* If either min_byte1 or max_byte1 are nonzero, both
1155 min_char_or_byte2 and max_char_or_byte2 are less than
1156 256, and the 2-byte character index values corresponding
1157 to the per_char array element N (counting from 0) are:
1159 byte1 = N/D + min_byte1
1160 byte2 = N\D + min_char_or_byte2
1162 where:
1164 D = max_char_or_byte2 - min_char_or_byte2 + 1
1165 / = integer division
1166 \ = integer modulus */
1167 if (char2b->byte1 >= font->min_byte1
1168 && char2b->byte1 <= font->max_byte1
1169 && char2b->byte2 >= font->min_char_or_byte2
1170 && char2b->byte2 <= font->max_char_or_byte2)
1172 pcm = (font->per_char
1173 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1174 * (char2b->byte1 - font->min_byte1))
1175 + (char2b->byte2 - font->min_char_or_byte2));
1179 else
1181 /* If the per_char pointer is null, all glyphs between the first
1182 and last character indexes inclusive have the same
1183 information, as given by both min_bounds and max_bounds. */
1184 if (char2b->byte2 >= font->min_char_or_byte2
1185 && char2b->byte2 <= font->max_char_or_byte2)
1186 pcm = &font->max_bounds;
1189 return ((pcm == NULL
1190 || pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1191 ? NULL : pcm);
1195 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1196 the two-byte form of C. Encoding is returned in *CHAR2B. */
1198 static INLINE void
1199 x_encode_char (c, char2b, font_info)
1200 int c;
1201 XChar2b *char2b;
1202 struct font_info *font_info;
1204 int charset = CHAR_CHARSET (c);
1205 XFontStruct *font = font_info->font;
1207 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1208 This may be either a program in a special encoder language or a
1209 fixed encoding. */
1210 if (font_info->font_encoder)
1212 /* It's a program. */
1213 struct ccl_program *ccl = font_info->font_encoder;
1215 if (CHARSET_DIMENSION (charset) == 1)
1217 ccl->reg[0] = charset;
1218 ccl->reg[1] = char2b->byte2;
1220 else
1222 ccl->reg[0] = charset;
1223 ccl->reg[1] = char2b->byte1;
1224 ccl->reg[2] = char2b->byte2;
1227 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1229 /* We assume that MSBs are appropriately set/reset by CCL
1230 program. */
1231 if (font->max_byte1 == 0) /* 1-byte font */
1232 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1233 else
1234 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1236 else if (font_info->encoding[charset])
1238 /* Fixed encoding scheme. See fontset.h for the meaning of the
1239 encoding numbers. */
1240 int enc = font_info->encoding[charset];
1242 if ((enc == 1 || enc == 2)
1243 && CHARSET_DIMENSION (charset) == 2)
1244 char2b->byte1 |= 0x80;
1246 if (enc == 1 || enc == 3)
1247 char2b->byte2 |= 0x80;
1252 /* Get face and two-byte form of character C in face FACE_ID on frame
1253 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1254 means we want to display multibyte text. Value is a pointer to a
1255 realized face that is ready for display. */
1257 static INLINE struct face *
1258 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1259 struct frame *f;
1260 int c, face_id;
1261 XChar2b *char2b;
1262 int multibyte_p;
1264 struct face *face = FACE_FROM_ID (f, face_id);
1266 if (!multibyte_p)
1268 /* Unibyte case. We don't have to encode, but we have to make
1269 sure to use a face suitable for unibyte. */
1270 char2b->byte1 = 0;
1271 char2b->byte2 = c;
1272 face_id = FACE_FOR_CHAR (f, face, c);
1273 face = FACE_FROM_ID (f, face_id);
1275 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1277 /* Case of ASCII in a face known to fit ASCII. */
1278 char2b->byte1 = 0;
1279 char2b->byte2 = c;
1281 else
1283 int c1, c2, charset;
1285 /* Split characters into bytes. If c2 is -1 afterwards, C is
1286 really a one-byte character so that byte1 is zero. */
1287 SPLIT_CHAR (c, charset, c1, c2);
1288 if (c2 > 0)
1289 char2b->byte1 = c1, char2b->byte2 = c2;
1290 else
1291 char2b->byte1 = 0, char2b->byte2 = c1;
1293 /* Maybe encode the character in *CHAR2B. */
1294 if (face->font != NULL)
1296 struct font_info *font_info
1297 = FONT_INFO_FROM_ID (f, face->font_info_id);
1298 if (font_info)
1299 x_encode_char (c, char2b, font_info);
1303 /* Make sure X resources of the face are allocated. */
1304 xassert (face != NULL);
1305 PREPARE_FACE_FOR_DISPLAY (f, face);
1307 return face;
1311 /* Get face and two-byte form of character glyph GLYPH on frame F.
1312 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1313 a pointer to a realized face that is ready for display. */
1315 static INLINE struct face *
1316 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1317 struct frame *f;
1318 struct glyph *glyph;
1319 XChar2b *char2b;
1320 int *two_byte_p;
1322 struct face *face;
1324 xassert (glyph->type == CHAR_GLYPH);
1325 face = FACE_FROM_ID (f, glyph->face_id);
1327 if (two_byte_p)
1328 *two_byte_p = 0;
1330 if (!glyph->multibyte_p)
1332 /* Unibyte case. We don't have to encode, but we have to make
1333 sure to use a face suitable for unibyte. */
1334 char2b->byte1 = 0;
1335 char2b->byte2 = glyph->u.ch;
1337 else if (glyph->u.ch < 128
1338 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1340 /* Case of ASCII in a face known to fit ASCII. */
1341 char2b->byte1 = 0;
1342 char2b->byte2 = glyph->u.ch;
1344 else
1346 int c1, c2, charset;
1348 /* Split characters into bytes. If c2 is -1 afterwards, C is
1349 really a one-byte character so that byte1 is zero. */
1350 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1351 if (c2 > 0)
1352 char2b->byte1 = c1, char2b->byte2 = c2;
1353 else
1354 char2b->byte1 = 0, char2b->byte2 = c1;
1356 /* Maybe encode the character in *CHAR2B. */
1357 if (charset != CHARSET_ASCII)
1359 struct font_info *font_info
1360 = FONT_INFO_FROM_ID (f, face->font_info_id);
1361 if (font_info)
1363 x_encode_char (glyph->u.ch, char2b, font_info);
1364 if (two_byte_p)
1365 *two_byte_p
1366 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1371 /* Make sure X resources of the face are allocated. */
1372 xassert (face != NULL);
1373 PREPARE_FACE_FOR_DISPLAY (f, face);
1374 return face;
1378 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1379 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1381 static INLINE void
1382 x_append_glyph (it)
1383 struct it *it;
1385 struct glyph *glyph;
1386 enum glyph_row_area area = it->area;
1388 xassert (it->glyph_row);
1389 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1391 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1392 if (glyph < it->glyph_row->glyphs[area + 1])
1394 /* Play it safe. If sub-structures of the glyph are not all the
1395 same size, it otherwise be that some bits stay set. This
1396 would prevent a comparison with GLYPH_EQUAL_P. */
1397 glyph->u.val = 0;
1399 glyph->type = CHAR_GLYPH;
1400 glyph->pixel_width = it->pixel_width;
1401 glyph->u.ch = it->char_to_display;
1402 glyph->face_id = it->face_id;
1403 glyph->charpos = CHARPOS (it->position);
1404 glyph->object = it->object;
1405 glyph->left_box_line_p = it->start_of_box_run_p;
1406 glyph->right_box_line_p = it->end_of_box_run_p;
1407 glyph->voffset = it->voffset;
1408 glyph->multibyte_p = it->multibyte_p;
1409 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1410 || it->phys_descent > it->descent);
1411 glyph->glyph_not_available_p = it->glyph_not_available_p;
1412 ++it->glyph_row->used[area];
1416 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1417 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1419 static INLINE void
1420 x_append_composite_glyph (it)
1421 struct it *it;
1423 struct glyph *glyph;
1424 enum glyph_row_area area = it->area;
1426 xassert (it->glyph_row);
1428 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1429 if (glyph < it->glyph_row->glyphs[area + 1])
1431 /* Play it safe. If sub-structures of the glyph are not all the
1432 same size, it otherwise be that some bits stay set. This
1433 would prevent a comparison with GLYPH_EQUAL_P. */
1434 glyph->u.val = 0;
1436 glyph->type = COMPOSITE_GLYPH;
1437 glyph->pixel_width = it->pixel_width;
1438 glyph->u.cmp_id = it->cmp_id;
1439 glyph->face_id = it->face_id;
1440 glyph->charpos = CHARPOS (it->position);
1441 glyph->object = it->object;
1442 glyph->left_box_line_p = it->start_of_box_run_p;
1443 glyph->right_box_line_p = it->end_of_box_run_p;
1444 glyph->voffset = it->voffset;
1445 glyph->multibyte_p = it->multibyte_p;
1446 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1447 || it->phys_descent > it->descent);
1448 ++it->glyph_row->used[area];
1453 /* Change IT->ascent and IT->height according to the setting of
1454 IT->voffset. */
1456 static INLINE void
1457 take_vertical_position_into_account (it)
1458 struct it *it;
1460 if (it->voffset)
1462 if (it->voffset < 0)
1463 /* Increase the ascent so that we can display the text higher
1464 in the line. */
1465 it->ascent += abs (it->voffset);
1466 else
1467 /* Increase the descent so that we can display the text lower
1468 in the line. */
1469 it->descent += it->voffset;
1474 /* Produce glyphs/get display metrics for the image IT is loaded with.
1475 See the description of struct display_iterator in dispextern.h for
1476 an overview of struct display_iterator. */
1478 static void
1479 x_produce_image_glyph (it)
1480 struct it *it;
1482 struct image *img;
1483 struct face *face;
1485 xassert (it->what == IT_IMAGE);
1487 face = FACE_FROM_ID (it->f, it->face_id);
1488 img = IMAGE_FROM_ID (it->f, it->image_id);
1489 xassert (img);
1491 /* Make sure X resources of the face and image are loaded. */
1492 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1493 prepare_image_for_display (it->f, img);
1495 it->ascent = it->phys_ascent = image_ascent (img, face);
1496 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1497 it->pixel_width = img->width + 2 * img->margin;
1499 it->nglyphs = 1;
1501 if (face->box != FACE_NO_BOX)
1503 it->ascent += face->box_line_width;
1504 it->descent += face->box_line_width;
1506 if (it->start_of_box_run_p)
1507 it->pixel_width += face->box_line_width;
1508 if (it->end_of_box_run_p)
1509 it->pixel_width += face->box_line_width;
1512 take_vertical_position_into_account (it);
1514 if (it->glyph_row)
1516 struct glyph *glyph;
1517 enum glyph_row_area area = it->area;
1519 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1520 if (glyph < it->glyph_row->glyphs[area + 1])
1522 glyph->type = IMAGE_GLYPH;
1523 glyph->u.img_id = img->id;
1524 glyph->face_id = it->face_id;
1525 glyph->pixel_width = it->pixel_width;
1526 glyph->charpos = CHARPOS (it->position);
1527 glyph->object = it->object;
1528 glyph->left_box_line_p = it->start_of_box_run_p;
1529 glyph->right_box_line_p = it->end_of_box_run_p;
1530 glyph->voffset = it->voffset;
1531 glyph->multibyte_p = it->multibyte_p;
1532 ++it->glyph_row->used[area];
1538 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1539 of the glyph, WIDTH and HEIGHT are the width and height of the
1540 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1541 ascent of the glyph (0 <= ASCENT <= 1). */
1543 static void
1544 x_append_stretch_glyph (it, object, width, height, ascent)
1545 struct it *it;
1546 Lisp_Object object;
1547 int width, height;
1548 double ascent;
1550 struct glyph *glyph;
1551 enum glyph_row_area area = it->area;
1553 xassert (ascent >= 0 && ascent <= 1);
1555 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1556 if (glyph < it->glyph_row->glyphs[area + 1])
1558 glyph->type = STRETCH_GLYPH;
1559 glyph->u.stretch.ascent = height * ascent;
1560 glyph->u.stretch.height = height;
1561 glyph->face_id = it->face_id;
1562 glyph->pixel_width = width;
1563 glyph->charpos = CHARPOS (it->position);
1564 glyph->object = object;
1565 glyph->left_box_line_p = it->start_of_box_run_p;
1566 glyph->right_box_line_p = it->end_of_box_run_p;
1567 glyph->voffset = it->voffset;
1568 glyph->multibyte_p = it->multibyte_p;
1569 ++it->glyph_row->used[area];
1574 /* Produce a stretch glyph for iterator IT. IT->object is the value
1575 of the glyph property displayed. The value must be a list
1576 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1577 being recognized:
1579 1. `:width WIDTH' specifies that the space should be WIDTH *
1580 canonical char width wide. WIDTH may be an integer or floating
1581 point number.
1583 2. `:relative-width FACTOR' specifies that the width of the stretch
1584 should be computed from the width of the first character having the
1585 `glyph' property, and should be FACTOR times that width.
1587 3. `:align-to HPOS' specifies that the space should be wide enough
1588 to reach HPOS, a value in canonical character units.
1590 Exactly one of the above pairs must be present.
1592 4. `:height HEIGHT' specifies that the height of the stretch produced
1593 should be HEIGHT, measured in canonical character units.
1595 5. `:relative-height FACTOR' specifies that the height of the the
1596 stretch should be FACTOR times the height of the characters having
1597 the glyph property.
1599 Either none or exactly one of 4 or 5 must be present.
1601 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1602 of the stretch should be used for the ascent of the stretch.
1603 ASCENT must be in the range 0 <= ASCENT <= 100. */
1605 #define NUMVAL(X) \
1606 ((INTEGERP (X) || FLOATP (X)) \
1607 ? XFLOATINT (X) \
1608 : - 1)
1611 static void
1612 x_produce_stretch_glyph (it)
1613 struct it *it;
1615 /* (space :width WIDTH :height HEIGHT. */
1616 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1617 extern Lisp_Object QCrelative_width, QCrelative_height;
1618 extern Lisp_Object QCalign_to;
1619 Lisp_Object prop, plist;
1620 double width = 0, height = 0, ascent = 0;
1621 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1622 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1624 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1626 /* List should start with `space'. */
1627 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1628 plist = XCDR (it->object);
1630 /* Compute the width of the stretch. */
1631 if (prop = Fplist_get (plist, QCwidth),
1632 NUMVAL (prop) > 0)
1633 /* Absolute width `:width WIDTH' specified and valid. */
1634 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1635 else if (prop = Fplist_get (plist, QCrelative_width),
1636 NUMVAL (prop) > 0)
1638 /* Relative width `:relative-width FACTOR' specified and valid.
1639 Compute the width of the characters having the `glyph'
1640 property. */
1641 struct it it2;
1642 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1644 it2 = *it;
1645 if (it->multibyte_p)
1647 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1648 - IT_BYTEPOS (*it));
1649 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1651 else
1652 it2.c = *p, it2.len = 1;
1654 it2.glyph_row = NULL;
1655 it2.what = IT_CHARACTER;
1656 x_produce_glyphs (&it2);
1657 width = NUMVAL (prop) * it2.pixel_width;
1659 else if (prop = Fplist_get (plist, QCalign_to),
1660 NUMVAL (prop) > 0)
1661 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1662 else
1663 /* Nothing specified -> width defaults to canonical char width. */
1664 width = CANON_X_UNIT (it->f);
1666 /* Compute height. */
1667 if (prop = Fplist_get (plist, QCheight),
1668 NUMVAL (prop) > 0)
1669 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1670 else if (prop = Fplist_get (plist, QCrelative_height),
1671 NUMVAL (prop) > 0)
1672 height = FONT_HEIGHT (font) * NUMVAL (prop);
1673 else
1674 height = FONT_HEIGHT (font);
1676 /* Compute percentage of height used for ascent. If
1677 `:ascent ASCENT' is present and valid, use that. Otherwise,
1678 derive the ascent from the font in use. */
1679 if (prop = Fplist_get (plist, QCascent),
1680 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1681 ascent = NUMVAL (prop) / 100.0;
1682 else
1683 ascent = (double) font->ascent / FONT_HEIGHT (font);
1685 if (width <= 0)
1686 width = 1;
1687 if (height <= 0)
1688 height = 1;
1690 if (it->glyph_row)
1692 Lisp_Object object = it->stack[it->sp - 1].string;
1693 if (!STRINGP (object))
1694 object = it->w->buffer;
1695 x_append_stretch_glyph (it, object, width, height, ascent);
1698 it->pixel_width = width;
1699 it->ascent = it->phys_ascent = height * ascent;
1700 it->descent = it->phys_descent = height - it->ascent;
1701 it->nglyphs = 1;
1703 if (face->box != FACE_NO_BOX)
1705 it->ascent += face->box_line_width;
1706 it->descent += face->box_line_width;
1708 if (it->start_of_box_run_p)
1709 it->pixel_width += face->box_line_width;
1710 if (it->end_of_box_run_p)
1711 it->pixel_width += face->box_line_width;
1714 take_vertical_position_into_account (it);
1717 /* Return proper value to be used as baseline offset of font that has
1718 ASCENT and DESCENT to draw characters by the font at the vertical
1719 center of the line of frame F.
1721 Here, out task is to find the value of BOFF in the following figure;
1723 -------------------------+-----------+-
1724 -+-+---------+-+ | |
1725 | | | | | |
1726 | | | | F_ASCENT F_HEIGHT
1727 | | | ASCENT | |
1728 HEIGHT | | | | |
1729 | | |-|-+------+-----------|------- baseline
1730 | | | | BOFF | |
1731 | |---------|-+-+ | |
1732 | | | DESCENT | |
1733 -+-+---------+-+ F_DESCENT |
1734 -------------------------+-----------+-
1736 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1737 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1738 DESCENT = FONT->descent
1739 HEIGHT = FONT_HEIGHT (FONT)
1740 F_DESCENT = (F->output_data.x->font->descent
1741 - F->output_data.x->baseline_offset)
1742 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1745 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1746 ((FONT)->descent \
1747 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1748 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1750 /* Produce glyphs/get display metrics for the display element IT is
1751 loaded with. See the description of struct display_iterator in
1752 dispextern.h for an overview of struct display_iterator. */
1754 static void
1755 x_produce_glyphs (it)
1756 struct it *it;
1758 it->glyph_not_available_p = 0;
1760 if (it->what == IT_CHARACTER)
1762 XChar2b char2b;
1763 XFontStruct *font;
1764 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1765 XCharStruct *pcm;
1766 int font_not_found_p;
1767 struct font_info *font_info;
1768 int boff; /* baseline offset */
1770 /* Maybe translate single-byte characters to multibyte, or the
1771 other way. */
1772 it->char_to_display = it->c;
1773 if (!ASCII_BYTE_P (it->c))
1775 if (unibyte_display_via_language_environment
1776 && SINGLE_BYTE_CHAR_P (it->c)
1777 && (it->c >= 0240
1778 || !NILP (Vnonascii_translation_table)))
1780 it->char_to_display = unibyte_char_to_multibyte (it->c);
1781 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1782 face = FACE_FROM_ID (it->f, it->face_id);
1784 else if (!SINGLE_BYTE_CHAR_P (it->c)
1785 && !it->multibyte_p)
1787 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1788 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1789 face = FACE_FROM_ID (it->f, it->face_id);
1793 /* Get font to use. Encode IT->char_to_display. */
1794 x_get_char_face_and_encoding (it->f, it->char_to_display,
1795 it->face_id, &char2b,
1796 it->multibyte_p);
1797 font = face->font;
1799 /* When no suitable font found, use the default font. */
1800 font_not_found_p = font == NULL;
1801 if (font_not_found_p)
1803 font = FRAME_FONT (it->f);
1804 boff = it->f->output_data.x->baseline_offset;
1805 font_info = NULL;
1807 else
1809 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1810 boff = font_info->baseline_offset;
1811 if (font_info->vertical_centering)
1812 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1815 if (it->char_to_display >= ' '
1816 && (!it->multibyte_p || it->char_to_display < 128))
1818 /* Either unibyte or ASCII. */
1819 int stretched_p;
1821 it->nglyphs = 1;
1823 pcm = x_per_char_metric (font, &char2b);
1824 it->ascent = font->ascent + boff;
1825 it->descent = font->descent - boff;
1827 if (pcm)
1829 it->phys_ascent = pcm->ascent + boff;
1830 it->phys_descent = pcm->descent - boff;
1831 it->pixel_width = pcm->width;
1833 else
1835 it->glyph_not_available_p = 1;
1836 it->phys_ascent = font->ascent + boff;
1837 it->phys_descent = font->descent - boff;
1838 it->pixel_width = FONT_WIDTH (font);
1841 /* If this is a space inside a region of text with
1842 `space-width' property, change its width. */
1843 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1844 if (stretched_p)
1845 it->pixel_width *= XFLOATINT (it->space_width);
1847 /* If face has a box, add the box thickness to the character
1848 height. If character has a box line to the left and/or
1849 right, add the box line width to the character's width. */
1850 if (face->box != FACE_NO_BOX)
1852 int thick = face->box_line_width;
1854 it->ascent += thick;
1855 it->descent += thick;
1857 if (it->start_of_box_run_p)
1858 it->pixel_width += thick;
1859 if (it->end_of_box_run_p)
1860 it->pixel_width += thick;
1863 /* If face has an overline, add the height of the overline
1864 (1 pixel) and a 1 pixel margin to the character height. */
1865 if (face->overline_p)
1866 it->ascent += 2;
1868 take_vertical_position_into_account (it);
1870 /* If we have to actually produce glyphs, do it. */
1871 if (it->glyph_row)
1873 if (stretched_p)
1875 /* Translate a space with a `space-width' property
1876 into a stretch glyph. */
1877 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1878 x_append_stretch_glyph (it, it->object, it->pixel_width,
1879 it->ascent + it->descent, ascent);
1881 else
1882 x_append_glyph (it);
1884 /* If characters with lbearing or rbearing are displayed
1885 in this line, record that fact in a flag of the
1886 glyph row. This is used to optimize X output code. */
1887 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1888 it->glyph_row->contains_overlapping_glyphs_p = 1;
1891 else if (it->char_to_display == '\n')
1893 /* A newline has no width but we need the height of the line. */
1894 it->pixel_width = 0;
1895 it->nglyphs = 0;
1896 it->ascent = it->phys_ascent = font->ascent + boff;
1897 it->descent = it->phys_descent = font->descent - boff;
1899 if (face->box != FACE_NO_BOX)
1901 int thick = face->box_line_width;
1902 it->ascent += thick;
1903 it->descent += thick;
1906 else if (it->char_to_display == '\t')
1908 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1909 int x = it->current_x + it->continuation_lines_width;
1910 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1912 it->pixel_width = next_tab_x - x;
1913 it->nglyphs = 1;
1914 it->ascent = it->phys_ascent = font->ascent + boff;
1915 it->descent = it->phys_descent = font->descent - boff;
1917 if (it->glyph_row)
1919 double ascent = (double) it->ascent / (it->ascent + it->descent);
1920 x_append_stretch_glyph (it, it->object, it->pixel_width,
1921 it->ascent + it->descent, ascent);
1924 else
1926 /* A multi-byte character. Assume that the display width of the
1927 character is the width of the character multiplied by the
1928 width of the font. */
1930 /* If we found a font, this font should give us the right
1931 metrics. If we didn't find a font, use the frame's
1932 default font and calculate the width of the character
1933 from the charset width; this is what old redisplay code
1934 did. */
1935 pcm = x_per_char_metric (font, &char2b);
1936 if (font_not_found_p || !pcm)
1938 int charset = CHAR_CHARSET (it->char_to_display);
1940 it->glyph_not_available_p = 1;
1941 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1942 * CHARSET_WIDTH (charset));
1943 it->phys_ascent = font->ascent + boff;
1944 it->phys_descent = font->descent - boff;
1946 else
1948 it->pixel_width = pcm->width;
1949 it->phys_ascent = pcm->ascent + boff;
1950 it->phys_descent = pcm->descent - boff;
1951 if (it->glyph_row
1952 && (pcm->lbearing < 0
1953 || pcm->rbearing > pcm->width))
1954 it->glyph_row->contains_overlapping_glyphs_p = 1;
1956 it->nglyphs = 1;
1957 it->ascent = font->ascent + boff;
1958 it->descent = font->descent - boff;
1959 if (face->box != FACE_NO_BOX)
1961 int thick = face->box_line_width;
1962 it->ascent += thick;
1963 it->descent += thick;
1965 if (it->start_of_box_run_p)
1966 it->pixel_width += thick;
1967 if (it->end_of_box_run_p)
1968 it->pixel_width += thick;
1971 /* If face has an overline, add the height of the overline
1972 (1 pixel) and a 1 pixel margin to the character height. */
1973 if (face->overline_p)
1974 it->ascent += 2;
1976 take_vertical_position_into_account (it);
1978 if (it->glyph_row)
1979 x_append_glyph (it);
1982 else if (it->what == IT_COMPOSITION)
1984 /* Note: A composition is represented as one glyph in the
1985 glyph matrix. There are no padding glyphs. */
1986 XChar2b char2b;
1987 XFontStruct *font;
1988 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1989 XCharStruct *pcm;
1990 int font_not_found_p;
1991 struct font_info *font_info;
1992 int boff; /* baseline offset */
1993 struct composition *cmp = composition_table[it->cmp_id];
1995 /* Maybe translate single-byte characters to multibyte. */
1996 it->char_to_display = it->c;
1997 if (unibyte_display_via_language_environment
1998 && SINGLE_BYTE_CHAR_P (it->c)
1999 && (it->c >= 0240
2000 || (it->c >= 0200
2001 && !NILP (Vnonascii_translation_table))))
2003 it->char_to_display = unibyte_char_to_multibyte (it->c);
2006 /* Get face and font to use. Encode IT->char_to_display. */
2007 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2008 face = FACE_FROM_ID (it->f, it->face_id);
2009 x_get_char_face_and_encoding (it->f, it->char_to_display,
2010 it->face_id, &char2b, it->multibyte_p);
2011 font = face->font;
2013 /* When no suitable font found, use the default font. */
2014 font_not_found_p = font == NULL;
2015 if (font_not_found_p)
2017 font = FRAME_FONT (it->f);
2018 boff = it->f->output_data.x->baseline_offset;
2019 font_info = NULL;
2021 else
2023 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2024 boff = font_info->baseline_offset;
2025 if (font_info->vertical_centering)
2026 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2029 /* There are no padding glyphs, so there is only one glyph to
2030 produce for the composition. Important is that pixel_width,
2031 ascent and descent are the values of what is drawn by
2032 draw_glyphs (i.e. the values of the overall glyphs composed). */
2033 it->nglyphs = 1;
2035 /* If we have not yet calculated pixel size data of glyphs of
2036 the composition for the current face font, calculate them
2037 now. Theoretically, we have to check all fonts for the
2038 glyphs, but that requires much time and memory space. So,
2039 here we check only the font of the first glyph. This leads
2040 to incorrect display very rarely, and C-l (recenter) can
2041 correct the display anyway. */
2042 if (cmp->font != (void *) font)
2044 /* Ascent and descent of the font of the first character of
2045 this composition (adjusted by baseline offset). Ascent
2046 and descent of overall glyphs should not be less than
2047 them respectively. */
2048 int font_ascent = font->ascent + boff;
2049 int font_descent = font->descent - boff;
2050 /* Bounding box of the overall glyphs. */
2051 int leftmost, rightmost, lowest, highest;
2052 int i, width, ascent, descent;
2054 cmp->font = (void *) font;
2056 /* Initialize the bounding box. */
2057 pcm = x_per_char_metric (font, &char2b);
2058 if (pcm)
2060 width = pcm->width;
2061 ascent = pcm->ascent;
2062 descent = pcm->descent;
2064 else
2066 width = FONT_WIDTH (font);
2067 ascent = font->ascent;
2068 descent = font->descent;
2071 rightmost = width;
2072 lowest = - descent + boff;
2073 highest = ascent + boff;
2074 leftmost = 0;
2076 if (font_info
2077 && font_info->default_ascent
2078 && CHAR_TABLE_P (Vuse_default_ascent)
2079 && !NILP (Faref (Vuse_default_ascent,
2080 make_number (it->char_to_display))))
2081 highest = font_info->default_ascent + boff;
2083 /* Draw the first glyph at the normal position. It may be
2084 shifted to right later if some other glyphs are drawn at
2085 the left. */
2086 cmp->offsets[0] = 0;
2087 cmp->offsets[1] = boff;
2089 /* Set cmp->offsets for the remaining glyphs. */
2090 for (i = 1; i < cmp->glyph_len; i++)
2092 int left, right, btm, top;
2093 int ch = COMPOSITION_GLYPH (cmp, i);
2094 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2096 face = FACE_FROM_ID (it->f, face_id);
2097 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2098 it->multibyte_p);
2099 font = face->font;
2100 if (font == NULL)
2102 font = FRAME_FONT (it->f);
2103 boff = it->f->output_data.x->baseline_offset;
2104 font_info = NULL;
2106 else
2108 font_info
2109 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2110 boff = font_info->baseline_offset;
2111 if (font_info->vertical_centering)
2112 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2115 pcm = x_per_char_metric (font, &char2b);
2116 if (pcm)
2118 width = pcm->width;
2119 ascent = pcm->ascent;
2120 descent = pcm->descent;
2122 else
2124 width = FONT_WIDTH (font);
2125 ascent = font->ascent;
2126 descent = font->descent;
2129 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2131 /* Relative composition with or without
2132 alternate chars. */
2133 left = (leftmost + rightmost - width) / 2;
2134 btm = - descent + boff;
2135 if (font_info && font_info->relative_compose
2136 && (! CHAR_TABLE_P (Vignore_relative_composition)
2137 || NILP (Faref (Vignore_relative_composition,
2138 make_number (ch)))))
2141 if (- descent >= font_info->relative_compose)
2142 /* One extra pixel between two glyphs. */
2143 btm = highest + 1;
2144 else if (ascent <= 0)
2145 /* One extra pixel between two glyphs. */
2146 btm = lowest - 1 - ascent - descent;
2149 else
2151 /* A composition rule is specified by an integer
2152 value that encodes global and new reference
2153 points (GREF and NREF). GREF and NREF are
2154 specified by numbers as below:
2156 0---1---2 -- ascent
2160 9--10--11 -- center
2162 ---3---4---5--- baseline
2164 6---7---8 -- descent
2166 int rule = COMPOSITION_RULE (cmp, i);
2167 int gref, nref, grefx, grefy, nrefx, nrefy;
2169 COMPOSITION_DECODE_RULE (rule, gref, nref);
2170 grefx = gref % 3, nrefx = nref % 3;
2171 grefy = gref / 3, nrefy = nref / 3;
2173 left = (leftmost
2174 + grefx * (rightmost - leftmost) / 2
2175 - nrefx * width / 2);
2176 btm = ((grefy == 0 ? highest
2177 : grefy == 1 ? 0
2178 : grefy == 2 ? lowest
2179 : (highest + lowest) / 2)
2180 - (nrefy == 0 ? ascent + descent
2181 : nrefy == 1 ? descent - boff
2182 : nrefy == 2 ? 0
2183 : (ascent + descent) / 2));
2186 cmp->offsets[i * 2] = left;
2187 cmp->offsets[i * 2 + 1] = btm + descent;
2189 /* Update the bounding box of the overall glyphs. */
2190 right = left + width;
2191 top = btm + descent + ascent;
2192 if (left < leftmost)
2193 leftmost = left;
2194 if (right > rightmost)
2195 rightmost = right;
2196 if (top > highest)
2197 highest = top;
2198 if (btm < lowest)
2199 lowest = btm;
2202 /* If there are glyphs whose x-offsets are negative,
2203 shift all glyphs to the right and make all x-offsets
2204 non-negative. */
2205 if (leftmost < 0)
2207 for (i = 0; i < cmp->glyph_len; i++)
2208 cmp->offsets[i * 2] -= leftmost;
2209 rightmost -= leftmost;
2212 cmp->pixel_width = rightmost;
2213 cmp->ascent = highest;
2214 cmp->descent = - lowest;
2215 if (cmp->ascent < font_ascent)
2216 cmp->ascent = font_ascent;
2217 if (cmp->descent < font_descent)
2218 cmp->descent = font_descent;
2221 it->pixel_width = cmp->pixel_width;
2222 it->ascent = it->phys_ascent = cmp->ascent;
2223 it->descent = it->phys_descent = cmp->descent;
2225 if (face->box != FACE_NO_BOX)
2227 int thick = face->box_line_width;
2228 it->ascent += thick;
2229 it->descent += thick;
2231 if (it->start_of_box_run_p)
2232 it->pixel_width += thick;
2233 if (it->end_of_box_run_p)
2234 it->pixel_width += thick;
2237 /* If face has an overline, add the height of the overline
2238 (1 pixel) and a 1 pixel margin to the character height. */
2239 if (face->overline_p)
2240 it->ascent += 2;
2242 take_vertical_position_into_account (it);
2244 if (it->glyph_row)
2245 x_append_composite_glyph (it);
2247 else if (it->what == IT_IMAGE)
2248 x_produce_image_glyph (it);
2249 else if (it->what == IT_STRETCH)
2250 x_produce_stretch_glyph (it);
2252 /* Accumulate dimensions. */
2253 xassert (it->ascent >= 0 && it->descent > 0);
2254 if (it->area == TEXT_AREA)
2255 it->current_x += it->pixel_width;
2257 it->descent += it->extra_line_spacing;
2259 it->max_ascent = max (it->max_ascent, it->ascent);
2260 it->max_descent = max (it->max_descent, it->descent);
2261 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2262 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2266 /* Estimate the pixel height of the mode or top line on frame F.
2267 FACE_ID specifies what line's height to estimate. */
2270 x_estimate_mode_line_height (f, face_id)
2271 struct frame *f;
2272 enum face_id face_id;
2274 int height = 1;
2276 /* This function is called so early when Emacs starts that the face
2277 cache and mode line face are not yet initialized. */
2278 if (FRAME_FACE_CACHE (f))
2280 struct face *face = FACE_FROM_ID (f, face_id);
2281 if (face)
2282 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2285 return height;
2289 /***********************************************************************
2290 Glyph display
2291 ***********************************************************************/
2293 /* A sequence of glyphs to be drawn in the same face.
2295 This data structure is not really completely X specific, so it
2296 could possibly, at least partially, be useful for other systems. It
2297 is currently not part of the external redisplay interface because
2298 it's not clear what other systems will need. */
2300 struct glyph_string
2302 /* X-origin of the string. */
2303 int x;
2305 /* Y-origin and y-position of the base line of this string. */
2306 int y, ybase;
2308 /* The width of the string, not including a face extension. */
2309 int width;
2311 /* The width of the string, including a face extension. */
2312 int background_width;
2314 /* The height of this string. This is the height of the line this
2315 string is drawn in, and can be different from the height of the
2316 font the string is drawn in. */
2317 int height;
2319 /* Number of pixels this string overwrites in front of its x-origin.
2320 This number is zero if the string has an lbearing >= 0; it is
2321 -lbearing, if the string has an lbearing < 0. */
2322 int left_overhang;
2324 /* Number of pixels this string overwrites past its right-most
2325 nominal x-position, i.e. x + width. Zero if the string's
2326 rbearing is <= its nominal width, rbearing - width otherwise. */
2327 int right_overhang;
2329 /* The frame on which the glyph string is drawn. */
2330 struct frame *f;
2332 /* The window on which the glyph string is drawn. */
2333 struct window *w;
2335 /* X display and window for convenience. */
2336 Display *display;
2337 Window window;
2339 /* The glyph row for which this string was built. It determines the
2340 y-origin and height of the string. */
2341 struct glyph_row *row;
2343 /* The area within row. */
2344 enum glyph_row_area area;
2346 /* Characters to be drawn, and number of characters. */
2347 XChar2b *char2b;
2348 int nchars;
2350 /* A face-override for drawing cursors, mouse face and similar. */
2351 enum draw_glyphs_face hl;
2353 /* Face in which this string is to be drawn. */
2354 struct face *face;
2356 /* Font in which this string is to be drawn. */
2357 XFontStruct *font;
2359 /* Font info for this string. */
2360 struct font_info *font_info;
2362 /* Non-null means this string describes (part of) a composition.
2363 All characters from char2b are drawn composed. */
2364 struct composition *cmp;
2366 /* Index of this glyph string's first character in the glyph
2367 definition of CMP. If this is zero, this glyph string describes
2368 the first character of a composition. */
2369 int gidx;
2371 /* 1 means this glyph strings face has to be drawn to the right end
2372 of the window's drawing area. */
2373 unsigned extends_to_end_of_line_p : 1;
2375 /* 1 means the background of this string has been drawn. */
2376 unsigned background_filled_p : 1;
2378 /* 1 means glyph string must be drawn with 16-bit functions. */
2379 unsigned two_byte_p : 1;
2381 /* 1 means that the original font determined for drawing this glyph
2382 string could not be loaded. The member `font' has been set to
2383 the frame's default font in this case. */
2384 unsigned font_not_found_p : 1;
2386 /* 1 means that the face in which this glyph string is drawn has a
2387 stipple pattern. */
2388 unsigned stippled_p : 1;
2390 /* 1 means only the foreground of this glyph string must be drawn,
2391 and we should use the physical height of the line this glyph
2392 string appears in as clip rect. */
2393 unsigned for_overlaps_p : 1;
2395 /* The GC to use for drawing this glyph string. */
2396 GC gc;
2398 /* A pointer to the first glyph in the string. This glyph
2399 corresponds to char2b[0]. Needed to draw rectangles if
2400 font_not_found_p is 1. */
2401 struct glyph *first_glyph;
2403 /* Image, if any. */
2404 struct image *img;
2406 struct glyph_string *next, *prev;
2410 #if 0
2412 static void
2413 x_dump_glyph_string (s)
2414 struct glyph_string *s;
2416 fprintf (stderr, "glyph string\n");
2417 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2418 s->x, s->y, s->width, s->height);
2419 fprintf (stderr, " ybase = %d\n", s->ybase);
2420 fprintf (stderr, " hl = %d\n", s->hl);
2421 fprintf (stderr, " left overhang = %d, right = %d\n",
2422 s->left_overhang, s->right_overhang);
2423 fprintf (stderr, " nchars = %d\n", s->nchars);
2424 fprintf (stderr, " extends to end of line = %d\n",
2425 s->extends_to_end_of_line_p);
2426 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2427 fprintf (stderr, " bg width = %d\n", s->background_width);
2430 #endif /* GLYPH_DEBUG */
2434 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2435 struct glyph_string **,
2436 struct glyph_string *,
2437 struct glyph_string *));
2438 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2439 struct glyph_string **,
2440 struct glyph_string *,
2441 struct glyph_string *));
2442 static void x_append_glyph_string P_ ((struct glyph_string **,
2443 struct glyph_string **,
2444 struct glyph_string *));
2445 static int x_left_overwritten P_ ((struct glyph_string *));
2446 static int x_left_overwriting P_ ((struct glyph_string *));
2447 static int x_right_overwritten P_ ((struct glyph_string *));
2448 static int x_right_overwriting P_ ((struct glyph_string *));
2449 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2450 int));
2451 static void x_init_glyph_string P_ ((struct glyph_string *,
2452 XChar2b *, struct window *,
2453 struct glyph_row *,
2454 enum glyph_row_area, int,
2455 enum draw_glyphs_face));
2456 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2457 enum glyph_row_area, int, int,
2458 enum draw_glyphs_face, int *, int *, int));
2459 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2460 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2461 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2462 int));
2463 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2464 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2465 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2466 static void x_draw_glyph_string P_ ((struct glyph_string *));
2467 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2468 static void x_set_cursor_gc P_ ((struct glyph_string *));
2469 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2470 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2471 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2472 int *, int *));
2473 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2474 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2475 unsigned long *, double, int));
2476 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2477 double, int, unsigned long));
2478 static void x_setup_relief_colors P_ ((struct glyph_string *));
2479 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2480 static void x_draw_image_relief P_ ((struct glyph_string *));
2481 static void x_draw_image_foreground P_ ((struct glyph_string *));
2482 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2483 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2484 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2485 int, int, int));
2486 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2487 int, int, int, int, XRectangle *));
2488 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2489 int, int, int, XRectangle *));
2490 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2491 enum glyph_row_area));
2494 /* Append the list of glyph strings with head H and tail T to the list
2495 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2497 static INLINE void
2498 x_append_glyph_string_lists (head, tail, h, t)
2499 struct glyph_string **head, **tail;
2500 struct glyph_string *h, *t;
2502 if (h)
2504 if (*head)
2505 (*tail)->next = h;
2506 else
2507 *head = h;
2508 h->prev = *tail;
2509 *tail = t;
2514 /* Prepend the list of glyph strings with head H and tail T to the
2515 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2516 result. */
2518 static INLINE void
2519 x_prepend_glyph_string_lists (head, tail, h, t)
2520 struct glyph_string **head, **tail;
2521 struct glyph_string *h, *t;
2523 if (h)
2525 if (*head)
2526 (*head)->prev = t;
2527 else
2528 *tail = t;
2529 t->next = *head;
2530 *head = h;
2535 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2536 Set *HEAD and *TAIL to the resulting list. */
2538 static INLINE void
2539 x_append_glyph_string (head, tail, s)
2540 struct glyph_string **head, **tail;
2541 struct glyph_string *s;
2543 s->next = s->prev = NULL;
2544 x_append_glyph_string_lists (head, tail, s, s);
2548 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2549 face. */
2551 static void
2552 x_set_cursor_gc (s)
2553 struct glyph_string *s;
2555 if (s->font == FRAME_FONT (s->f)
2556 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2557 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2558 && !s->cmp)
2559 s->gc = s->f->output_data.x->cursor_gc;
2560 else
2562 /* Cursor on non-default face: must merge. */
2563 XGCValues xgcv;
2564 unsigned long mask;
2566 xgcv.background = s->f->output_data.x->cursor_pixel;
2567 xgcv.foreground = s->face->background;
2569 /* If the glyph would be invisible, try a different foreground. */
2570 if (xgcv.foreground == xgcv.background)
2571 xgcv.foreground = s->face->foreground;
2572 if (xgcv.foreground == xgcv.background)
2573 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2574 if (xgcv.foreground == xgcv.background)
2575 xgcv.foreground = s->face->foreground;
2577 /* Make sure the cursor is distinct from text in this face. */
2578 if (xgcv.background == s->face->background
2579 && xgcv.foreground == s->face->foreground)
2581 xgcv.background = s->face->foreground;
2582 xgcv.foreground = s->face->background;
2585 IF_DEBUG (x_check_font (s->f, s->font));
2586 xgcv.font = s->font->fid;
2587 xgcv.graphics_exposures = False;
2588 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2590 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2591 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2592 mask, &xgcv);
2593 else
2594 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2595 = XCreateGC (s->display, s->window, mask, &xgcv);
2597 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2602 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2604 static void
2605 x_set_mouse_face_gc (s)
2606 struct glyph_string *s;
2608 int face_id;
2609 struct face *face;
2611 /* What face has to be used for the mouse face? */
2612 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2613 face = FACE_FROM_ID (s->f, face_id);
2614 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2615 s->face = FACE_FROM_ID (s->f, face_id);
2616 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2618 /* If font in this face is same as S->font, use it. */
2619 if (s->font == s->face->font)
2620 s->gc = s->face->gc;
2621 else
2623 /* Otherwise construct scratch_cursor_gc with values from FACE
2624 but font FONT. */
2625 XGCValues xgcv;
2626 unsigned long mask;
2628 xgcv.background = s->face->background;
2629 xgcv.foreground = s->face->foreground;
2630 IF_DEBUG (x_check_font (s->f, s->font));
2631 xgcv.font = s->font->fid;
2632 xgcv.graphics_exposures = False;
2633 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2635 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2636 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2637 mask, &xgcv);
2638 else
2639 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2640 = XCreateGC (s->display, s->window, mask, &xgcv);
2642 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2645 xassert (s->gc != 0);
2649 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2650 Faces to use in the mode line have already been computed when the
2651 matrix was built, so there isn't much to do, here. */
2653 static INLINE void
2654 x_set_mode_line_face_gc (s)
2655 struct glyph_string *s;
2657 s->gc = s->face->gc;
2658 xassert (s->gc != 0);
2662 /* Set S->gc of glyph string S for drawing that glyph string. Set
2663 S->stippled_p to a non-zero value if the face of S has a stipple
2664 pattern. */
2666 static INLINE void
2667 x_set_glyph_string_gc (s)
2668 struct glyph_string *s;
2670 if (s->hl == DRAW_NORMAL_TEXT)
2672 s->gc = s->face->gc;
2673 s->stippled_p = s->face->stipple != 0;
2675 else if (s->hl == DRAW_INVERSE_VIDEO)
2677 x_set_mode_line_face_gc (s);
2678 s->stippled_p = s->face->stipple != 0;
2680 else if (s->hl == DRAW_CURSOR)
2682 x_set_cursor_gc (s);
2683 s->stippled_p = 0;
2685 else if (s->hl == DRAW_MOUSE_FACE)
2687 x_set_mouse_face_gc (s);
2688 s->stippled_p = s->face->stipple != 0;
2690 else if (s->hl == DRAW_IMAGE_RAISED
2691 || s->hl == DRAW_IMAGE_SUNKEN)
2693 s->gc = s->face->gc;
2694 s->stippled_p = s->face->stipple != 0;
2696 else
2698 s->gc = s->face->gc;
2699 s->stippled_p = s->face->stipple != 0;
2702 /* GC must have been set. */
2703 xassert (s->gc != 0);
2707 /* Return in *R the clipping rectangle for glyph string S. */
2709 static void
2710 x_get_glyph_string_clip_rect (s, r)
2711 struct glyph_string *s;
2712 XRectangle *r;
2714 if (s->row->full_width_p)
2716 /* Draw full-width. X coordinates are relative to S->w->left. */
2717 int canon_x = CANON_X_UNIT (s->f);
2719 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2720 r->width = XFASTINT (s->w->width) * canon_x;
2722 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2724 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2725 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2726 r->x -= width;
2729 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2731 /* Unless displaying a mode or menu bar line, which are always
2732 fully visible, clip to the visible part of the row. */
2733 if (s->w->pseudo_window_p)
2734 r->height = s->row->visible_height;
2735 else
2736 r->height = s->height;
2738 else
2740 /* This is a text line that may be partially visible. */
2741 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2742 r->width = window_box_width (s->w, s->area);
2743 r->height = s->row->visible_height;
2746 /* Don't use S->y for clipping because it doesn't take partially
2747 visible lines into account. For example, it can be negative for
2748 partially visible lines at the top of a window. */
2749 if (!s->row->full_width_p
2750 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2751 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2752 else
2753 r->y = max (0, s->row->y);
2755 /* If drawing a tool-bar window, draw it over the internal border
2756 at the top of the window. */
2757 if (s->w == XWINDOW (s->f->tool_bar_window))
2758 r->y -= s->f->output_data.x->internal_border_width;
2760 /* If S draws overlapping rows, it's sufficient to use the top and
2761 bottom of the window for clipping because this glyph string
2762 intentionally draws over other lines. */
2763 if (s->for_overlaps_p)
2765 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2766 r->height = window_text_bottom_y (s->w) - r->y;
2769 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2773 /* Set clipping for output of glyph string S. S may be part of a mode
2774 line or menu if we don't have X toolkit support. */
2776 static INLINE void
2777 x_set_glyph_string_clipping (s)
2778 struct glyph_string *s;
2780 XRectangle r;
2781 x_get_glyph_string_clip_rect (s, &r);
2782 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2786 /* Compute left and right overhang of glyph string S. If S is a glyph
2787 string for a composition, assume overhangs don't exist. */
2789 static INLINE void
2790 x_compute_glyph_string_overhangs (s)
2791 struct glyph_string *s;
2793 if (s->cmp == NULL
2794 && s->first_glyph->type == CHAR_GLYPH)
2796 XCharStruct cs;
2797 int direction, font_ascent, font_descent;
2798 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2799 &font_ascent, &font_descent, &cs);
2800 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2801 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2806 /* Compute overhangs and x-positions for glyph string S and its
2807 predecessors, or successors. X is the starting x-position for S.
2808 BACKWARD_P non-zero means process predecessors. */
2810 static void
2811 x_compute_overhangs_and_x (s, x, backward_p)
2812 struct glyph_string *s;
2813 int x;
2814 int backward_p;
2816 if (backward_p)
2818 while (s)
2820 x_compute_glyph_string_overhangs (s);
2821 x -= s->width;
2822 s->x = x;
2823 s = s->prev;
2826 else
2828 while (s)
2830 x_compute_glyph_string_overhangs (s);
2831 s->x = x;
2832 x += s->width;
2833 s = s->next;
2839 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2840 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2841 assumed to be zero. */
2843 static void
2844 x_get_glyph_overhangs (glyph, f, left, right)
2845 struct glyph *glyph;
2846 struct frame *f;
2847 int *left, *right;
2849 int c;
2851 *left = *right = 0;
2853 if (glyph->type == CHAR_GLYPH)
2855 XFontStruct *font;
2856 struct face *face;
2857 struct font_info *font_info;
2858 XChar2b char2b;
2859 XCharStruct *pcm;
2861 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2862 font = face->font;
2863 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2864 if (font
2865 && (pcm = x_per_char_metric (font, &char2b)))
2867 if (pcm->rbearing > pcm->width)
2868 *right = pcm->rbearing - pcm->width;
2869 if (pcm->lbearing < 0)
2870 *left = -pcm->lbearing;
2876 /* Return the index of the first glyph preceding glyph string S that
2877 is overwritten by S because of S's left overhang. Value is -1
2878 if no glyphs are overwritten. */
2880 static int
2881 x_left_overwritten (s)
2882 struct glyph_string *s;
2884 int k;
2886 if (s->left_overhang)
2888 int x = 0, i;
2889 struct glyph *glyphs = s->row->glyphs[s->area];
2890 int first = s->first_glyph - glyphs;
2892 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2893 x -= glyphs[i].pixel_width;
2895 k = i + 1;
2897 else
2898 k = -1;
2900 return k;
2904 /* Return the index of the first glyph preceding glyph string S that
2905 is overwriting S because of its right overhang. Value is -1 if no
2906 glyph in front of S overwrites S. */
2908 static int
2909 x_left_overwriting (s)
2910 struct glyph_string *s;
2912 int i, k, x;
2913 struct glyph *glyphs = s->row->glyphs[s->area];
2914 int first = s->first_glyph - glyphs;
2916 k = -1;
2917 x = 0;
2918 for (i = first - 1; i >= 0; --i)
2920 int left, right;
2921 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2922 if (x + right > 0)
2923 k = i;
2924 x -= glyphs[i].pixel_width;
2927 return k;
2931 /* Return the index of the last glyph following glyph string S that is
2932 not overwritten by S because of S's right overhang. Value is -1 if
2933 no such glyph is found. */
2935 static int
2936 x_right_overwritten (s)
2937 struct glyph_string *s;
2939 int k = -1;
2941 if (s->right_overhang)
2943 int x = 0, i;
2944 struct glyph *glyphs = s->row->glyphs[s->area];
2945 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2946 int end = s->row->used[s->area];
2948 for (i = first; i < end && s->right_overhang > x; ++i)
2949 x += glyphs[i].pixel_width;
2951 k = i;
2954 return k;
2958 /* Return the index of the last glyph following glyph string S that
2959 overwrites S because of its left overhang. Value is negative
2960 if no such glyph is found. */
2962 static int
2963 x_right_overwriting (s)
2964 struct glyph_string *s;
2966 int i, k, x;
2967 int end = s->row->used[s->area];
2968 struct glyph *glyphs = s->row->glyphs[s->area];
2969 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2971 k = -1;
2972 x = 0;
2973 for (i = first; i < end; ++i)
2975 int left, right;
2976 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2977 if (x - left < 0)
2978 k = i;
2979 x += glyphs[i].pixel_width;
2982 return k;
2986 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2988 static INLINE void
2989 x_clear_glyph_string_rect (s, x, y, w, h)
2990 struct glyph_string *s;
2991 int x, y, w, h;
2993 XGCValues xgcv;
2994 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
2995 XSetForeground (s->display, s->gc, xgcv.background);
2996 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2997 XSetForeground (s->display, s->gc, xgcv.foreground);
3001 /* Draw the background of glyph_string S. If S->background_filled_p
3002 is non-zero don't draw it. FORCE_P non-zero means draw the
3003 background even if it wouldn't be drawn normally. This is used
3004 when a string preceding S draws into the background of S, or S
3005 contains the first component of a composition. */
3007 static void
3008 x_draw_glyph_string_background (s, force_p)
3009 struct glyph_string *s;
3010 int force_p;
3012 /* Nothing to do if background has already been drawn or if it
3013 shouldn't be drawn in the first place. */
3014 if (!s->background_filled_p)
3016 if (s->stippled_p)
3018 /* Fill background with a stipple pattern. */
3019 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3020 XFillRectangle (s->display, s->window, s->gc, s->x,
3021 s->y + s->face->box_line_width,
3022 s->background_width,
3023 s->height - 2 * s->face->box_line_width);
3024 XSetFillStyle (s->display, s->gc, FillSolid);
3025 s->background_filled_p = 1;
3027 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3028 || s->font_not_found_p
3029 || s->extends_to_end_of_line_p
3030 || force_p)
3032 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3033 s->background_width,
3034 s->height - 2 * s->face->box_line_width);
3035 s->background_filled_p = 1;
3041 /* Draw the foreground of glyph string S. */
3043 static void
3044 x_draw_glyph_string_foreground (s)
3045 struct glyph_string *s;
3047 int i, x;
3049 /* If first glyph of S has a left box line, start drawing the text
3050 of S to the right of that box line. */
3051 if (s->face->box != FACE_NO_BOX
3052 && s->first_glyph->left_box_line_p)
3053 x = s->x + s->face->box_line_width;
3054 else
3055 x = s->x;
3057 /* Draw characters of S as rectangles if S's font could not be
3058 loaded. */
3059 if (s->font_not_found_p)
3061 for (i = 0; i < s->nchars; ++i)
3063 struct glyph *g = s->first_glyph + i;
3064 XDrawRectangle (s->display, s->window,
3065 s->gc, x, s->y, g->pixel_width - 1,
3066 s->height - 1);
3067 x += g->pixel_width;
3070 else
3072 char *char1b = (char *) s->char2b;
3073 int boff = s->font_info->baseline_offset;
3075 if (s->font_info->vertical_centering)
3076 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3078 /* If we can use 8-bit functions, condense S->char2b. */
3079 if (!s->two_byte_p)
3080 for (i = 0; i < s->nchars; ++i)
3081 char1b[i] = s->char2b[i].byte2;
3083 /* Draw text with XDrawString if background has already been
3084 filled. Otherwise, use XDrawImageString. (Note that
3085 XDrawImageString is usually faster than XDrawString.) Always
3086 use XDrawImageString when drawing the cursor so that there is
3087 no chance that characters under a box cursor are invisible. */
3088 if (s->for_overlaps_p
3089 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3091 /* Draw characters with 16-bit or 8-bit functions. */
3092 if (s->two_byte_p)
3093 XDrawString16 (s->display, s->window, s->gc, x,
3094 s->ybase - boff, s->char2b, s->nchars);
3095 else
3096 XDrawString (s->display, s->window, s->gc, x,
3097 s->ybase - boff, char1b, s->nchars);
3099 else
3101 if (s->two_byte_p)
3102 XDrawImageString16 (s->display, s->window, s->gc, x,
3103 s->ybase - boff, s->char2b, s->nchars);
3104 else
3105 XDrawImageString (s->display, s->window, s->gc, x,
3106 s->ybase - boff, char1b, s->nchars);
3111 /* Draw the foreground of composite glyph string S. */
3113 static void
3114 x_draw_composite_glyph_string_foreground (s)
3115 struct glyph_string *s;
3117 int i, x;
3119 /* If first glyph of S has a left box line, start drawing the text
3120 of S to the right of that box line. */
3121 if (s->face->box != FACE_NO_BOX
3122 && s->first_glyph->left_box_line_p)
3123 x = s->x + s->face->box_line_width;
3124 else
3125 x = s->x;
3127 /* S is a glyph string for a composition. S->gidx is the index of
3128 the first character drawn for glyphs of this composition.
3129 S->gidx == 0 means we are drawing the very first character of
3130 this composition. */
3132 /* Draw a rectangle for the composition if the font for the very
3133 first character of the composition could not be loaded. */
3134 if (s->font_not_found_p)
3136 if (s->gidx == 0)
3137 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3138 s->width - 1, s->height - 1);
3140 else
3142 for (i = 0; i < s->nchars; i++, ++s->gidx)
3143 XDrawString16 (s->display, s->window, s->gc,
3144 x + s->cmp->offsets[s->gidx * 2],
3145 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3146 s->char2b + i, 1);
3151 #ifdef USE_X_TOOLKIT
3153 /* Allocate the color COLOR->pixel on the screen and display of
3154 widget WIDGET in colormap CMAP. If an exact match cannot be
3155 allocated, try the nearest color available. Value is non-zero
3156 if successful. This is called from lwlib. */
3159 x_alloc_nearest_color_for_widget (widget, cmap, color)
3160 Widget widget;
3161 Colormap cmap;
3162 XColor *color;
3164 struct frame *f;
3165 struct x_display_info *dpyinfo;
3166 Lisp_Object tail;
3168 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3170 /* Find the top-level shell of the widget. Note that this function
3171 can be called when the widget is not yet realized, so XtWindow
3172 (widget) == 0. That's the reason we can't simply use
3173 x_any_window_to_frame. */
3174 while (!XtIsTopLevelShell (widget))
3175 widget = XtParent (widget);
3177 /* Look for a frame with that top-level widget. Allocate the color
3178 on that frame to get the right gamma correction value. */
3179 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3180 if (GC_FRAMEP (XCAR (tail))
3181 && (f = XFRAME (XCAR (tail)),
3182 (f->output_data.nothing != 1
3183 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3184 && f->output_data.x->widget == widget)
3185 return x_alloc_nearest_color (f, cmap, color);
3187 abort ();
3190 #endif /* USE_X_TOOLKIT */
3193 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3194 CMAP. If an exact match can't be allocated, try the nearest color
3195 available. Value is non-zero if successful. Set *COLOR to the
3196 color allocated. */
3199 x_alloc_nearest_color (f, cmap, color)
3200 struct frame *f;
3201 Colormap cmap;
3202 XColor *color;
3204 Display *display = FRAME_X_DISPLAY (f);
3205 Screen *screen = FRAME_X_SCREEN (f);
3206 int rc;
3208 gamma_correct (f, color);
3209 rc = XAllocColor (display, cmap, color);
3210 if (rc == 0)
3212 /* If we got to this point, the colormap is full, so we're going
3213 to try to get the next closest color. The algorithm used is
3214 a least-squares matching, which is what X uses for closest
3215 color matching with StaticColor visuals. */
3216 int nearest, i;
3217 unsigned long nearest_delta = ~0;
3218 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3219 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3221 for (i = 0; i < ncells; ++i)
3222 cells[i].pixel = i;
3223 XQueryColors (display, cmap, cells, ncells);
3225 for (nearest = i = 0; i < ncells; ++i)
3227 long dred = (color->red >> 8) - (cells[i].red >> 8);
3228 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3229 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3230 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3232 if (delta < nearest_delta)
3234 nearest = i;
3235 nearest_delta = delta;
3239 color->red = cells[nearest].red;
3240 color->green = cells[nearest].green;
3241 color->blue = cells[nearest].blue;
3242 rc = XAllocColor (display, cmap, color);
3245 #ifdef DEBUG_X_COLORS
3246 if (rc)
3247 register_color (color->pixel);
3248 #endif /* DEBUG_X_COLORS */
3250 return rc;
3254 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3255 It's necessary to do this instead of just using PIXEL directly to
3256 get color reference counts right. */
3258 unsigned long
3259 x_copy_color (f, pixel)
3260 struct frame *f;
3261 unsigned long pixel;
3263 XColor color;
3265 color.pixel = pixel;
3266 BLOCK_INPUT;
3267 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3268 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3269 UNBLOCK_INPUT;
3270 #ifdef DEBUG_X_COLORS
3271 register_color (pixel);
3272 #endif
3273 return color.pixel;
3277 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3278 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3279 If this produces the same color as PIXEL, try a color where all RGB
3280 values have DELTA added. Return the allocated color in *PIXEL.
3281 DISPLAY is the X display, CMAP is the colormap to operate on.
3282 Value is non-zero if successful. */
3284 static int
3285 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3286 struct frame *f;
3287 Display *display;
3288 Colormap cmap;
3289 unsigned long *pixel;
3290 double factor;
3291 int delta;
3293 XColor color, new;
3294 int success_p;
3296 /* Get RGB color values. */
3297 color.pixel = *pixel;
3298 XQueryColor (display, cmap, &color);
3300 /* Change RGB values by specified FACTOR. Avoid overflow! */
3301 xassert (factor >= 0);
3302 new.red = min (0xffff, factor * color.red);
3303 new.green = min (0xffff, factor * color.green);
3304 new.blue = min (0xffff, factor * color.blue);
3306 /* Try to allocate the color. */
3307 success_p = x_alloc_nearest_color (f, cmap, &new);
3308 if (success_p)
3310 if (new.pixel == *pixel)
3312 /* If we end up with the same color as before, try adding
3313 delta to the RGB values. */
3314 x_free_colors (f, &new.pixel, 1);
3316 new.red = min (0xffff, delta + color.red);
3317 new.green = min (0xffff, delta + color.green);
3318 new.blue = min (0xffff, delta + color.blue);
3319 success_p = x_alloc_nearest_color (f, cmap, &new);
3321 else
3322 success_p = 1;
3323 *pixel = new.pixel;
3326 return success_p;
3330 /* Set up the foreground color for drawing relief lines of glyph
3331 string S. RELIEF is a pointer to a struct relief containing the GC
3332 with which lines will be drawn. Use a color that is FACTOR or
3333 DELTA lighter or darker than the relief's background which is found
3334 in S->f->output_data.x->relief_background. If such a color cannot
3335 be allocated, use DEFAULT_PIXEL, instead. */
3337 static void
3338 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3339 struct frame *f;
3340 struct relief *relief;
3341 double factor;
3342 int delta;
3343 unsigned long default_pixel;
3345 XGCValues xgcv;
3346 struct x_output *di = f->output_data.x;
3347 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3348 unsigned long pixel;
3349 unsigned long background = di->relief_background;
3350 Colormap cmap = FRAME_X_COLORMAP (f);
3351 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3352 Display *dpy = FRAME_X_DISPLAY (f);
3354 xgcv.graphics_exposures = False;
3355 xgcv.line_width = 1;
3357 /* Free previously allocated color. The color cell will be reused
3358 when it has been freed as many times as it was allocated, so this
3359 doesn't affect faces using the same colors. */
3360 if (relief->gc
3361 && relief->allocated_p)
3363 /* If display has an immutable color map, freeing colors is not
3364 necessary and some servers don't allow it. So don't do it. */
3365 x_free_colors (f, &relief->pixel, 1);
3366 relief->allocated_p = 0;
3369 /* Allocate new color. */
3370 xgcv.foreground = default_pixel;
3371 pixel = background;
3372 if (dpyinfo->n_planes != 1
3373 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3375 relief->allocated_p = 1;
3376 xgcv.foreground = relief->pixel = pixel;
3379 if (relief->gc == 0)
3381 xgcv.stipple = dpyinfo->gray;
3382 mask |= GCStipple;
3383 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3385 else
3386 XChangeGC (dpy, relief->gc, mask, &xgcv);
3390 /* Set up colors for the relief lines around glyph string S. */
3392 static void
3393 x_setup_relief_colors (s)
3394 struct glyph_string *s;
3396 struct x_output *di = s->f->output_data.x;
3397 unsigned long color;
3399 if (s->face->use_box_color_for_shadows_p)
3400 color = s->face->box_color;
3401 else
3403 XGCValues xgcv;
3405 /* Get the background color of the face. */
3406 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3407 color = xgcv.background;
3410 if (di->white_relief.gc == 0
3411 || color != di->relief_background)
3413 di->relief_background = color;
3414 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3415 WHITE_PIX_DEFAULT (s->f));
3416 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3417 BLACK_PIX_DEFAULT (s->f));
3422 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3423 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3424 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3425 relief. LEFT_P non-zero means draw a relief on the left side of
3426 the rectangle. RIGHT_P non-zero means draw a relief on the right
3427 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3428 when drawing. */
3430 static void
3431 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3432 raised_p, left_p, right_p, clip_rect)
3433 struct frame *f;
3434 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3435 XRectangle *clip_rect;
3437 int i;
3438 GC gc;
3440 if (raised_p)
3441 gc = f->output_data.x->white_relief.gc;
3442 else
3443 gc = f->output_data.x->black_relief.gc;
3444 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3446 /* Top. */
3447 for (i = 0; i < width; ++i)
3448 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3449 left_x + i * left_p, top_y + i,
3450 right_x + 1 - i * right_p, top_y + i);
3452 /* Left. */
3453 if (left_p)
3454 for (i = 0; i < width; ++i)
3455 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3456 left_x + i, top_y + i, left_x + i, bottom_y - i);
3458 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3459 if (raised_p)
3460 gc = f->output_data.x->black_relief.gc;
3461 else
3462 gc = f->output_data.x->white_relief.gc;
3463 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3465 /* Bottom. */
3466 for (i = 0; i < width; ++i)
3467 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3468 left_x + i * left_p, bottom_y - i,
3469 right_x + 1 - i * right_p, bottom_y - i);
3471 /* Right. */
3472 if (right_p)
3473 for (i = 0; i < width; ++i)
3474 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3475 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3477 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3481 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3482 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3483 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3484 left side of the rectangle. RIGHT_P non-zero means draw a line
3485 on the right side of the rectangle. CLIP_RECT is the clipping
3486 rectangle to use when drawing. */
3488 static void
3489 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3490 left_p, right_p, clip_rect)
3491 struct glyph_string *s;
3492 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3493 XRectangle *clip_rect;
3495 XGCValues xgcv;
3497 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3498 XSetForeground (s->display, s->gc, s->face->box_color);
3499 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3501 /* Top. */
3502 XFillRectangle (s->display, s->window, s->gc,
3503 left_x, top_y, right_x - left_x, width);
3505 /* Left. */
3506 if (left_p)
3507 XFillRectangle (s->display, s->window, s->gc,
3508 left_x, top_y, width, bottom_y - top_y);
3510 /* Bottom. */
3511 XFillRectangle (s->display, s->window, s->gc,
3512 left_x, bottom_y - width, right_x - left_x, width);
3514 /* Right. */
3515 if (right_p)
3516 XFillRectangle (s->display, s->window, s->gc,
3517 right_x - width, top_y, width, bottom_y - top_y);
3519 XSetForeground (s->display, s->gc, xgcv.foreground);
3520 XSetClipMask (s->display, s->gc, None);
3524 /* Draw a box around glyph string S. */
3526 static void
3527 x_draw_glyph_string_box (s)
3528 struct glyph_string *s;
3530 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3531 int left_p, right_p;
3532 struct glyph *last_glyph;
3533 XRectangle clip_rect;
3535 last_x = window_box_right (s->w, s->area);
3536 if (s->row->full_width_p
3537 && !s->w->pseudo_window_p)
3539 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3540 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3541 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3544 /* The glyph that may have a right box line. */
3545 last_glyph = (s->cmp || s->img
3546 ? s->first_glyph
3547 : s->first_glyph + s->nchars - 1);
3549 width = s->face->box_line_width;
3550 raised_p = s->face->box == FACE_RAISED_BOX;
3551 left_x = s->x;
3552 right_x = ((s->row->full_width_p
3553 ? last_x - 1
3554 : min (last_x, s->x + s->background_width) - 1));
3555 top_y = s->y;
3556 bottom_y = top_y + s->height - 1;
3558 left_p = (s->first_glyph->left_box_line_p
3559 || (s->hl == DRAW_MOUSE_FACE
3560 && (s->prev == NULL
3561 || s->prev->hl != s->hl)));
3562 right_p = (last_glyph->right_box_line_p
3563 || (s->hl == DRAW_MOUSE_FACE
3564 && (s->next == NULL
3565 || s->next->hl != s->hl)));
3567 x_get_glyph_string_clip_rect (s, &clip_rect);
3569 if (s->face->box == FACE_SIMPLE_BOX)
3570 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3571 left_p, right_p, &clip_rect);
3572 else
3574 x_setup_relief_colors (s);
3575 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3576 width, raised_p, left_p, right_p, &clip_rect);
3581 /* Draw foreground of image glyph string S. */
3583 static void
3584 x_draw_image_foreground (s)
3585 struct glyph_string *s;
3587 int x;
3588 int y = s->ybase - image_ascent (s->img, s->face);
3590 /* If first glyph of S has a left box line, start drawing it to the
3591 right of that line. */
3592 if (s->face->box != FACE_NO_BOX
3593 && s->first_glyph->left_box_line_p)
3594 x = s->x + s->face->box_line_width;
3595 else
3596 x = s->x;
3598 /* If there is a margin around the image, adjust x- and y-position
3599 by that margin. */
3600 if (s->img->margin)
3602 x += s->img->margin;
3603 y += s->img->margin;
3606 if (s->img->pixmap)
3608 if (s->img->mask)
3610 /* We can't set both a clip mask and use XSetClipRectangles
3611 because the latter also sets a clip mask. We also can't
3612 trust on the shape extension to be available
3613 (XShapeCombineRegion). So, compute the rectangle to draw
3614 manually. */
3615 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3616 | GCFunction);
3617 XGCValues xgcv;
3618 XRectangle clip_rect, image_rect, r;
3620 xgcv.clip_mask = s->img->mask;
3621 xgcv.clip_x_origin = x;
3622 xgcv.clip_y_origin = y;
3623 xgcv.function = GXcopy;
3624 XChangeGC (s->display, s->gc, mask, &xgcv);
3626 x_get_glyph_string_clip_rect (s, &clip_rect);
3627 image_rect.x = x;
3628 image_rect.y = y;
3629 image_rect.width = s->img->width;
3630 image_rect.height = s->img->height;
3631 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3632 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3633 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3635 else
3637 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3638 0, 0, s->img->width, s->img->height, x, y);
3640 /* When the image has a mask, we can expect that at
3641 least part of a mouse highlight or a block cursor will
3642 be visible. If the image doesn't have a mask, make
3643 a block cursor visible by drawing a rectangle around
3644 the image. I believe it's looking better if we do
3645 nothing here for mouse-face. */
3646 if (s->hl == DRAW_CURSOR)
3647 XDrawRectangle (s->display, s->window, s->gc, x, y,
3648 s->img->width - 1, s->img->height - 1);
3651 else
3652 /* Draw a rectangle if image could not be loaded. */
3653 XDrawRectangle (s->display, s->window, s->gc, x, y,
3654 s->img->width - 1, s->img->height - 1);
3658 /* Draw a relief around the image glyph string S. */
3660 static void
3661 x_draw_image_relief (s)
3662 struct glyph_string *s;
3664 int x0, y0, x1, y1, thick, raised_p;
3665 XRectangle r;
3666 int x;
3667 int y = s->ybase - image_ascent (s->img, s->face);
3669 /* If first glyph of S has a left box line, start drawing it to the
3670 right of that line. */
3671 if (s->face->box != FACE_NO_BOX
3672 && s->first_glyph->left_box_line_p)
3673 x = s->x + s->face->box_line_width;
3674 else
3675 x = s->x;
3677 /* If there is a margin around the image, adjust x- and y-position
3678 by that margin. */
3679 if (s->img->margin)
3681 x += s->img->margin;
3682 y += s->img->margin;
3685 if (s->hl == DRAW_IMAGE_SUNKEN
3686 || s->hl == DRAW_IMAGE_RAISED)
3688 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3689 raised_p = s->hl == DRAW_IMAGE_RAISED;
3691 else
3693 thick = abs (s->img->relief);
3694 raised_p = s->img->relief > 0;
3697 x0 = x - thick;
3698 y0 = y - thick;
3699 x1 = x + s->img->width + thick - 1;
3700 y1 = y + s->img->height + thick - 1;
3702 x_setup_relief_colors (s);
3703 x_get_glyph_string_clip_rect (s, &r);
3704 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3708 /* Draw the foreground of image glyph string S to PIXMAP. */
3710 static void
3711 x_draw_image_foreground_1 (s, pixmap)
3712 struct glyph_string *s;
3713 Pixmap pixmap;
3715 int x;
3716 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3718 /* If first glyph of S has a left box line, start drawing it to the
3719 right of that line. */
3720 if (s->face->box != FACE_NO_BOX
3721 && s->first_glyph->left_box_line_p)
3722 x = s->face->box_line_width;
3723 else
3724 x = 0;
3726 /* If there is a margin around the image, adjust x- and y-position
3727 by that margin. */
3728 if (s->img->margin)
3730 x += s->img->margin;
3731 y += s->img->margin;
3734 if (s->img->pixmap)
3736 if (s->img->mask)
3738 /* We can't set both a clip mask and use XSetClipRectangles
3739 because the latter also sets a clip mask. We also can't
3740 trust on the shape extension to be available
3741 (XShapeCombineRegion). So, compute the rectangle to draw
3742 manually. */
3743 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3744 | GCFunction);
3745 XGCValues xgcv;
3747 xgcv.clip_mask = s->img->mask;
3748 xgcv.clip_x_origin = x;
3749 xgcv.clip_y_origin = y;
3750 xgcv.function = GXcopy;
3751 XChangeGC (s->display, s->gc, mask, &xgcv);
3753 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3754 0, 0, s->img->width, s->img->height, x, y);
3755 XSetClipMask (s->display, s->gc, None);
3757 else
3759 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3760 0, 0, s->img->width, s->img->height, x, y);
3762 /* When the image has a mask, we can expect that at
3763 least part of a mouse highlight or a block cursor will
3764 be visible. If the image doesn't have a mask, make
3765 a block cursor visible by drawing a rectangle around
3766 the image. I believe it's looking better if we do
3767 nothing here for mouse-face. */
3768 if (s->hl == DRAW_CURSOR)
3769 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3770 s->img->width - 1, s->img->height - 1);
3773 else
3774 /* Draw a rectangle if image could not be loaded. */
3775 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3776 s->img->width - 1, s->img->height - 1);
3780 /* Draw part of the background of glyph string S. X, Y, W, and H
3781 give the rectangle to draw. */
3783 static void
3784 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3785 struct glyph_string *s;
3786 int x, y, w, h;
3788 if (s->stippled_p)
3790 /* Fill background with a stipple pattern. */
3791 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3792 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3793 XSetFillStyle (s->display, s->gc, FillSolid);
3795 else
3796 x_clear_glyph_string_rect (s, x, y, w, h);
3800 /* Draw image glyph string S.
3802 s->y
3803 s->x +-------------------------
3804 | s->face->box
3806 | +-------------------------
3807 | | s->img->margin
3809 | | +-------------------
3810 | | | the image
3814 static void
3815 x_draw_image_glyph_string (s)
3816 struct glyph_string *s;
3818 int x, y;
3819 int box_line_width = s->face->box_line_width;
3820 int margin = s->img->margin;
3821 int height;
3822 Pixmap pixmap = None;
3824 height = s->height - 2 * box_line_width;
3826 /* Fill background with face under the image. Do it only if row is
3827 taller than image or if image has a clip mask to reduce
3828 flickering. */
3829 s->stippled_p = s->face->stipple != 0;
3830 if (height > s->img->height
3831 || margin
3832 || s->img->mask
3833 || s->img->pixmap == 0
3834 || s->width != s->background_width)
3836 if (box_line_width && s->first_glyph->left_box_line_p)
3837 x = s->x + box_line_width;
3838 else
3839 x = s->x;
3841 y = s->y + box_line_width;
3843 if (s->img->mask)
3845 /* Create a pixmap as large as the glyph string Fill it with
3846 the background color. Copy the image to it, using its
3847 mask. Copy the temporary pixmap to the display. */
3848 Screen *screen = FRAME_X_SCREEN (s->f);
3849 int depth = DefaultDepthOfScreen (screen);
3851 /* Create a pixmap as large as the glyph string. */
3852 pixmap = XCreatePixmap (s->display, s->window,
3853 s->background_width,
3854 s->height, depth);
3856 /* Don't clip in the following because we're working on the
3857 pixmap. */
3858 XSetClipMask (s->display, s->gc, None);
3860 /* Fill the pixmap with the background color/stipple. */
3861 if (s->stippled_p)
3863 /* Fill background with a stipple pattern. */
3864 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3865 XFillRectangle (s->display, pixmap, s->gc,
3866 0, 0, s->background_width, s->height);
3867 XSetFillStyle (s->display, s->gc, FillSolid);
3869 else
3871 XGCValues xgcv;
3872 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3873 &xgcv);
3874 XSetForeground (s->display, s->gc, xgcv.background);
3875 XFillRectangle (s->display, pixmap, s->gc,
3876 0, 0, s->background_width, s->height);
3877 XSetForeground (s->display, s->gc, xgcv.foreground);
3880 else
3881 /* Implementation idea: Is it possible to construct a mask?
3882 We could look at the color at the margins of the image, and
3883 say that this color is probably the background color of the
3884 image. */
3885 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3887 s->background_filled_p = 1;
3890 /* Draw the foreground. */
3891 if (pixmap != None)
3893 x_draw_image_foreground_1 (s, pixmap);
3894 x_set_glyph_string_clipping (s);
3895 XCopyArea (s->display, pixmap, s->window, s->gc,
3896 0, 0, s->background_width, s->height, s->x, s->y);
3897 XFreePixmap (s->display, pixmap);
3899 else
3900 x_draw_image_foreground (s);
3902 /* If we must draw a relief around the image, do it. */
3903 if (s->img->relief
3904 || s->hl == DRAW_IMAGE_RAISED
3905 || s->hl == DRAW_IMAGE_SUNKEN)
3906 x_draw_image_relief (s);
3910 /* Draw stretch glyph string S. */
3912 static void
3913 x_draw_stretch_glyph_string (s)
3914 struct glyph_string *s;
3916 xassert (s->first_glyph->type == STRETCH_GLYPH);
3917 s->stippled_p = s->face->stipple != 0;
3919 if (s->hl == DRAW_CURSOR
3920 && !x_stretch_cursor_p)
3922 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3923 as wide as the stretch glyph. */
3924 int width = min (CANON_X_UNIT (s->f), s->background_width);
3926 /* Draw cursor. */
3927 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3929 /* Clear rest using the GC of the original non-cursor face. */
3930 if (width < s->background_width)
3932 GC gc = s->face->gc;
3933 int x = s->x + width, y = s->y;
3934 int w = s->background_width - width, h = s->height;
3935 XRectangle r;
3937 x_get_glyph_string_clip_rect (s, &r);
3938 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
3940 if (s->face->stipple)
3942 /* Fill background with a stipple pattern. */
3943 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3944 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3945 XSetFillStyle (s->display, gc, FillSolid);
3947 else
3949 XGCValues xgcv;
3950 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3951 XSetForeground (s->display, gc, xgcv.background);
3952 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3953 XSetForeground (s->display, gc, xgcv.foreground);
3957 else
3958 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3959 s->height);
3961 s->background_filled_p = 1;
3965 /* Draw glyph string S. */
3967 static void
3968 x_draw_glyph_string (s)
3969 struct glyph_string *s;
3971 /* If S draws into the background of its successor, draw the
3972 background of the successor first so that S can draw into it.
3973 This makes S->next use XDrawString instead of XDrawImageString. */
3974 if (s->next && s->right_overhang && !s->for_overlaps_p)
3976 xassert (s->next->img == NULL);
3977 x_set_glyph_string_gc (s->next);
3978 x_set_glyph_string_clipping (s->next);
3979 x_draw_glyph_string_background (s->next, 1);
3982 /* Set up S->gc, set clipping and draw S. */
3983 x_set_glyph_string_gc (s);
3984 x_set_glyph_string_clipping (s);
3986 switch (s->first_glyph->type)
3988 case IMAGE_GLYPH:
3989 x_draw_image_glyph_string (s);
3990 break;
3992 case STRETCH_GLYPH:
3993 x_draw_stretch_glyph_string (s);
3994 break;
3996 case CHAR_GLYPH:
3997 if (s->for_overlaps_p)
3998 s->background_filled_p = 1;
3999 else
4000 x_draw_glyph_string_background (s, 0);
4001 x_draw_glyph_string_foreground (s);
4002 break;
4004 case COMPOSITE_GLYPH:
4005 if (s->for_overlaps_p || s->gidx > 0)
4006 s->background_filled_p = 1;
4007 else
4008 x_draw_glyph_string_background (s, 1);
4009 x_draw_composite_glyph_string_foreground (s);
4010 break;
4012 default:
4013 abort ();
4016 if (!s->for_overlaps_p)
4018 /* Draw underline. */
4019 if (s->face->underline_p)
4021 unsigned long dy, h;
4023 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4024 h = 1;
4025 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4026 dy = s->height - h;
4028 if (s->face->underline_defaulted_p)
4029 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4030 s->width, h);
4031 else
4033 XGCValues xgcv;
4034 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4035 XSetForeground (s->display, s->gc, s->face->underline_color);
4036 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4037 s->width, h);
4038 XSetForeground (s->display, s->gc, xgcv.foreground);
4042 /* Draw overline. */
4043 if (s->face->overline_p)
4045 unsigned long dy = 0, h = 1;
4047 if (s->face->overline_color_defaulted_p)
4048 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4049 s->width, h);
4050 else
4052 XGCValues xgcv;
4053 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4054 XSetForeground (s->display, s->gc, s->face->overline_color);
4055 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4056 s->width, h);
4057 XSetForeground (s->display, s->gc, xgcv.foreground);
4061 /* Draw strike-through. */
4062 if (s->face->strike_through_p)
4064 unsigned long h = 1;
4065 unsigned long dy = (s->height - h) / 2;
4067 if (s->face->strike_through_color_defaulted_p)
4068 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4069 s->width, h);
4070 else
4072 XGCValues xgcv;
4073 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4074 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4075 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4076 s->width, h);
4077 XSetForeground (s->display, s->gc, xgcv.foreground);
4081 /* Draw relief. */
4082 if (s->face->box != FACE_NO_BOX)
4083 x_draw_glyph_string_box (s);
4086 /* Reset clipping. */
4087 XSetClipMask (s->display, s->gc, None);
4091 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4092 struct face **, int));
4095 /* Load glyph string S with a composition components specified by S->cmp.
4096 FACES is an array of faces for all components of this composition.
4097 S->gidx is the index of the first component for S.
4098 OVERLAPS_P non-zero means S should draw the foreground only, and
4099 use its lines physical height for clipping.
4101 Value is the index of a component not in S. */
4103 static int
4104 x_fill_composite_glyph_string (s, faces, overlaps_p)
4105 struct glyph_string *s;
4106 struct face **faces;
4107 int overlaps_p;
4109 int i;
4111 xassert (s);
4113 s->for_overlaps_p = overlaps_p;
4115 s->face = faces[s->gidx];
4116 s->font = s->face->font;
4117 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4119 /* For all glyphs of this composition, starting at the offset
4120 S->gidx, until we reach the end of the definition or encounter a
4121 glyph that requires the different face, add it to S. */
4122 ++s->nchars;
4123 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4124 ++s->nchars;
4126 /* All glyph strings for the same composition has the same width,
4127 i.e. the width set for the first component of the composition. */
4129 s->width = s->first_glyph->pixel_width;
4131 /* If the specified font could not be loaded, use the frame's
4132 default font, but record the fact that we couldn't load it in
4133 the glyph string so that we can draw rectangles for the
4134 characters of the glyph string. */
4135 if (s->font == NULL)
4137 s->font_not_found_p = 1;
4138 s->font = FRAME_FONT (s->f);
4141 /* Adjust base line for subscript/superscript text. */
4142 s->ybase += s->first_glyph->voffset;
4144 xassert (s->face && s->face->gc);
4146 /* This glyph string must always be drawn with 16-bit functions. */
4147 s->two_byte_p = 1;
4149 return s->gidx + s->nchars;
4153 /* Load glyph string S with a sequence characters.
4154 FACE_ID is the face id of the string. START is the index of the
4155 first glyph to consider, END is the index of the last + 1.
4156 OVERLAPS_P non-zero means S should draw the foreground only, and
4157 use its lines physical height for clipping.
4159 Value is the index of the first glyph not in S. */
4161 static int
4162 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4163 struct glyph_string *s;
4164 int face_id;
4165 int start, end, overlaps_p;
4167 struct glyph *glyph, *last;
4168 int voffset;
4169 int glyph_not_available_p;
4171 xassert (s->f == XFRAME (s->w->frame));
4172 xassert (s->nchars == 0);
4173 xassert (start >= 0 && end > start);
4175 s->for_overlaps_p = overlaps_p,
4176 glyph = s->row->glyphs[s->area] + start;
4177 last = s->row->glyphs[s->area] + end;
4178 voffset = glyph->voffset;
4180 glyph_not_available_p = glyph->glyph_not_available_p;
4182 while (glyph < last
4183 && glyph->type == CHAR_GLYPH
4184 && glyph->voffset == voffset
4185 /* Same face id implies same font, nowadays. */
4186 && glyph->face_id == face_id
4187 && glyph->glyph_not_available_p == glyph_not_available_p)
4189 int two_byte_p;
4191 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4192 s->char2b + s->nchars,
4193 &two_byte_p);
4194 s->two_byte_p = two_byte_p;
4195 ++s->nchars;
4196 xassert (s->nchars <= end - start);
4197 s->width += glyph->pixel_width;
4198 ++glyph;
4201 s->font = s->face->font;
4202 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4204 /* If the specified font could not be loaded, use the frame's font,
4205 but record the fact that we couldn't load it in
4206 S->font_not_found_p so that we can draw rectangles for the
4207 characters of the glyph string. */
4208 if (s->font == NULL || glyph_not_available_p)
4210 s->font_not_found_p = 1;
4211 s->font = FRAME_FONT (s->f);
4214 /* Adjust base line for subscript/superscript text. */
4215 s->ybase += voffset;
4217 xassert (s->face && s->face->gc);
4218 return glyph - s->row->glyphs[s->area];
4222 /* Fill glyph string S from image glyph S->first_glyph. */
4224 static void
4225 x_fill_image_glyph_string (s)
4226 struct glyph_string *s;
4228 xassert (s->first_glyph->type == IMAGE_GLYPH);
4229 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4230 xassert (s->img);
4231 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4232 s->font = s->face->font;
4233 s->width = s->first_glyph->pixel_width;
4235 /* Adjust base line for subscript/superscript text. */
4236 s->ybase += s->first_glyph->voffset;
4240 /* Fill glyph string S from stretch glyph S->first_glyph. */
4242 static void
4243 x_fill_stretch_glyph_string (s)
4244 struct glyph_string *s;
4246 xassert (s->first_glyph->type == STRETCH_GLYPH);
4247 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4248 s->font = s->face->font;
4249 s->width = s->first_glyph->pixel_width;
4251 /* Adjust base line for subscript/superscript text. */
4252 s->ybase += s->first_glyph->voffset;
4256 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4257 of XChar2b structures for S; it can't be allocated in
4258 x_init_glyph_string because it must be allocated via `alloca'. W
4259 is the window on which S is drawn. ROW and AREA are the glyph row
4260 and area within the row from which S is constructed. START is the
4261 index of the first glyph structure covered by S. HL is a
4262 face-override for drawing S. */
4264 static void
4265 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4266 struct glyph_string *s;
4267 XChar2b *char2b;
4268 struct window *w;
4269 struct glyph_row *row;
4270 enum glyph_row_area area;
4271 int start;
4272 enum draw_glyphs_face hl;
4274 bzero (s, sizeof *s);
4275 s->w = w;
4276 s->f = XFRAME (w->frame);
4277 s->display = FRAME_X_DISPLAY (s->f);
4278 s->window = FRAME_X_WINDOW (s->f);
4279 s->char2b = char2b;
4280 s->hl = hl;
4281 s->row = row;
4282 s->area = area;
4283 s->first_glyph = row->glyphs[area] + start;
4284 s->height = row->height;
4285 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4287 /* Display the internal border below the tool-bar window. */
4288 if (s->w == XWINDOW (s->f->tool_bar_window))
4289 s->y -= s->f->output_data.x->internal_border_width;
4291 s->ybase = s->y + row->ascent;
4295 /* Set background width of glyph string S. START is the index of the
4296 first glyph following S. LAST_X is the right-most x-position + 1
4297 in the drawing area. */
4299 static INLINE void
4300 x_set_glyph_string_background_width (s, start, last_x)
4301 struct glyph_string *s;
4302 int start;
4303 int last_x;
4305 /* If the face of this glyph string has to be drawn to the end of
4306 the drawing area, set S->extends_to_end_of_line_p. */
4307 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4309 if (start == s->row->used[s->area]
4310 && s->hl == DRAW_NORMAL_TEXT
4311 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4312 || s->face->background != default_face->background
4313 || s->face->stipple != default_face->stipple))
4314 s->extends_to_end_of_line_p = 1;
4316 /* If S extends its face to the end of the line, set its
4317 background_width to the distance to the right edge of the drawing
4318 area. */
4319 if (s->extends_to_end_of_line_p)
4320 s->background_width = last_x - s->x + 1;
4321 else
4322 s->background_width = s->width;
4326 /* Add a glyph string for a stretch glyph to the list of strings
4327 between HEAD and TAIL. START is the index of the stretch glyph in
4328 row area AREA of glyph row ROW. END is the index of the last glyph
4329 in that glyph row area. X is the current output position assigned
4330 to the new glyph string constructed. HL overrides that face of the
4331 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4332 is the right-most x-position of the drawing area. */
4334 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4335 and below -- keep them on one line. */
4336 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4337 do \
4339 s = (struct glyph_string *) alloca (sizeof *s); \
4340 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4341 x_fill_stretch_glyph_string (s); \
4342 x_append_glyph_string (&HEAD, &TAIL, s); \
4343 ++START; \
4344 s->x = (X); \
4346 while (0)
4349 /* Add a glyph string for an image glyph to the list of strings
4350 between HEAD and TAIL. START is the index of the image glyph in
4351 row area AREA of glyph row ROW. END is the index of the last glyph
4352 in that glyph row area. X is the current output position assigned
4353 to the new glyph string constructed. HL overrides that face of the
4354 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4355 is the right-most x-position of the drawing area. */
4357 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4358 do \
4360 s = (struct glyph_string *) alloca (sizeof *s); \
4361 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4362 x_fill_image_glyph_string (s); \
4363 x_append_glyph_string (&HEAD, &TAIL, s); \
4364 ++START; \
4365 s->x = (X); \
4367 while (0)
4370 /* Add a glyph string for a sequence of character glyphs to the list
4371 of strings between HEAD and TAIL. START is the index of the first
4372 glyph in row area AREA of glyph row ROW that is part of the new
4373 glyph string. END is the index of the last glyph in that glyph row
4374 area. X is the current output position assigned to the new glyph
4375 string constructed. HL overrides that face of the glyph; e.g. it
4376 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4377 right-most x-position of the drawing area. */
4379 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4380 do \
4382 int c, charset, face_id; \
4383 XChar2b *char2b; \
4385 c = (ROW)->glyphs[AREA][START].u.ch; \
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->x = (X); \
4393 START = x_fill_glyph_string (s, face_id, START, END, \
4394 OVERLAPS_P); \
4396 while (0)
4399 /* Add a glyph string for a composite sequence to the list of strings
4400 between HEAD and TAIL. START is the index of the first glyph in
4401 row area AREA of glyph row ROW that is part of the new glyph
4402 string. END is the index of the last glyph in that glyph row area.
4403 X is the current output position assigned to the new glyph string
4404 constructed. HL overrides that face of the glyph; e.g. it is
4405 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4406 x-position of the drawing area. */
4408 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4409 do { \
4410 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4411 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4412 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), 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 base_face = base_face->ascii_face; \
4421 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4422 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4423 /* At first, fill in `char2b' and `faces'. */ \
4424 for (n = 0; n < glyph_len; n++) \
4426 int c = COMPOSITION_GLYPH (cmp, n); \
4427 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4428 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4429 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4430 this_face_id, char2b + n, 1); \
4433 /* Make glyph_strings for each glyph sequence that is drawable by \
4434 the same face, and append them to HEAD/TAIL. */ \
4435 for (n = 0; n < cmp->glyph_len;) \
4437 s = (struct glyph_string *) alloca (sizeof *s); \
4438 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4439 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4440 s->cmp = cmp; \
4441 s->gidx = n; \
4442 s->x = (X); \
4444 if (n == 0) \
4445 first_s = s; \
4447 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4450 ++START; \
4451 s = first_s; \
4452 } while (0)
4455 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4456 of AREA of glyph row ROW on window W between indices START and END.
4457 HL overrides the face for drawing glyph strings, e.g. it is
4458 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4459 x-positions of the drawing area.
4461 This is an ugly monster macro construct because we must use alloca
4462 to allocate glyph strings (because x_draw_glyphs can be called
4463 asynchronously). */
4465 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4466 do \
4468 HEAD = TAIL = NULL; \
4469 while (START < END) \
4471 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4472 switch (first_glyph->type) \
4474 case CHAR_GLYPH: \
4475 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4476 TAIL, HL, X, LAST_X, \
4477 OVERLAPS_P); \
4478 break; \
4480 case COMPOSITE_GLYPH: \
4481 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4482 HEAD, TAIL, HL, X, LAST_X,\
4483 OVERLAPS_P); \
4484 break; \
4486 case STRETCH_GLYPH: \
4487 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4488 HEAD, TAIL, HL, X, LAST_X); \
4489 break; \
4491 case IMAGE_GLYPH: \
4492 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4493 TAIL, HL, X, LAST_X); \
4494 break; \
4496 default: \
4497 abort (); \
4500 x_set_glyph_string_background_width (s, START, LAST_X); \
4501 (X) += s->width; \
4504 while (0)
4507 /* Draw glyphs between START and END in AREA of ROW on window W,
4508 starting at x-position X. X is relative to AREA in W. HL is a
4509 face-override with the following meaning:
4511 DRAW_NORMAL_TEXT draw normally
4512 DRAW_CURSOR draw in cursor face
4513 DRAW_MOUSE_FACE draw in mouse face.
4514 DRAW_INVERSE_VIDEO draw in mode line face
4515 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4516 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4518 If REAL_START is non-null, return in *REAL_START the real starting
4519 position for display. This can be different from START in case
4520 overlapping glyphs must be displayed. If REAL_END is non-null,
4521 return in *REAL_END the real end position for display. This can be
4522 different from END in case overlapping glyphs must be displayed.
4524 If OVERLAPS_P is non-zero, draw only the foreground of characters
4525 and clip to the physical height of ROW.
4527 Value is the x-position reached, relative to AREA of W. */
4529 static int
4530 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4531 overlaps_p)
4532 struct window *w;
4533 int x;
4534 struct glyph_row *row;
4535 enum glyph_row_area area;
4536 int start, end;
4537 enum draw_glyphs_face hl;
4538 int *real_start, *real_end;
4539 int overlaps_p;
4541 struct glyph_string *head, *tail;
4542 struct glyph_string *s;
4543 int last_x, area_width;
4544 int x_reached;
4545 int i, j;
4547 /* Let's rather be paranoid than getting a SEGV. */
4548 start = max (0, start);
4549 end = min (end, row->used[area]);
4550 if (real_start)
4551 *real_start = start;
4552 if (real_end)
4553 *real_end = end;
4555 /* Translate X to frame coordinates. Set last_x to the right
4556 end of the drawing area. */
4557 if (row->full_width_p)
4559 /* X is relative to the left edge of W, without scroll bars
4560 or flag areas. */
4561 struct frame *f = XFRAME (w->frame);
4562 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4563 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4565 x += window_left_x;
4566 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4567 last_x = window_left_x + area_width;
4569 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4571 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4572 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4573 last_x += width;
4574 else
4575 x -= width;
4578 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4579 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4581 else
4583 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4584 area_width = window_box_width (w, area);
4585 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4588 /* Build a doubly-linked list of glyph_string structures between
4589 head and tail from what we have to draw. Note that the macro
4590 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4591 the reason we use a separate variable `i'. */
4592 i = start;
4593 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4594 overlaps_p);
4595 if (tail)
4596 x_reached = tail->x + tail->background_width;
4597 else
4598 x_reached = x;
4600 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4601 the row, redraw some glyphs in front or following the glyph
4602 strings built above. */
4603 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4605 int dummy_x = 0;
4606 struct glyph_string *h, *t;
4608 /* Compute overhangs for all glyph strings. */
4609 for (s = head; s; s = s->next)
4610 x_compute_glyph_string_overhangs (s);
4612 /* Prepend glyph strings for glyphs in front of the first glyph
4613 string that are overwritten because of the first glyph
4614 string's left overhang. The background of all strings
4615 prepended must be drawn because the first glyph string
4616 draws over it. */
4617 i = x_left_overwritten (head);
4618 if (i >= 0)
4620 j = i;
4621 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4622 DRAW_NORMAL_TEXT, dummy_x, last_x,
4623 overlaps_p);
4624 start = i;
4625 if (real_start)
4626 *real_start = start;
4627 x_compute_overhangs_and_x (t, head->x, 1);
4628 x_prepend_glyph_string_lists (&head, &tail, h, t);
4631 /* Prepend glyph strings for glyphs in front of the first glyph
4632 string that overwrite that glyph string because of their
4633 right overhang. For these strings, only the foreground must
4634 be drawn, because it draws over the glyph string at `head'.
4635 The background must not be drawn because this would overwrite
4636 right overhangs of preceding glyphs for which no glyph
4637 strings exist. */
4638 i = x_left_overwriting (head);
4639 if (i >= 0)
4641 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4642 DRAW_NORMAL_TEXT, dummy_x, last_x,
4643 overlaps_p);
4644 for (s = h; s; s = s->next)
4645 s->background_filled_p = 1;
4646 if (real_start)
4647 *real_start = i;
4648 x_compute_overhangs_and_x (t, head->x, 1);
4649 x_prepend_glyph_string_lists (&head, &tail, h, t);
4652 /* Append glyphs strings for glyphs following the last glyph
4653 string tail that are overwritten by tail. The background of
4654 these strings has to be drawn because tail's foreground draws
4655 over it. */
4656 i = x_right_overwritten (tail);
4657 if (i >= 0)
4659 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4660 DRAW_NORMAL_TEXT, x, last_x,
4661 overlaps_p);
4662 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4663 x_append_glyph_string_lists (&head, &tail, h, t);
4664 if (real_end)
4665 *real_end = i;
4668 /* Append glyph strings for glyphs following the last glyph
4669 string tail that overwrite tail. The foreground of such
4670 glyphs has to be drawn because it writes into the background
4671 of tail. The background must not be drawn because it could
4672 paint over the foreground of following glyphs. */
4673 i = x_right_overwriting (tail);
4674 if (i >= 0)
4676 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4677 DRAW_NORMAL_TEXT, x, last_x,
4678 overlaps_p);
4679 for (s = h; s; s = s->next)
4680 s->background_filled_p = 1;
4681 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4682 x_append_glyph_string_lists (&head, &tail, h, t);
4683 if (real_end)
4684 *real_end = i;
4688 /* Draw all strings. */
4689 for (s = head; s; s = s->next)
4690 x_draw_glyph_string (s);
4692 /* Value is the x-position up to which drawn, relative to AREA of W.
4693 This doesn't include parts drawn because of overhangs. */
4694 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4695 if (!row->full_width_p)
4697 if (area > LEFT_MARGIN_AREA)
4698 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4699 if (area > TEXT_AREA)
4700 x_reached -= window_box_width (w, TEXT_AREA);
4702 return x_reached;
4706 /* Fix the display of area AREA of overlapping row ROW in window W. */
4708 static void
4709 x_fix_overlapping_area (w, row, area)
4710 struct window *w;
4711 struct glyph_row *row;
4712 enum glyph_row_area area;
4714 int i, x;
4716 BLOCK_INPUT;
4718 if (area == LEFT_MARGIN_AREA)
4719 x = 0;
4720 else if (area == TEXT_AREA)
4721 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4722 else
4723 x = (window_box_width (w, LEFT_MARGIN_AREA)
4724 + window_box_width (w, TEXT_AREA));
4726 for (i = 0; i < row->used[area];)
4728 if (row->glyphs[area][i].overlaps_vertically_p)
4730 int start = i, start_x = x;
4734 x += row->glyphs[area][i].pixel_width;
4735 ++i;
4737 while (i < row->used[area]
4738 && row->glyphs[area][i].overlaps_vertically_p);
4740 x_draw_glyphs (w, start_x, row, area, start, i,
4741 (row->inverse_p
4742 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4743 NULL, NULL, 1);
4745 else
4747 x += row->glyphs[area][i].pixel_width;
4748 ++i;
4752 UNBLOCK_INPUT;
4756 /* Output LEN glyphs starting at START at the nominal cursor position.
4757 Advance the nominal cursor over the text. The global variable
4758 updated_window contains the window being updated, updated_row is
4759 the glyph row being updated, and updated_area is the area of that
4760 row being updated. */
4762 static void
4763 x_write_glyphs (start, len)
4764 struct glyph *start;
4765 int len;
4767 int x, hpos, real_start, real_end;
4769 xassert (updated_window && updated_row);
4770 BLOCK_INPUT;
4772 /* Write glyphs. */
4774 hpos = start - updated_row->glyphs[updated_area];
4775 x = x_draw_glyphs (updated_window, output_cursor.x,
4776 updated_row, updated_area,
4777 hpos, hpos + len,
4778 (updated_row->inverse_p
4779 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4780 &real_start, &real_end, 0);
4782 /* If we drew over the cursor, note that it is not visible any more. */
4783 note_overwritten_text_cursor (updated_window, real_start,
4784 real_end - real_start);
4786 UNBLOCK_INPUT;
4788 /* Advance the output cursor. */
4789 output_cursor.hpos += len;
4790 output_cursor.x = x;
4794 /* Insert LEN glyphs from START at the nominal cursor position. */
4796 static void
4797 x_insert_glyphs (start, len)
4798 struct glyph *start;
4799 register int len;
4801 struct frame *f;
4802 struct window *w;
4803 int line_height, shift_by_width, shifted_region_width;
4804 struct glyph_row *row;
4805 struct glyph *glyph;
4806 int frame_x, frame_y, hpos, real_start, real_end;
4808 xassert (updated_window && updated_row);
4809 BLOCK_INPUT;
4810 w = updated_window;
4811 f = XFRAME (WINDOW_FRAME (w));
4813 /* Get the height of the line we are in. */
4814 row = updated_row;
4815 line_height = row->height;
4817 /* Get the width of the glyphs to insert. */
4818 shift_by_width = 0;
4819 for (glyph = start; glyph < start + len; ++glyph)
4820 shift_by_width += glyph->pixel_width;
4822 /* Get the width of the region to shift right. */
4823 shifted_region_width = (window_box_width (w, updated_area)
4824 - output_cursor.x
4825 - shift_by_width);
4827 /* Shift right. */
4828 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4829 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4830 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4831 f->output_data.x->normal_gc,
4832 frame_x, frame_y,
4833 shifted_region_width, line_height,
4834 frame_x + shift_by_width, frame_y);
4836 /* Write the glyphs. */
4837 hpos = start - row->glyphs[updated_area];
4838 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4839 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4840 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4842 /* Advance the output cursor. */
4843 output_cursor.hpos += len;
4844 output_cursor.x += shift_by_width;
4845 UNBLOCK_INPUT;
4849 /* Delete N glyphs at the nominal cursor position. Not implemented
4850 for X frames. */
4852 static void
4853 x_delete_glyphs (n)
4854 register int n;
4856 abort ();
4860 /* Erase the current text line from the nominal cursor position
4861 (inclusive) to pixel column TO_X (exclusive). The idea is that
4862 everything from TO_X onward is already erased.
4864 TO_X is a pixel position relative to updated_area of
4865 updated_window. TO_X == -1 means clear to the end of this area. */
4867 static void
4868 x_clear_end_of_line (to_x)
4869 int to_x;
4871 struct frame *f;
4872 struct window *w = updated_window;
4873 int max_x, min_y, max_y;
4874 int from_x, from_y, to_y;
4876 xassert (updated_window && updated_row);
4877 f = XFRAME (w->frame);
4879 if (updated_row->full_width_p)
4881 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4882 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4883 && !w->pseudo_window_p)
4884 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4886 else
4887 max_x = window_box_width (w, updated_area);
4888 max_y = window_text_bottom_y (w);
4890 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4891 of window. For TO_X > 0, truncate to end of drawing area. */
4892 if (to_x == 0)
4893 return;
4894 else if (to_x < 0)
4895 to_x = max_x;
4896 else
4897 to_x = min (to_x, max_x);
4899 to_y = min (max_y, output_cursor.y + updated_row->height);
4901 /* Notice if the cursor will be cleared by this operation. */
4902 if (!updated_row->full_width_p)
4903 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4905 from_x = output_cursor.x;
4907 /* Translate to frame coordinates. */
4908 if (updated_row->full_width_p)
4910 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4911 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4913 else
4915 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4916 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4919 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4920 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4921 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4923 /* Prevent inadvertently clearing to end of the X window. */
4924 if (to_x > from_x && to_y > from_y)
4926 BLOCK_INPUT;
4927 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4928 from_x, from_y, to_x - from_x, to_y - from_y,
4929 False);
4930 UNBLOCK_INPUT;
4935 /* Clear entire frame. If updating_frame is non-null, clear that
4936 frame. Otherwise clear the selected frame. */
4938 static void
4939 x_clear_frame ()
4941 struct frame *f;
4943 if (updating_frame)
4944 f = updating_frame;
4945 else
4946 f = SELECTED_FRAME ();
4948 /* Clearing the frame will erase any cursor, so mark them all as no
4949 longer visible. */
4950 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4951 output_cursor.hpos = output_cursor.vpos = 0;
4952 output_cursor.x = -1;
4954 /* We don't set the output cursor here because there will always
4955 follow an explicit cursor_to. */
4956 BLOCK_INPUT;
4957 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4959 /* We have to clear the scroll bars, too. If we have changed
4960 colors or something like that, then they should be notified. */
4961 x_scroll_bar_clear (f);
4963 XFlush (FRAME_X_DISPLAY (f));
4964 UNBLOCK_INPUT;
4969 /* Invert the middle quarter of the frame for .15 sec. */
4971 /* We use the select system call to do the waiting, so we have to make
4972 sure it's available. If it isn't, we just won't do visual bells. */
4974 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4977 /* Subtract the `struct timeval' values X and Y, storing the result in
4978 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4980 static int
4981 timeval_subtract (result, x, y)
4982 struct timeval *result, x, y;
4984 /* Perform the carry for the later subtraction by updating y. This
4985 is safer because on some systems the tv_sec member is unsigned. */
4986 if (x.tv_usec < y.tv_usec)
4988 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4989 y.tv_usec -= 1000000 * nsec;
4990 y.tv_sec += nsec;
4993 if (x.tv_usec - y.tv_usec > 1000000)
4995 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4996 y.tv_usec += 1000000 * nsec;
4997 y.tv_sec -= nsec;
5000 /* Compute the time remaining to wait. tv_usec is certainly
5001 positive. */
5002 result->tv_sec = x.tv_sec - y.tv_sec;
5003 result->tv_usec = x.tv_usec - y.tv_usec;
5005 /* Return indication of whether the result should be considered
5006 negative. */
5007 return x.tv_sec < y.tv_sec;
5010 void
5011 XTflash (f)
5012 struct frame *f;
5014 BLOCK_INPUT;
5017 GC gc;
5019 /* Create a GC that will use the GXxor function to flip foreground
5020 pixels into background pixels. */
5022 XGCValues values;
5024 values.function = GXxor;
5025 values.foreground = (f->output_data.x->foreground_pixel
5026 ^ f->output_data.x->background_pixel);
5028 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5029 GCFunction | GCForeground, &values);
5033 /* Get the height not including a menu bar widget. */
5034 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5035 /* Height of each line to flash. */
5036 int flash_height = FRAME_LINE_HEIGHT (f);
5037 /* These will be the left and right margins of the rectangles. */
5038 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5039 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5041 int width;
5043 /* Don't flash the area between a scroll bar and the frame
5044 edge it is next to. */
5045 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5047 case vertical_scroll_bar_left:
5048 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5049 break;
5051 case vertical_scroll_bar_right:
5052 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5053 break;
5055 default:
5056 break;
5059 width = flash_right - flash_left;
5061 /* If window is tall, flash top and bottom line. */
5062 if (height > 3 * FRAME_LINE_HEIGHT (f))
5064 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5065 flash_left,
5066 (FRAME_INTERNAL_BORDER_WIDTH (f)
5067 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5068 width, flash_height);
5069 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5070 flash_left,
5071 (height - flash_height
5072 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5073 width, flash_height);
5075 else
5076 /* If it is short, flash it all. */
5077 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5078 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5079 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5081 x_flush (f);
5084 struct timeval wakeup;
5086 EMACS_GET_TIME (wakeup);
5088 /* Compute time to wait until, propagating carry from usecs. */
5089 wakeup.tv_usec += 150000;
5090 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5091 wakeup.tv_usec %= 1000000;
5093 /* Keep waiting until past the time wakeup. */
5094 while (1)
5096 struct timeval timeout;
5098 EMACS_GET_TIME (timeout);
5100 /* In effect, timeout = wakeup - timeout.
5101 Break if result would be negative. */
5102 if (timeval_subtract (&timeout, wakeup, timeout))
5103 break;
5105 /* Try to wait that long--but we might wake up sooner. */
5106 select (0, NULL, NULL, NULL, &timeout);
5110 /* If window is tall, flash top and bottom line. */
5111 if (height > 3 * FRAME_LINE_HEIGHT (f))
5113 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5114 flash_left,
5115 (FRAME_INTERNAL_BORDER_WIDTH (f)
5116 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5117 width, flash_height);
5118 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5119 flash_left,
5120 (height - flash_height
5121 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5122 width, flash_height);
5124 else
5125 /* If it is short, flash it all. */
5126 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5127 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5128 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5130 XFreeGC (FRAME_X_DISPLAY (f), gc);
5131 x_flush (f);
5135 UNBLOCK_INPUT;
5138 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5141 /* Make audible bell. */
5143 void
5144 XTring_bell ()
5146 struct frame *f = SELECTED_FRAME ();
5148 if (FRAME_X_DISPLAY (f))
5150 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5151 if (visible_bell)
5152 XTflash (f);
5153 else
5154 #endif
5156 BLOCK_INPUT;
5157 XBell (FRAME_X_DISPLAY (f), 0);
5158 XFlush (FRAME_X_DISPLAY (f));
5159 UNBLOCK_INPUT;
5165 /* Specify how many text lines, from the top of the window,
5166 should be affected by insert-lines and delete-lines operations.
5167 This, and those operations, are used only within an update
5168 that is bounded by calls to x_update_begin and x_update_end. */
5170 static void
5171 XTset_terminal_window (n)
5172 register int n;
5174 /* This function intentionally left blank. */
5179 /***********************************************************************
5180 Line Dance
5181 ***********************************************************************/
5183 /* Perform an insert-lines or delete-lines operation, inserting N
5184 lines or deleting -N lines at vertical position VPOS. */
5186 static void
5187 x_ins_del_lines (vpos, n)
5188 int vpos, n;
5190 abort ();
5194 /* Scroll part of the display as described by RUN. */
5196 static void
5197 x_scroll_run (w, run)
5198 struct window *w;
5199 struct run *run;
5201 struct frame *f = XFRAME (w->frame);
5202 int x, y, width, height, from_y, to_y, bottom_y;
5204 /* Get frame-relative bounding box of the text display area of W,
5205 without mode lines. Include in this box the flags areas to the
5206 left and right of W. */
5207 window_box (w, -1, &x, &y, &width, &height);
5208 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5209 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5211 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5212 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5213 bottom_y = y + height;
5215 if (to_y < from_y)
5217 /* Scrolling up. Make sure we don't copy part of the mode
5218 line at the bottom. */
5219 if (from_y + run->height > bottom_y)
5220 height = bottom_y - from_y;
5221 else
5222 height = run->height;
5224 else
5226 /* Scolling down. Make sure we don't copy over the mode line.
5227 at the bottom. */
5228 if (to_y + run->height > bottom_y)
5229 height = bottom_y - to_y;
5230 else
5231 height = run->height;
5234 BLOCK_INPUT;
5236 /* Cursor off. Will be switched on again in x_update_window_end. */
5237 updated_window = w;
5238 x_clear_cursor (w);
5240 XCopyArea (FRAME_X_DISPLAY (f),
5241 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5242 f->output_data.x->normal_gc,
5243 x, from_y,
5244 width, height,
5245 x, to_y);
5247 UNBLOCK_INPUT;
5252 /***********************************************************************
5253 Exposure Events
5254 ***********************************************************************/
5256 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5257 corner of the exposed rectangle. W and H are width and height of
5258 the exposed area. All are pixel values. W or H zero means redraw
5259 the entire frame. */
5261 static void
5262 expose_frame (f, x, y, w, h)
5263 struct frame *f;
5264 int x, y, w, h;
5266 XRectangle r;
5268 TRACE ((stderr, "expose_frame "));
5270 /* No need to redraw if frame will be redrawn soon. */
5271 if (FRAME_GARBAGED_P (f))
5273 TRACE ((stderr, " garbaged\n"));
5274 return;
5277 /* If basic faces haven't been realized yet, there is no point in
5278 trying to redraw anything. This can happen when we get an expose
5279 event while Emacs is starting, e.g. by moving another window. */
5280 if (FRAME_FACE_CACHE (f) == NULL
5281 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5283 TRACE ((stderr, " no faces\n"));
5284 return;
5287 if (w == 0 || h == 0)
5289 r.x = r.y = 0;
5290 r.width = CANON_X_UNIT (f) * f->width;
5291 r.height = CANON_Y_UNIT (f) * f->height;
5293 else
5295 r.x = x;
5296 r.y = y;
5297 r.width = w;
5298 r.height = h;
5301 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5302 expose_window_tree (XWINDOW (f->root_window), &r);
5304 if (WINDOWP (f->tool_bar_window))
5306 struct window *w = XWINDOW (f->tool_bar_window);
5307 XRectangle window_rect;
5308 XRectangle intersection_rect;
5309 int window_x, window_y, window_width, window_height;
5312 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5313 window_rect.x = window_x;
5314 window_rect.y = window_y;
5315 window_rect.width = window_width;
5316 window_rect.height = window_height;
5318 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5319 expose_window (w, &intersection_rect);
5322 #ifndef USE_X_TOOLKIT
5323 if (WINDOWP (f->menu_bar_window))
5325 struct window *w = XWINDOW (f->menu_bar_window);
5326 XRectangle window_rect;
5327 XRectangle intersection_rect;
5328 int window_x, window_y, window_width, window_height;
5331 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5332 window_rect.x = window_x;
5333 window_rect.y = window_y;
5334 window_rect.width = window_width;
5335 window_rect.height = window_height;
5337 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5338 expose_window (w, &intersection_rect);
5340 #endif /* not USE_X_TOOLKIT */
5344 /* Redraw (parts) of all windows in the window tree rooted at W that
5345 intersect R. R contains frame pixel coordinates. */
5347 static void
5348 expose_window_tree (w, r)
5349 struct window *w;
5350 XRectangle *r;
5352 while (w)
5354 if (!NILP (w->hchild))
5355 expose_window_tree (XWINDOW (w->hchild), r);
5356 else if (!NILP (w->vchild))
5357 expose_window_tree (XWINDOW (w->vchild), r);
5358 else
5360 XRectangle window_rect;
5361 XRectangle intersection_rect;
5362 struct frame *f = XFRAME (w->frame);
5363 int window_x, window_y, window_width, window_height;
5365 /* Frame-relative pixel rectangle of W. */
5366 window_box (w, -1, &window_x, &window_y, &window_width,
5367 &window_height);
5368 window_rect.x
5369 = (window_x
5370 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5371 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5372 window_rect.y = window_y;
5373 window_rect.width
5374 = (window_width
5375 + FRAME_X_FLAGS_AREA_WIDTH (f)
5376 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5377 window_rect.height
5378 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5380 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5381 expose_window (w, &intersection_rect);
5384 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5389 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5390 which intersects rectangle R. R is in window-relative coordinates. */
5392 static void
5393 expose_area (w, row, r, area)
5394 struct window *w;
5395 struct glyph_row *row;
5396 XRectangle *r;
5397 enum glyph_row_area area;
5399 int x;
5400 struct glyph *first = row->glyphs[area];
5401 struct glyph *end = row->glyphs[area] + row->used[area];
5402 struct glyph *last;
5403 int first_x;
5405 /* Set x to the window-relative start position for drawing glyphs of
5406 AREA. The first glyph of the text area can be partially visible.
5407 The first glyphs of other areas cannot. */
5408 if (area == LEFT_MARGIN_AREA)
5409 x = 0;
5410 else if (area == TEXT_AREA)
5411 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5412 else
5413 x = (window_box_width (w, LEFT_MARGIN_AREA)
5414 + window_box_width (w, TEXT_AREA));
5416 if (area == TEXT_AREA && row->fill_line_p)
5417 /* If row extends face to end of line write the whole line. */
5418 x_draw_glyphs (w, x, row, area,
5419 0, row->used[area],
5420 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5421 NULL, NULL, 0);
5422 else
5424 /* Find the first glyph that must be redrawn. */
5425 while (first < end
5426 && x + first->pixel_width < r->x)
5428 x += first->pixel_width;
5429 ++first;
5432 /* Find the last one. */
5433 last = first;
5434 first_x = x;
5435 while (last < end
5436 && x < r->x + r->width)
5438 x += last->pixel_width;
5439 ++last;
5442 /* Repaint. */
5443 if (last > first)
5444 x_draw_glyphs (w, first_x, row, area,
5445 first - row->glyphs[area],
5446 last - row->glyphs[area],
5447 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5448 NULL, NULL, 0);
5453 /* Redraw the parts of the glyph row ROW on window W intersecting
5454 rectangle R. R is in window-relative coordinates. */
5456 static void
5457 expose_line (w, row, r)
5458 struct window *w;
5459 struct glyph_row *row;
5460 XRectangle *r;
5462 xassert (row->enabled_p);
5464 if (row->mode_line_p || w->pseudo_window_p)
5465 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5466 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5467 NULL, NULL, 0);
5468 else
5470 if (row->used[LEFT_MARGIN_AREA])
5471 expose_area (w, row, r, LEFT_MARGIN_AREA);
5472 if (row->used[TEXT_AREA])
5473 expose_area (w, row, r, TEXT_AREA);
5474 if (row->used[RIGHT_MARGIN_AREA])
5475 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5476 x_draw_row_bitmaps (w, row);
5481 /* Return non-zero if W's cursor intersects rectangle R. */
5483 static int
5484 x_phys_cursor_in_rect_p (w, r)
5485 struct window *w;
5486 XRectangle *r;
5488 XRectangle cr, result;
5489 struct glyph *cursor_glyph;
5491 cursor_glyph = get_phys_cursor_glyph (w);
5492 if (cursor_glyph)
5494 cr.x = w->phys_cursor.x;
5495 cr.y = w->phys_cursor.y;
5496 cr.width = cursor_glyph->pixel_width;
5497 cr.height = w->phys_cursor_height;
5498 return x_intersect_rectangles (&cr, r, &result);
5500 else
5501 return 0;
5505 /* Redraw a rectangle of window W. R is a rectangle in window
5506 relative coordinates. Call this function with input blocked. */
5508 static void
5509 expose_window (w, r)
5510 struct window *w;
5511 XRectangle *r;
5513 struct glyph_row *row;
5514 int y;
5515 int yb = window_text_bottom_y (w);
5516 int cursor_cleared_p;
5518 /* If window is not yet fully initialized, do nothing. This can
5519 happen when toolkit scroll bars are used and a window is split.
5520 Reconfiguring the scroll bar will generate an expose for a newly
5521 created window. */
5522 if (w->current_matrix == NULL)
5523 return;
5525 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5526 r->x, r->y, r->width, r->height));
5528 /* Convert to window coordinates. */
5529 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5530 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5532 /* Turn off the cursor. */
5533 if (!w->pseudo_window_p
5534 && x_phys_cursor_in_rect_p (w, r))
5536 x_clear_cursor (w);
5537 cursor_cleared_p = 1;
5539 else
5540 cursor_cleared_p = 0;
5542 /* Find the first row intersecting the rectangle R. */
5543 row = w->current_matrix->rows;
5544 y = 0;
5545 while (row->enabled_p
5546 && y < yb
5547 && y + row->height < r->y)
5549 y += row->height;
5550 ++row;
5553 /* Display the text in the rectangle, one text line at a time. */
5554 while (row->enabled_p
5555 && y < yb
5556 && y < r->y + r->height)
5558 expose_line (w, row, r);
5559 y += row->height;
5560 ++row;
5563 /* Display the mode line if there is one. */
5564 if (WINDOW_WANTS_MODELINE_P (w)
5565 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5566 row->enabled_p)
5567 && row->y < r->y + r->height)
5568 expose_line (w, row, r);
5570 if (!w->pseudo_window_p)
5572 /* Draw border between windows. */
5573 x_draw_vertical_border (w);
5575 /* Turn the cursor on again. */
5576 if (cursor_cleared_p)
5577 x_update_window_cursor (w, 1);
5582 /* Determine the intersection of two rectangles R1 and R2. Return
5583 the intersection in *RESULT. Value is non-zero if RESULT is not
5584 empty. */
5586 static int
5587 x_intersect_rectangles (r1, r2, result)
5588 XRectangle *r1, *r2, *result;
5590 XRectangle *left, *right;
5591 XRectangle *upper, *lower;
5592 int intersection_p = 0;
5594 /* Rearrange so that R1 is the left-most rectangle. */
5595 if (r1->x < r2->x)
5596 left = r1, right = r2;
5597 else
5598 left = r2, right = r1;
5600 /* X0 of the intersection is right.x0, if this is inside R1,
5601 otherwise there is no intersection. */
5602 if (right->x <= left->x + left->width)
5604 result->x = right->x;
5606 /* The right end of the intersection is the minimum of the
5607 the right ends of left and right. */
5608 result->width = (min (left->x + left->width, right->x + right->width)
5609 - result->x);
5611 /* Same game for Y. */
5612 if (r1->y < r2->y)
5613 upper = r1, lower = r2;
5614 else
5615 upper = r2, lower = r1;
5617 /* The upper end of the intersection is lower.y0, if this is inside
5618 of upper. Otherwise, there is no intersection. */
5619 if (lower->y <= upper->y + upper->height)
5621 result->y = lower->y;
5623 /* The lower end of the intersection is the minimum of the lower
5624 ends of upper and lower. */
5625 result->height = (min (lower->y + lower->height,
5626 upper->y + upper->height)
5627 - result->y);
5628 intersection_p = 1;
5632 return intersection_p;
5639 static void
5640 frame_highlight (f)
5641 struct frame *f;
5643 /* We used to only do this if Vx_no_window_manager was non-nil, but
5644 the ICCCM (section 4.1.6) says that the window's border pixmap
5645 and border pixel are window attributes which are "private to the
5646 client", so we can always change it to whatever we want. */
5647 BLOCK_INPUT;
5648 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5649 f->output_data.x->border_pixel);
5650 UNBLOCK_INPUT;
5651 x_update_cursor (f, 1);
5654 static void
5655 frame_unhighlight (f)
5656 struct frame *f;
5658 /* We used to only do this if Vx_no_window_manager was non-nil, but
5659 the ICCCM (section 4.1.6) says that the window's border pixmap
5660 and border pixel are window attributes which are "private to the
5661 client", so we can always change it to whatever we want. */
5662 BLOCK_INPUT;
5663 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5664 f->output_data.x->border_tile);
5665 UNBLOCK_INPUT;
5666 x_update_cursor (f, 1);
5669 /* The focus has changed. Update the frames as necessary to reflect
5670 the new situation. Note that we can't change the selected frame
5671 here, because the Lisp code we are interrupting might become confused.
5672 Each event gets marked with the frame in which it occurred, so the
5673 Lisp code can tell when the switch took place by examining the events. */
5675 static void
5676 x_new_focus_frame (dpyinfo, frame)
5677 struct x_display_info *dpyinfo;
5678 struct frame *frame;
5680 struct frame *old_focus = dpyinfo->x_focus_frame;
5682 if (frame != dpyinfo->x_focus_frame)
5684 /* Set this before calling other routines, so that they see
5685 the correct value of x_focus_frame. */
5686 dpyinfo->x_focus_frame = frame;
5688 if (old_focus && old_focus->auto_lower)
5689 x_lower_frame (old_focus);
5691 #if 0
5692 selected_frame = frame;
5693 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5694 selected_frame);
5695 Fselect_window (selected_frame->selected_window);
5696 choose_minibuf_frame ();
5697 #endif /* ! 0 */
5699 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5700 pending_autoraise_frame = dpyinfo->x_focus_frame;
5701 else
5702 pending_autoraise_frame = 0;
5705 x_frame_rehighlight (dpyinfo);
5708 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5710 void
5711 x_mouse_leave (dpyinfo)
5712 struct x_display_info *dpyinfo;
5714 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5717 /* The focus has changed, or we have redirected a frame's focus to
5718 another frame (this happens when a frame uses a surrogate
5719 mini-buffer frame). Shift the highlight as appropriate.
5721 The FRAME argument doesn't necessarily have anything to do with which
5722 frame is being highlighted or un-highlighted; we only use it to find
5723 the appropriate X display info. */
5725 static void
5726 XTframe_rehighlight (frame)
5727 struct frame *frame;
5729 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5732 static void
5733 x_frame_rehighlight (dpyinfo)
5734 struct x_display_info *dpyinfo;
5736 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5738 if (dpyinfo->x_focus_frame)
5740 dpyinfo->x_highlight_frame
5741 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5742 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5743 : dpyinfo->x_focus_frame);
5744 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5746 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5747 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5750 else
5751 dpyinfo->x_highlight_frame = 0;
5753 if (dpyinfo->x_highlight_frame != old_highlight)
5755 if (old_highlight)
5756 frame_unhighlight (old_highlight);
5757 if (dpyinfo->x_highlight_frame)
5758 frame_highlight (dpyinfo->x_highlight_frame);
5764 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5766 /* Initialize mode_switch_bit and modifier_meaning. */
5767 static void
5768 x_find_modifier_meanings (dpyinfo)
5769 struct x_display_info *dpyinfo;
5771 int min_code, max_code;
5772 KeySym *syms;
5773 int syms_per_code;
5774 XModifierKeymap *mods;
5776 dpyinfo->meta_mod_mask = 0;
5777 dpyinfo->shift_lock_mask = 0;
5778 dpyinfo->alt_mod_mask = 0;
5779 dpyinfo->super_mod_mask = 0;
5780 dpyinfo->hyper_mod_mask = 0;
5782 #ifdef HAVE_X11R4
5783 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5784 #else
5785 min_code = dpyinfo->display->min_keycode;
5786 max_code = dpyinfo->display->max_keycode;
5787 #endif
5789 syms = XGetKeyboardMapping (dpyinfo->display,
5790 min_code, max_code - min_code + 1,
5791 &syms_per_code);
5792 mods = XGetModifierMapping (dpyinfo->display);
5794 /* Scan the modifier table to see which modifier bits the Meta and
5795 Alt keysyms are on. */
5797 int row, col; /* The row and column in the modifier table. */
5799 for (row = 3; row < 8; row++)
5800 for (col = 0; col < mods->max_keypermod; col++)
5802 KeyCode code
5803 = mods->modifiermap[(row * mods->max_keypermod) + col];
5805 /* Zeroes are used for filler. Skip them. */
5806 if (code == 0)
5807 continue;
5809 /* Are any of this keycode's keysyms a meta key? */
5811 int code_col;
5813 for (code_col = 0; code_col < syms_per_code; code_col++)
5815 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5817 switch (sym)
5819 case XK_Meta_L:
5820 case XK_Meta_R:
5821 dpyinfo->meta_mod_mask |= (1 << row);
5822 break;
5824 case XK_Alt_L:
5825 case XK_Alt_R:
5826 dpyinfo->alt_mod_mask |= (1 << row);
5827 break;
5829 case XK_Hyper_L:
5830 case XK_Hyper_R:
5831 dpyinfo->hyper_mod_mask |= (1 << row);
5832 break;
5834 case XK_Super_L:
5835 case XK_Super_R:
5836 dpyinfo->super_mod_mask |= (1 << row);
5837 break;
5839 case XK_Shift_Lock:
5840 /* Ignore this if it's not on the lock modifier. */
5841 if ((1 << row) == LockMask)
5842 dpyinfo->shift_lock_mask = LockMask;
5843 break;
5850 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5851 if (! dpyinfo->meta_mod_mask)
5853 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5854 dpyinfo->alt_mod_mask = 0;
5857 /* If some keys are both alt and meta,
5858 make them just meta, not alt. */
5859 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5861 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5864 XFree ((char *) syms);
5865 XFreeModifiermap (mods);
5868 /* Convert between the modifier bits X uses and the modifier bits
5869 Emacs uses. */
5871 static unsigned int
5872 x_x_to_emacs_modifiers (dpyinfo, state)
5873 struct x_display_info *dpyinfo;
5874 unsigned int state;
5876 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5877 | ((state & ControlMask) ? ctrl_modifier : 0)
5878 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5879 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5880 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5881 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
5884 static unsigned int
5885 x_emacs_to_x_modifiers (dpyinfo, state)
5886 struct x_display_info *dpyinfo;
5887 unsigned int state;
5889 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5890 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5891 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5892 | ((state & shift_modifier) ? ShiftMask : 0)
5893 | ((state & ctrl_modifier) ? ControlMask : 0)
5894 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
5897 /* Convert a keysym to its name. */
5899 char *
5900 x_get_keysym_name (keysym)
5901 KeySym keysym;
5903 char *value;
5905 BLOCK_INPUT;
5906 value = XKeysymToString (keysym);
5907 UNBLOCK_INPUT;
5909 return value;
5914 /* Mouse clicks and mouse movement. Rah. */
5916 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5917 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5918 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5919 not force the value into range. */
5921 void
5922 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5923 FRAME_PTR f;
5924 register int pix_x, pix_y;
5925 register int *x, *y;
5926 XRectangle *bounds;
5927 int noclip;
5929 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5930 even for negative values. */
5931 if (pix_x < 0)
5932 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
5933 if (pix_y < 0)
5934 pix_y -= (f)->output_data.x->line_height - 1;
5936 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5937 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5939 if (bounds)
5941 bounds->width = FONT_WIDTH (f->output_data.x->font);
5942 bounds->height = f->output_data.x->line_height;
5943 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5944 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5947 if (!noclip)
5949 if (pix_x < 0)
5950 pix_x = 0;
5951 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5952 pix_x = FRAME_WINDOW_WIDTH (f);
5954 if (pix_y < 0)
5955 pix_y = 0;
5956 else if (pix_y > f->height)
5957 pix_y = f->height;
5960 *x = pix_x;
5961 *y = pix_y;
5965 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5966 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5967 can't tell the positions because W's display is not up to date,
5968 return 0. */
5971 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5972 struct window *w;
5973 int hpos, vpos;
5974 int *frame_x, *frame_y;
5976 int success_p;
5978 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5979 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5981 if (display_completed)
5983 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5984 struct glyph *glyph = row->glyphs[TEXT_AREA];
5985 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5987 *frame_y = row->y;
5988 *frame_x = row->x;
5989 while (glyph < end)
5991 *frame_x += glyph->pixel_width;
5992 ++glyph;
5995 success_p = 1;
5997 else
5999 *frame_y = *frame_x = 0;
6000 success_p = 0;
6003 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6004 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6005 return success_p;
6009 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6011 If the event is a button press, then note that we have grabbed
6012 the mouse. */
6014 static Lisp_Object
6015 construct_mouse_click (result, event, f)
6016 struct input_event *result;
6017 XButtonEvent *event;
6018 struct frame *f;
6020 /* Make the event type no_event; we'll change that when we decide
6021 otherwise. */
6022 result->kind = mouse_click;
6023 result->code = event->button - Button1;
6024 result->timestamp = event->time;
6025 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6026 event->state)
6027 | (event->type == ButtonRelease
6028 ? up_modifier
6029 : down_modifier));
6031 XSETINT (result->x, event->x);
6032 XSETINT (result->y, event->y);
6033 XSETFRAME (result->frame_or_window, f);
6034 return Qnil;
6037 #if 0 /* This function isn't called. --gerd */
6039 /* Prepare a menu-event in *RESULT for placement in the input queue. */
6041 static Lisp_Object
6042 construct_menu_click (result, event, f)
6043 struct input_event *result;
6044 XButtonEvent *event;
6045 struct frame *f;
6047 /* Make the event type no_event; we'll change that when we decide
6048 otherwise. */
6049 result->kind = mouse_click;
6050 result->code = event->button - Button1;
6051 result->timestamp = event->time;
6052 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6053 event->state)
6054 | (event->type == ButtonRelease
6055 ? up_modifier
6056 : down_modifier));
6058 XSETINT (result->x, event->x);
6059 XSETINT (result->y, -1);
6060 XSETFRAME (result->frame_or_window, f);
6063 #endif /* 0 */
6066 /* Function to report a mouse movement to the mainstream Emacs code.
6067 The input handler calls this.
6069 We have received a mouse movement event, which is given in *event.
6070 If the mouse is over a different glyph than it was last time, tell
6071 the mainstream emacs code by setting mouse_moved. If not, ask for
6072 another motion event, so we can check again the next time it moves. */
6074 static XMotionEvent last_mouse_motion_event;
6075 static Lisp_Object last_mouse_motion_frame;
6077 static void
6078 note_mouse_movement (frame, event)
6079 FRAME_PTR frame;
6080 XMotionEvent *event;
6082 last_mouse_movement_time = event->time;
6083 last_mouse_motion_event = *event;
6084 XSETFRAME (last_mouse_motion_frame, frame);
6086 if (event->window != FRAME_X_WINDOW (frame))
6088 frame->mouse_moved = 1;
6089 last_mouse_scroll_bar = Qnil;
6090 note_mouse_highlight (frame, -1, -1);
6093 /* Has the mouse moved off the glyph it was on at the last sighting? */
6094 else if (event->x < last_mouse_glyph.x
6095 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6096 || event->y < last_mouse_glyph.y
6097 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6099 frame->mouse_moved = 1;
6100 last_mouse_scroll_bar = Qnil;
6101 note_mouse_highlight (frame, event->x, event->y);
6105 /* This is used for debugging, to turn off note_mouse_highlight. */
6107 int disable_mouse_highlight;
6111 /************************************************************************
6112 Mouse Face
6113 ************************************************************************/
6115 /* Find the glyph under window-relative coordinates X/Y in window W.
6116 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6117 strings. Return in *HPOS and *VPOS the row and column number of
6118 the glyph found. Return in *AREA the glyph area containing X.
6119 Value is a pointer to the glyph found or null if X/Y is not on
6120 text, or we can't tell because W's current matrix is not up to
6121 date. */
6123 static struct glyph *
6124 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6125 struct window *w;
6126 int x, y;
6127 int *hpos, *vpos, *area;
6129 struct glyph *glyph, *end;
6130 struct glyph_row *row;
6131 int x0, i, left_area_width;
6133 /* Find row containing Y. Give up if some row is not enabled. */
6134 for (i = 0; i < w->current_matrix->nrows; ++i)
6136 row = MATRIX_ROW (w->current_matrix, i);
6137 if (!row->enabled_p)
6138 return NULL;
6139 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6140 break;
6143 *vpos = i;
6144 *hpos = 0;
6146 /* Give up if Y is not in the window. */
6147 if (i == w->current_matrix->nrows)
6148 return NULL;
6150 /* Get the glyph area containing X. */
6151 if (w->pseudo_window_p)
6153 *area = TEXT_AREA;
6154 x0 = 0;
6156 else
6158 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6159 if (x < left_area_width)
6161 *area = LEFT_MARGIN_AREA;
6162 x0 = 0;
6164 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6166 *area = TEXT_AREA;
6167 x0 = row->x + left_area_width;
6169 else
6171 *area = RIGHT_MARGIN_AREA;
6172 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6176 /* Find glyph containing X. */
6177 glyph = row->glyphs[*area];
6178 end = glyph + row->used[*area];
6179 while (glyph < end)
6181 if (x < x0 + glyph->pixel_width)
6183 if (w->pseudo_window_p)
6184 break;
6185 else if (BUFFERP (glyph->object))
6186 break;
6189 x0 += glyph->pixel_width;
6190 ++glyph;
6193 if (glyph == end)
6194 return NULL;
6196 *hpos = glyph - row->glyphs[*area];
6197 return glyph;
6201 /* Convert frame-relative x/y to coordinates relative to window W.
6202 Takes pseudo-windows into account. */
6204 static void
6205 frame_to_window_pixel_xy (w, x, y)
6206 struct window *w;
6207 int *x, *y;
6209 if (w->pseudo_window_p)
6211 /* A pseudo-window is always full-width, and starts at the
6212 left edge of the frame, plus a frame border. */
6213 struct frame *f = XFRAME (w->frame);
6214 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6215 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6217 else
6219 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6220 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6225 /* Take proper action when mouse has moved to the mode or top line of
6226 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6227 mode line. X is relative to the start of the text display area of
6228 W, so the width of bitmap areas and scroll bars must be subtracted
6229 to get a position relative to the start of the mode line. */
6231 static void
6232 note_mode_line_highlight (w, x, mode_line_p)
6233 struct window *w;
6234 int x, mode_line_p;
6236 struct frame *f = XFRAME (w->frame);
6237 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6238 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6239 struct glyph_row *row;
6241 if (mode_line_p)
6242 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6243 else
6244 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6246 if (row->enabled_p)
6248 struct glyph *glyph, *end;
6249 Lisp_Object help, map;
6250 int x0;
6252 /* Find the glyph under X. */
6253 glyph = row->glyphs[TEXT_AREA];
6254 end = glyph + row->used[TEXT_AREA];
6255 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6256 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6257 while (glyph < end
6258 && x >= x0 + glyph->pixel_width)
6260 x0 += glyph->pixel_width;
6261 ++glyph;
6264 if (glyph < end
6265 && STRINGP (glyph->object)
6266 && XSTRING (glyph->object)->intervals
6267 && glyph->charpos >= 0
6268 && glyph->charpos < XSTRING (glyph->object)->size)
6270 /* If we're on a string with `help-echo' text property,
6271 arrange for the help to be displayed. This is done by
6272 setting the global variable help_echo to the help string. */
6273 help = Fget_text_property (make_number (glyph->charpos),
6274 Qhelp_echo, glyph->object);
6275 if (STRINGP (help))
6276 help_echo = help;
6278 /* Change the mouse pointer according to what is under X/Y. */
6279 map = Fget_text_property (make_number (glyph->charpos),
6280 Qlocal_map, glyph->object);
6281 if (!NILP (Fkeymapp (map)))
6282 cursor = f->output_data.x->nontext_cursor;
6286 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6290 /* Take proper action when the mouse has moved to position X, Y on
6291 frame F as regards highlighting characters that have mouse-face
6292 properties. Also de-highlighting chars where the mouse was before.
6293 X and Y can be negative or out of range. */
6295 static void
6296 note_mouse_highlight (f, x, y)
6297 struct frame *f;
6298 int x, y;
6300 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6301 int portion;
6302 Lisp_Object window;
6303 struct window *w;
6305 /* When a menu is active, don't highlight because this looks odd. */
6306 #ifdef USE_X_TOOLKIT
6307 if (popup_activated ())
6308 return;
6309 #endif
6311 if (disable_mouse_highlight
6312 || !f->glyphs_initialized_p)
6313 return;
6315 dpyinfo->mouse_face_mouse_x = x;
6316 dpyinfo->mouse_face_mouse_y = y;
6317 dpyinfo->mouse_face_mouse_frame = f;
6319 if (dpyinfo->mouse_face_defer)
6320 return;
6322 if (gc_in_progress)
6324 dpyinfo->mouse_face_deferred_gc = 1;
6325 return;
6328 /* Which window is that in? */
6329 window = window_from_coordinates (f, x, y, &portion, 1);
6331 /* If we were displaying active text in another window, clear that. */
6332 if (! EQ (window, dpyinfo->mouse_face_window))
6333 clear_mouse_face (dpyinfo);
6335 /* Not on a window -> return. */
6336 if (!WINDOWP (window))
6337 return;
6339 /* Convert to window-relative pixel coordinates. */
6340 w = XWINDOW (window);
6341 frame_to_window_pixel_xy (w, &x, &y);
6343 /* Handle tool-bar window differently since it doesn't display a
6344 buffer. */
6345 if (EQ (window, f->tool_bar_window))
6347 note_tool_bar_highlight (f, x, y);
6348 return;
6351 if (portion == 1 || portion == 3)
6353 /* Mouse is on the mode or top line. */
6354 note_mode_line_highlight (w, x, portion == 1);
6355 return;
6357 else
6358 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6359 f->output_data.x->text_cursor);
6361 /* Are we in a window whose display is up to date?
6362 And verify the buffer's text has not changed. */
6363 if (/* Within text portion of the window. */
6364 portion == 0
6365 && EQ (w->window_end_valid, w->buffer)
6366 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6367 && (XFASTINT (w->last_overlay_modified)
6368 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6370 int hpos, vpos, pos, i, area;
6371 struct glyph *glyph;
6373 /* Find the glyph under X/Y. */
6374 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6376 /* Clear mouse face if X/Y not over text. */
6377 if (glyph == NULL
6378 || area != TEXT_AREA
6379 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6381 clear_mouse_face (dpyinfo);
6382 return;
6385 pos = glyph->charpos;
6386 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6388 /* Check for mouse-face and help-echo. */
6390 Lisp_Object mouse_face, overlay, position;
6391 Lisp_Object *overlay_vec;
6392 int len, noverlays;
6393 struct buffer *obuf;
6394 int obegv, ozv;
6396 /* If we get an out-of-range value, return now; avoid an error. */
6397 if (pos > BUF_Z (XBUFFER (w->buffer)))
6398 return;
6400 /* Make the window's buffer temporarily current for
6401 overlays_at and compute_char_face. */
6402 obuf = current_buffer;
6403 current_buffer = XBUFFER (w->buffer);
6404 obegv = BEGV;
6405 ozv = ZV;
6406 BEGV = BEG;
6407 ZV = Z;
6409 /* Is this char mouse-active or does it have help-echo? */
6410 XSETINT (position, pos);
6412 /* Put all the overlays we want in a vector in overlay_vec.
6413 Store the length in len. If there are more than 10, make
6414 enough space for all, and try again. */
6415 len = 10;
6416 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6417 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6418 if (noverlays > len)
6420 len = noverlays;
6421 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6422 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6425 noverlays = sort_overlays (overlay_vec, noverlays, w);
6427 /* Check mouse-face highlighting. */
6428 if (! (EQ (window, dpyinfo->mouse_face_window)
6429 && vpos >= dpyinfo->mouse_face_beg_row
6430 && vpos <= dpyinfo->mouse_face_end_row
6431 && (vpos > dpyinfo->mouse_face_beg_row
6432 || hpos >= dpyinfo->mouse_face_beg_col)
6433 && (vpos < dpyinfo->mouse_face_end_row
6434 || hpos < dpyinfo->mouse_face_end_col
6435 || dpyinfo->mouse_face_past_end)))
6437 /* Clear the display of the old active region, if any. */
6438 clear_mouse_face (dpyinfo);
6440 /* Find the highest priority overlay that has a mouse-face prop. */
6441 overlay = Qnil;
6442 for (i = 0; i < noverlays; i++)
6444 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6445 if (!NILP (mouse_face))
6447 overlay = overlay_vec[i];
6448 break;
6452 /* If no overlay applies, get a text property. */
6453 if (NILP (overlay))
6454 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6456 /* Handle the overlay case. */
6457 if (! NILP (overlay))
6459 /* Find the range of text around this char that
6460 should be active. */
6461 Lisp_Object before, after;
6462 int ignore;
6464 before = Foverlay_start (overlay);
6465 after = Foverlay_end (overlay);
6466 /* Record this as the current active region. */
6467 fast_find_position (w, XFASTINT (before),
6468 &dpyinfo->mouse_face_beg_col,
6469 &dpyinfo->mouse_face_beg_row,
6470 &dpyinfo->mouse_face_beg_x,
6471 &dpyinfo->mouse_face_beg_y);
6472 dpyinfo->mouse_face_past_end
6473 = !fast_find_position (w, XFASTINT (after),
6474 &dpyinfo->mouse_face_end_col,
6475 &dpyinfo->mouse_face_end_row,
6476 &dpyinfo->mouse_face_end_x,
6477 &dpyinfo->mouse_face_end_y);
6478 dpyinfo->mouse_face_window = window;
6479 dpyinfo->mouse_face_face_id
6480 = face_at_buffer_position (w, pos, 0, 0,
6481 &ignore, pos + 1, 1);
6483 /* Display it as active. */
6484 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6486 /* Handle the text property case. */
6487 else if (! NILP (mouse_face))
6489 /* Find the range of text around this char that
6490 should be active. */
6491 Lisp_Object before, after, beginning, end;
6492 int ignore;
6494 beginning = Fmarker_position (w->start);
6495 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6496 - XFASTINT (w->window_end_pos)));
6497 before
6498 = Fprevious_single_property_change (make_number (pos + 1),
6499 Qmouse_face,
6500 w->buffer, beginning);
6501 after
6502 = Fnext_single_property_change (position, Qmouse_face,
6503 w->buffer, end);
6504 /* Record this as the current active region. */
6505 fast_find_position (w, XFASTINT (before),
6506 &dpyinfo->mouse_face_beg_col,
6507 &dpyinfo->mouse_face_beg_row,
6508 &dpyinfo->mouse_face_beg_x,
6509 &dpyinfo->mouse_face_beg_y);
6510 dpyinfo->mouse_face_past_end
6511 = !fast_find_position (w, XFASTINT (after),
6512 &dpyinfo->mouse_face_end_col,
6513 &dpyinfo->mouse_face_end_row,
6514 &dpyinfo->mouse_face_end_x,
6515 &dpyinfo->mouse_face_end_y);
6516 dpyinfo->mouse_face_window = window;
6517 dpyinfo->mouse_face_face_id
6518 = face_at_buffer_position (w, pos, 0, 0,
6519 &ignore, pos + 1, 1);
6521 /* Display it as active. */
6522 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6526 /* Look for a `help-echo' property. */
6528 Lisp_Object help;
6530 /* Check overlays first. */
6531 help = Qnil;
6532 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6533 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6535 /* Try text properties. */
6536 if (!STRINGP (help)
6537 && ((STRINGP (glyph->object)
6538 && glyph->charpos >= 0
6539 && glyph->charpos < XSTRING (glyph->object)->size)
6540 || (BUFFERP (glyph->object)
6541 && glyph->charpos >= BEGV
6542 && glyph->charpos < ZV)))
6543 help = Fget_text_property (make_number (glyph->charpos),
6544 Qhelp_echo, glyph->object);
6546 if (STRINGP (help))
6547 help_echo = help;
6550 BEGV = obegv;
6551 ZV = ozv;
6552 current_buffer = obuf;
6557 static void
6558 redo_mouse_highlight ()
6560 if (!NILP (last_mouse_motion_frame)
6561 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6562 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6563 last_mouse_motion_event.x,
6564 last_mouse_motion_event.y);
6569 /***********************************************************************
6570 Tool-bars
6571 ***********************************************************************/
6573 static int x_tool_bar_item P_ ((struct frame *, int, int,
6574 struct glyph **, int *, int *, int *));
6576 /* Tool-bar item index of the item on which a mouse button was pressed
6577 or -1. */
6579 static int last_tool_bar_item;
6582 /* Get information about the tool-bar item at position X/Y on frame F.
6583 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6584 the current matrix of the tool-bar window of F, or NULL if not
6585 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6586 item in F->current_tool_bar_items. Value is
6588 -1 if X/Y is not on a tool-bar item
6589 0 if X/Y is on the same item that was highlighted before.
6590 1 otherwise. */
6592 static int
6593 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6594 struct frame *f;
6595 int x, y;
6596 struct glyph **glyph;
6597 int *hpos, *vpos, *prop_idx;
6599 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6600 struct window *w = XWINDOW (f->tool_bar_window);
6601 int area;
6603 /* Find the glyph under X/Y. */
6604 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6605 if (*glyph == NULL)
6606 return -1;
6608 /* Get the start of this tool-bar item's properties in
6609 f->current_tool_bar_items. */
6610 if (!tool_bar_item_info (f, *glyph, prop_idx))
6611 return -1;
6613 /* Is mouse on the highlighted item? */
6614 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6615 && *vpos >= dpyinfo->mouse_face_beg_row
6616 && *vpos <= dpyinfo->mouse_face_end_row
6617 && (*vpos > dpyinfo->mouse_face_beg_row
6618 || *hpos >= dpyinfo->mouse_face_beg_col)
6619 && (*vpos < dpyinfo->mouse_face_end_row
6620 || *hpos < dpyinfo->mouse_face_end_col
6621 || dpyinfo->mouse_face_past_end))
6622 return 0;
6624 return 1;
6628 /* Handle mouse button event on the tool-bar of frame F, at
6629 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6630 or ButtonRelase. */
6632 static void
6633 x_handle_tool_bar_click (f, button_event)
6634 struct frame *f;
6635 XButtonEvent *button_event;
6637 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6638 struct window *w = XWINDOW (f->tool_bar_window);
6639 int hpos, vpos, prop_idx;
6640 struct glyph *glyph;
6641 Lisp_Object enabled_p;
6642 int x = button_event->x;
6643 int y = button_event->y;
6645 /* If not on the highlighted tool-bar item, return. */
6646 frame_to_window_pixel_xy (w, &x, &y);
6647 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6648 return;
6650 /* If item is disabled, do nothing. */
6651 enabled_p = (XVECTOR (f->current_tool_bar_items)
6652 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6653 if (NILP (enabled_p))
6654 return;
6656 if (button_event->type == ButtonPress)
6658 /* Show item in pressed state. */
6659 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6660 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6661 last_tool_bar_item = prop_idx;
6663 else
6665 Lisp_Object key, frame;
6666 struct input_event event;
6668 /* Show item in released state. */
6669 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6670 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6672 key = (XVECTOR (f->current_tool_bar_items)
6673 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6675 XSETFRAME (frame, f);
6676 event.kind = TOOL_BAR_EVENT;
6677 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6678 kbd_buffer_store_event (&event);
6680 event.kind = TOOL_BAR_EVENT;
6681 event.frame_or_window = Fcons (frame, key);
6682 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6683 button_event->state);
6684 kbd_buffer_store_event (&event);
6685 last_tool_bar_item = -1;
6690 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6691 tool-bar window-relative coordinates X/Y. Called from
6692 note_mouse_highlight. */
6694 static void
6695 note_tool_bar_highlight (f, x, y)
6696 struct frame *f;
6697 int x, y;
6699 Lisp_Object window = f->tool_bar_window;
6700 struct window *w = XWINDOW (window);
6701 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6702 int hpos, vpos;
6703 struct glyph *glyph;
6704 struct glyph_row *row;
6705 int i;
6706 Lisp_Object enabled_p;
6707 int prop_idx;
6708 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6709 int mouse_down_p, rc;
6711 /* Function note_mouse_highlight is called with negative x(y
6712 values when mouse moves outside of the frame. */
6713 if (x <= 0 || y <= 0)
6715 clear_mouse_face (dpyinfo);
6716 return;
6719 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6720 if (rc < 0)
6722 /* Not on tool-bar item. */
6723 clear_mouse_face (dpyinfo);
6724 return;
6726 else if (rc == 0)
6727 /* On same tool-bar item as before. */
6728 goto set_help_echo;
6730 clear_mouse_face (dpyinfo);
6732 /* Mouse is down, but on different tool-bar item? */
6733 mouse_down_p = (dpyinfo->grabbed
6734 && f == last_mouse_frame
6735 && FRAME_LIVE_P (f));
6736 if (mouse_down_p
6737 && last_tool_bar_item != prop_idx)
6738 return;
6740 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6741 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6743 /* If tool-bar item is not enabled, don't highlight it. */
6744 enabled_p = (XVECTOR (f->current_tool_bar_items)
6745 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6746 if (!NILP (enabled_p))
6748 /* Compute the x-position of the glyph. In front and past the
6749 image is a space. We include this is the highlighted area. */
6750 row = MATRIX_ROW (w->current_matrix, vpos);
6751 for (i = x = 0; i < hpos; ++i)
6752 x += row->glyphs[TEXT_AREA][i].pixel_width;
6754 /* Record this as the current active region. */
6755 dpyinfo->mouse_face_beg_col = hpos;
6756 dpyinfo->mouse_face_beg_row = vpos;
6757 dpyinfo->mouse_face_beg_x = x;
6758 dpyinfo->mouse_face_beg_y = row->y;
6759 dpyinfo->mouse_face_past_end = 0;
6761 dpyinfo->mouse_face_end_col = hpos + 1;
6762 dpyinfo->mouse_face_end_row = vpos;
6763 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6764 dpyinfo->mouse_face_end_y = row->y;
6765 dpyinfo->mouse_face_window = window;
6766 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6768 /* Display it as active. */
6769 show_mouse_face (dpyinfo, draw);
6770 dpyinfo->mouse_face_image_state = draw;
6773 set_help_echo:
6775 /* Set help_echo to a help string.to display for this tool-bar item.
6776 XTread_socket does the rest. */
6777 help_echo = (XVECTOR (f->current_tool_bar_items)
6778 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6779 if (!STRINGP (help_echo))
6780 help_echo = (XVECTOR (f->current_tool_bar_items)
6781 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6786 /* Find the glyph matrix position of buffer position POS in window W.
6787 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6788 current glyphs must be up to date. If POS is above window start
6789 return (0, 0, 0, 0). If POS is after end of W, return end of
6790 last line in W. */
6792 static int
6793 fast_find_position (w, pos, hpos, vpos, x, y)
6794 struct window *w;
6795 int pos;
6796 int *hpos, *vpos, *x, *y;
6798 int i;
6799 int lastcol;
6800 int maybe_next_line_p = 0;
6801 int line_start_position;
6802 int yb = window_text_bottom_y (w);
6803 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6804 struct glyph_row *best_row = row;
6805 int row_vpos = 0, best_row_vpos = 0;
6806 int current_x;
6808 while (row->y < yb)
6810 if (row->used[TEXT_AREA])
6811 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6812 else
6813 line_start_position = 0;
6815 if (line_start_position > pos)
6816 break;
6817 /* If the position sought is the end of the buffer,
6818 don't include the blank lines at the bottom of the window. */
6819 else if (line_start_position == pos
6820 && pos == BUF_ZV (XBUFFER (w->buffer)))
6822 maybe_next_line_p = 1;
6823 break;
6825 else if (line_start_position > 0)
6827 best_row = row;
6828 best_row_vpos = row_vpos;
6831 if (row->y + row->height >= yb)
6832 break;
6834 ++row;
6835 ++row_vpos;
6838 /* Find the right column within BEST_ROW. */
6839 lastcol = 0;
6840 current_x = best_row->x;
6841 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6843 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6844 int charpos;
6846 charpos = glyph->charpos;
6847 if (charpos == pos)
6849 *hpos = i;
6850 *vpos = best_row_vpos;
6851 *x = current_x;
6852 *y = best_row->y;
6853 return 1;
6855 else if (charpos > pos)
6856 break;
6857 else if (charpos > 0)
6858 lastcol = i;
6860 current_x += glyph->pixel_width;
6863 /* If we're looking for the end of the buffer,
6864 and we didn't find it in the line we scanned,
6865 use the start of the following line. */
6866 if (maybe_next_line_p)
6868 ++best_row;
6869 ++best_row_vpos;
6870 lastcol = 0;
6871 current_x = best_row->x;
6874 *vpos = best_row_vpos;
6875 *hpos = lastcol + 1;
6876 *x = current_x;
6877 *y = best_row->y;
6878 return 0;
6882 /* Display the active region described by mouse_face_*
6883 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6885 static void
6886 show_mouse_face (dpyinfo, draw)
6887 struct x_display_info *dpyinfo;
6888 enum draw_glyphs_face draw;
6890 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6891 struct frame *f = XFRAME (WINDOW_FRAME (w));
6892 int i;
6893 int cursor_off_p = 0;
6894 struct cursor_pos saved_cursor;
6896 saved_cursor = output_cursor;
6898 /* If window is in the process of being destroyed, don't bother
6899 to do anything. */
6900 if (w->current_matrix == NULL)
6901 goto set_x_cursor;
6903 /* Recognize when we are called to operate on rows that don't exist
6904 anymore. This can happen when a window is split. */
6905 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6906 goto set_x_cursor;
6908 set_output_cursor (&w->phys_cursor);
6910 /* Note that mouse_face_beg_row etc. are window relative. */
6911 for (i = dpyinfo->mouse_face_beg_row;
6912 i <= dpyinfo->mouse_face_end_row;
6913 i++)
6915 int start_hpos, end_hpos, start_x;
6916 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6918 /* Don't do anything if row doesn't have valid contents. */
6919 if (!row->enabled_p)
6920 continue;
6922 /* For all but the first row, the highlight starts at column 0. */
6923 if (i == dpyinfo->mouse_face_beg_row)
6925 start_hpos = dpyinfo->mouse_face_beg_col;
6926 start_x = dpyinfo->mouse_face_beg_x;
6928 else
6930 start_hpos = 0;
6931 start_x = 0;
6934 if (i == dpyinfo->mouse_face_end_row)
6935 end_hpos = dpyinfo->mouse_face_end_col;
6936 else
6937 end_hpos = row->used[TEXT_AREA];
6939 /* If the cursor's in the text we are about to rewrite, turn the
6940 cursor off. */
6941 if (!w->pseudo_window_p
6942 && i == output_cursor.vpos
6943 && output_cursor.hpos >= start_hpos - 1
6944 && output_cursor.hpos <= end_hpos)
6946 x_update_window_cursor (w, 0);
6947 cursor_off_p = 1;
6950 if (end_hpos > start_hpos)
6951 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6952 start_hpos, end_hpos, draw, NULL, NULL, 0);
6955 /* If we turned the cursor off, turn it back on. */
6956 if (cursor_off_p)
6957 x_display_cursor (w, 1,
6958 output_cursor.hpos, output_cursor.vpos,
6959 output_cursor.x, output_cursor.y);
6961 output_cursor = saved_cursor;
6963 set_x_cursor:
6965 /* Change the mouse cursor. */
6966 if (draw == DRAW_NORMAL_TEXT)
6967 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6968 f->output_data.x->text_cursor);
6969 else if (draw == DRAW_MOUSE_FACE)
6970 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6971 f->output_data.x->cross_cursor);
6972 else
6973 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6974 f->output_data.x->nontext_cursor);
6977 /* Clear out the mouse-highlighted active region.
6978 Redraw it un-highlighted first. */
6980 void
6981 clear_mouse_face (dpyinfo)
6982 struct x_display_info *dpyinfo;
6984 if (tip_frame)
6985 return;
6987 if (! NILP (dpyinfo->mouse_face_window))
6988 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6990 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6991 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6992 dpyinfo->mouse_face_window = Qnil;
6995 /* Just discard the mouse face information for frame F, if any.
6996 This is used when the size of F is changed. */
6998 void
6999 cancel_mouse_face (f)
7000 FRAME_PTR f;
7002 Lisp_Object window;
7003 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7005 window = dpyinfo->mouse_face_window;
7006 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7008 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7009 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7010 dpyinfo->mouse_face_window = Qnil;
7014 static struct scroll_bar *x_window_to_scroll_bar ();
7015 static void x_scroll_bar_report_motion ();
7017 /* Return the current position of the mouse.
7018 *fp should be a frame which indicates which display to ask about.
7020 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7021 and *part to the frame, window, and scroll bar part that the mouse
7022 is over. Set *x and *y to the portion and whole of the mouse's
7023 position on the scroll bar.
7025 If the mouse movement started elsewhere, set *fp to the frame the
7026 mouse is on, *bar_window to nil, and *x and *y to the character cell
7027 the mouse is over.
7029 Set *time to the server time-stamp for the time at which the mouse
7030 was at this position.
7032 Don't store anything if we don't have a valid set of values to report.
7034 This clears the mouse_moved flag, so we can wait for the next mouse
7035 movement. */
7037 static void
7038 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7039 FRAME_PTR *fp;
7040 int insist;
7041 Lisp_Object *bar_window;
7042 enum scroll_bar_part *part;
7043 Lisp_Object *x, *y;
7044 unsigned long *time;
7046 FRAME_PTR f1;
7048 BLOCK_INPUT;
7050 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7051 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7052 else
7054 Window root;
7055 int root_x, root_y;
7057 Window dummy_window;
7058 int dummy;
7060 Lisp_Object frame, tail;
7062 /* Clear the mouse-moved flag for every frame on this display. */
7063 FOR_EACH_FRAME (tail, frame)
7064 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7065 XFRAME (frame)->mouse_moved = 0;
7067 last_mouse_scroll_bar = Qnil;
7069 /* Figure out which root window we're on. */
7070 XQueryPointer (FRAME_X_DISPLAY (*fp),
7071 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7073 /* The root window which contains the pointer. */
7074 &root,
7076 /* Trash which we can't trust if the pointer is on
7077 a different screen. */
7078 &dummy_window,
7080 /* The position on that root window. */
7081 &root_x, &root_y,
7083 /* More trash we can't trust. */
7084 &dummy, &dummy,
7086 /* Modifier keys and pointer buttons, about which
7087 we don't care. */
7088 (unsigned int *) &dummy);
7090 /* Now we have a position on the root; find the innermost window
7091 containing the pointer. */
7093 Window win, child;
7094 int win_x, win_y;
7095 int parent_x = 0, parent_y = 0;
7096 int count;
7098 win = root;
7100 /* XTranslateCoordinates can get errors if the window
7101 structure is changing at the same time this function
7102 is running. So at least we must not crash from them. */
7104 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7106 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7107 && FRAME_LIVE_P (last_mouse_frame))
7109 /* If mouse was grabbed on a frame, give coords for that frame
7110 even if the mouse is now outside it. */
7111 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7113 /* From-window, to-window. */
7114 root, FRAME_X_WINDOW (last_mouse_frame),
7116 /* From-position, to-position. */
7117 root_x, root_y, &win_x, &win_y,
7119 /* Child of win. */
7120 &child);
7121 f1 = last_mouse_frame;
7123 else
7125 while (1)
7127 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7129 /* From-window, to-window. */
7130 root, win,
7132 /* From-position, to-position. */
7133 root_x, root_y, &win_x, &win_y,
7135 /* Child of win. */
7136 &child);
7138 if (child == None || child == win)
7139 break;
7141 win = child;
7142 parent_x = win_x;
7143 parent_y = win_y;
7146 /* Now we know that:
7147 win is the innermost window containing the pointer
7148 (XTC says it has no child containing the pointer),
7149 win_x and win_y are the pointer's position in it
7150 (XTC did this the last time through), and
7151 parent_x and parent_y are the pointer's position in win's parent.
7152 (They are what win_x and win_y were when win was child.
7153 If win is the root window, it has no parent, and
7154 parent_{x,y} are invalid, but that's okay, because we'll
7155 never use them in that case.) */
7157 /* Is win one of our frames? */
7158 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7161 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7162 f1 = 0;
7164 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7166 /* If not, is it one of our scroll bars? */
7167 if (! f1)
7169 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7171 if (bar)
7173 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7174 win_x = parent_x;
7175 win_y = parent_y;
7179 if (f1 == 0 && insist > 0)
7180 f1 = SELECTED_FRAME ();
7182 if (f1)
7184 /* Ok, we found a frame. Store all the values.
7185 last_mouse_glyph is a rectangle used to reduce the
7186 generation of mouse events. To not miss any motion
7187 events, we must divide the frame into rectangles of the
7188 size of the smallest character that could be displayed
7189 on it, i.e. into the same rectangles that matrices on
7190 the frame are divided into. */
7192 #if OLD_REDISPLAY_CODE
7193 int ignore1, ignore2;
7194 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7195 &last_mouse_glyph,
7196 FRAME_X_DISPLAY_INFO (f1)->grabbed
7197 || insist);
7198 #else
7200 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7201 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7202 int x = win_x;
7203 int y = win_y;
7205 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7206 round down even for negative values. */
7207 if (x < 0)
7208 x -= width - 1;
7209 if (y < 0)
7210 y -= height - 1;
7212 last_mouse_glyph.width = width;
7213 last_mouse_glyph.height = height;
7214 last_mouse_glyph.x = (x + width - 1) / width * width;
7215 last_mouse_glyph.y = (y + height - 1) / height * height;
7217 #endif
7219 *bar_window = Qnil;
7220 *part = 0;
7221 *fp = f1;
7222 XSETINT (*x, win_x);
7223 XSETINT (*y, win_y);
7224 *time = last_mouse_movement_time;
7229 UNBLOCK_INPUT;
7233 #ifdef USE_X_TOOLKIT
7235 /* Atimer callback function for TIMER. Called every 0.1s to process
7236 Xt timeouts, if needed. We must avoid calling XtAppPending as
7237 much as possible because that function does an implicit XFlush
7238 that slows us down. */
7240 static void
7241 x_process_timeouts (timer)
7242 struct atimer *timer;
7244 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7246 BLOCK_INPUT;
7247 while (XtAppPending (Xt_app_con) & XtIMTimer)
7248 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7249 UNBLOCK_INPUT;
7253 #endif /* USE_X_TOOLKIT */
7256 /* Scroll bar support. */
7258 /* Given an X window ID, find the struct scroll_bar which manages it.
7259 This can be called in GC, so we have to make sure to strip off mark
7260 bits. */
7262 static struct scroll_bar *
7263 x_window_to_scroll_bar (window_id)
7264 Window window_id;
7266 Lisp_Object tail;
7268 for (tail = Vframe_list;
7269 XGCTYPE (tail) == Lisp_Cons;
7270 tail = XCDR (tail))
7272 Lisp_Object frame, bar, condemned;
7274 frame = XCAR (tail);
7275 /* All elements of Vframe_list should be frames. */
7276 if (! GC_FRAMEP (frame))
7277 abort ();
7279 /* Scan this frame's scroll bar list for a scroll bar with the
7280 right window ID. */
7281 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7282 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7283 /* This trick allows us to search both the ordinary and
7284 condemned scroll bar lists with one loop. */
7285 ! GC_NILP (bar) || (bar = condemned,
7286 condemned = Qnil,
7287 ! GC_NILP (bar));
7288 bar = XSCROLL_BAR (bar)->next)
7289 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7290 return XSCROLL_BAR (bar);
7293 return 0;
7298 /************************************************************************
7299 Toolkit scroll bars
7300 ************************************************************************/
7302 #if USE_TOOLKIT_SCROLL_BARS
7304 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7305 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7306 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7307 struct scroll_bar *));
7308 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7309 int, int, int));
7312 /* Id of action hook installed for scroll bars. */
7314 static XtActionHookId action_hook_id;
7316 /* Lisp window being scrolled. Set when starting to interact with
7317 a toolkit scroll bar, reset to nil when ending the interaction. */
7319 static Lisp_Object window_being_scrolled;
7321 /* Last scroll bar part sent in xm_scroll_callback. */
7323 static int last_scroll_bar_part;
7325 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7326 that movements of 1/20 of the screen size are mapped to up/down. */
7328 static Boolean xaw3d_arrow_scroll;
7330 /* Whether the drag scrolling maintains the mouse at the top of the
7331 thumb. If not, resizing the thumb needs to be done more carefully
7332 to avoid jerkyness. */
7334 static Boolean xaw3d_pick_top;
7337 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7338 bars are used.. The hook is responsible for detecting when
7339 the user ends an interaction with the scroll bar, and generates
7340 a `end-scroll' scroll_bar_click' event if so. */
7342 static void
7343 xt_action_hook (widget, client_data, action_name, event, params,
7344 num_params)
7345 Widget widget;
7346 XtPointer client_data;
7347 String action_name;
7348 XEvent *event;
7349 String *params;
7350 Cardinal *num_params;
7352 int scroll_bar_p;
7353 char *end_action;
7355 #ifdef USE_MOTIF
7356 scroll_bar_p = XmIsScrollBar (widget);
7357 end_action = "Release";
7358 #else /* !USE_MOTIF i.e. use Xaw */
7359 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7360 end_action = "EndScroll";
7361 #endif /* USE_MOTIF */
7363 if (scroll_bar_p
7364 && strcmp (action_name, end_action) == 0
7365 && WINDOWP (window_being_scrolled))
7367 struct window *w;
7369 x_send_scroll_bar_event (window_being_scrolled,
7370 scroll_bar_end_scroll, 0, 0);
7371 w = XWINDOW (window_being_scrolled);
7372 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7373 window_being_scrolled = Qnil;
7374 last_scroll_bar_part = -1;
7376 /* Xt timeouts no longer needed. */
7377 toolkit_scroll_bar_interaction = 0;
7382 /* Send a client message with message type Xatom_Scrollbar for a
7383 scroll action to the frame of WINDOW. PART is a value identifying
7384 the part of the scroll bar that was clicked on. PORTION is the
7385 amount to scroll of a whole of WHOLE. */
7387 static void
7388 x_send_scroll_bar_event (window, part, portion, whole)
7389 Lisp_Object window;
7390 int part, portion, whole;
7392 XEvent event;
7393 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7394 struct frame *f = XFRAME (XWINDOW (window)->frame);
7396 /* Construct a ClientMessage event to send to the frame. */
7397 ev->type = ClientMessage;
7398 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7399 ev->display = FRAME_X_DISPLAY (f);
7400 ev->window = FRAME_X_WINDOW (f);
7401 ev->format = 32;
7402 ev->data.l[0] = (long) window;
7403 ev->data.l[1] = (long) part;
7404 ev->data.l[2] = (long) 0;
7405 ev->data.l[3] = (long) portion;
7406 ev->data.l[4] = (long) whole;
7408 /* Make Xt timeouts work while the scroll bar is active. */
7409 toolkit_scroll_bar_interaction = 1;
7411 /* Setting the event mask to zero means that the message will
7412 be sent to the client that created the window, and if that
7413 window no longer exists, no event will be sent. */
7414 BLOCK_INPUT;
7415 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7416 UNBLOCK_INPUT;
7420 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7421 in *IEVENT. */
7423 static void
7424 x_scroll_bar_to_input_event (event, ievent)
7425 XEvent *event;
7426 struct input_event *ievent;
7428 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7429 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7430 struct frame *f = XFRAME (XWINDOW (window)->frame);
7432 ievent->kind = scroll_bar_click;
7433 ievent->frame_or_window = window;
7434 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7435 ievent->part = ev->data.l[1];
7436 ievent->code = ev->data.l[2];
7437 ievent->x = make_number ((int) ev->data.l[3]);
7438 ievent->y = make_number ((int) ev->data.l[4]);
7439 ievent->modifiers = 0;
7443 #ifdef USE_MOTIF
7445 /* Minimum and maximum values used for Motif scroll bars. */
7447 #define XM_SB_MIN 1
7448 #define XM_SB_MAX 10000000
7449 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7452 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7453 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7454 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7456 static void
7457 xm_scroll_callback (widget, client_data, call_data)
7458 Widget widget;
7459 XtPointer client_data, call_data;
7461 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7462 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7463 double percent;
7464 int part = -1, whole = 0, portion = 0;
7466 switch (cs->reason)
7468 case XmCR_DECREMENT:
7469 bar->dragging = Qnil;
7470 part = scroll_bar_up_arrow;
7471 break;
7473 case XmCR_INCREMENT:
7474 bar->dragging = Qnil;
7475 part = scroll_bar_down_arrow;
7476 break;
7478 case XmCR_PAGE_DECREMENT:
7479 bar->dragging = Qnil;
7480 part = scroll_bar_above_handle;
7481 break;
7483 case XmCR_PAGE_INCREMENT:
7484 bar->dragging = Qnil;
7485 part = scroll_bar_below_handle;
7486 break;
7488 case XmCR_TO_TOP:
7489 bar->dragging = Qnil;
7490 part = scroll_bar_to_top;
7491 break;
7493 case XmCR_TO_BOTTOM:
7494 bar->dragging = Qnil;
7495 part = scroll_bar_to_bottom;
7496 break;
7498 case XmCR_DRAG:
7500 int slider_size;
7501 int dragging_down_p = (INTEGERP (bar->dragging)
7502 && XINT (bar->dragging) <= cs->value);
7504 /* Get the slider size. */
7505 BLOCK_INPUT;
7506 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7507 UNBLOCK_INPUT;
7509 /* At the max position of the scroll bar, do a line-wise
7510 movement. Without doing anything, the LessTif scroll bar
7511 calls us with the same cs->value again and again. If we
7512 want to make sure that we can reach the end of the buffer,
7513 we have to do something.
7515 Implementation note: setting bar->dragging always to
7516 cs->value gives a smoother movement at the max position.
7517 Setting it to nil when doing line-wise movement gives
7518 a better slider behavior. */
7520 if (cs->value + slider_size == XM_SB_MAX
7521 || (dragging_down_p
7522 && last_scroll_bar_part == scroll_bar_down_arrow))
7524 part = scroll_bar_down_arrow;
7525 bar->dragging = Qnil;
7527 else
7529 whole = XM_SB_RANGE;
7530 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7531 part = scroll_bar_handle;
7532 bar->dragging = make_number (cs->value);
7535 break;
7537 case XmCR_VALUE_CHANGED:
7538 break;
7541 if (part >= 0)
7543 window_being_scrolled = bar->window;
7544 last_scroll_bar_part = part;
7545 x_send_scroll_bar_event (bar->window, part, portion, whole);
7550 #else /* !USE_MOTIF, i.e. Xaw. */
7553 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7554 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7555 scroll bar struct. CALL_DATA is a pointer to a float saying where
7556 the thumb is. */
7558 static void
7559 xaw_jump_callback (widget, client_data, call_data)
7560 Widget widget;
7561 XtPointer client_data, call_data;
7563 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7564 float top = *(float *) call_data;
7565 float shown;
7566 int whole, portion, height;
7567 int part;
7569 /* Get the size of the thumb, a value between 0 and 1. */
7570 BLOCK_INPUT;
7571 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7572 UNBLOCK_INPUT;
7574 whole = 10000000;
7575 portion = shown < 1 ? top * whole : 0;
7577 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7578 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7579 the bottom, so we force the scrolling whenever we see that we're
7580 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7581 we try to ensure that we always stay two pixels away from the
7582 bottom). */
7583 part = scroll_bar_down_arrow;
7584 else
7585 part = scroll_bar_handle;
7587 window_being_scrolled = bar->window;
7588 bar->dragging = make_number (portion);
7589 last_scroll_bar_part = part;
7590 x_send_scroll_bar_event (bar->window, part, portion, whole);
7594 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7595 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7596 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7597 the scroll bar. CALL_DATA is an integer specifying the action that
7598 has taken place. It's magnitude is in the range 0..height of the
7599 scroll bar. Negative values mean scroll towards buffer start.
7600 Values < height of scroll bar mean line-wise movement. */
7602 static void
7603 xaw_scroll_callback (widget, client_data, call_data)
7604 Widget widget;
7605 XtPointer client_data, call_data;
7607 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7608 int position = (int) call_data;
7609 Dimension height;
7610 int part;
7612 /* Get the height of the scroll bar. */
7613 BLOCK_INPUT;
7614 XtVaGetValues (widget, XtNheight, &height, NULL);
7615 UNBLOCK_INPUT;
7617 if (abs (position) >= height)
7618 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7620 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7621 it maps line-movement to call_data = max(5, height/20). */
7622 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7623 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7624 else
7625 part = scroll_bar_move_ratio;
7627 window_being_scrolled = bar->window;
7628 bar->dragging = Qnil;
7629 last_scroll_bar_part = part;
7630 x_send_scroll_bar_event (bar->window, part, position, height);
7634 #endif /* not USE_MOTIF */
7637 /* Create the widget for scroll bar BAR on frame F. Record the widget
7638 and X window of the scroll bar in BAR. */
7640 static void
7641 x_create_toolkit_scroll_bar (f, bar)
7642 struct frame *f;
7643 struct scroll_bar *bar;
7645 Window xwindow;
7646 Widget widget;
7647 Arg av[20];
7648 int ac = 0;
7649 char *scroll_bar_name = "verticalScrollBar";
7650 unsigned long pixel;
7652 BLOCK_INPUT;
7654 #ifdef USE_MOTIF
7655 /* LessTif 0.85, problems:
7657 1. When the mouse if over the scroll bar, the scroll bar will
7658 get keyboard events. I didn't find a way to turn this off.
7660 2. Do we have to explicitly set the cursor to get an arrow
7661 cursor (see below)? */
7663 /* Set resources. Create the widget. */
7664 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7665 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7666 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7667 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7668 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7669 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7670 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7672 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7673 if (pixel != -1)
7675 XtSetArg (av[ac], XmNforeground, pixel);
7676 ++ac;
7679 pixel = f->output_data.x->scroll_bar_background_pixel;
7680 if (pixel != -1)
7682 XtSetArg (av[ac], XmNbackground, pixel);
7683 ++ac;
7686 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7687 scroll_bar_name, av, ac);
7689 /* Add one callback for everything that can happen. */
7690 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7691 (XtPointer) bar);
7692 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7693 (XtPointer) bar);
7694 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7695 (XtPointer) bar);
7696 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7697 (XtPointer) bar);
7698 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7699 (XtPointer) bar);
7700 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7701 (XtPointer) bar);
7702 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7703 (XtPointer) bar);
7705 /* Realize the widget. Only after that is the X window created. */
7706 XtRealizeWidget (widget);
7708 /* Set the cursor to an arrow. I didn't find a resource to do that.
7709 And I'm wondering why it hasn't an arrow cursor by default. */
7710 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7711 f->output_data.x->nontext_cursor);
7713 #else /* !USE_MOTIF i.e. use Xaw */
7715 /* Set resources. Create the widget. The background of the
7716 Xaw3d scroll bar widget is a little bit light for my taste.
7717 We don't alter it here to let users change it according
7718 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7719 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7720 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7721 /* For smoother scrolling with Xaw3d -sm */
7722 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7723 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7725 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7726 if (pixel != -1)
7728 XtSetArg (av[ac], XtNforeground, pixel);
7729 ++ac;
7732 pixel = f->output_data.x->scroll_bar_background_pixel;
7733 if (pixel != -1)
7735 XtSetArg (av[ac], XtNbackground, pixel);
7736 ++ac;
7739 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7740 f->output_data.x->edit_widget, av, ac);
7743 char *initial = "";
7744 char *val = initial;
7745 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7746 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7747 if (val == initial)
7748 { /* ARROW_SCROLL */
7749 xaw3d_arrow_scroll = True;
7750 /* Isn't that just a personal preference ? -sm */
7751 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7755 /* Define callbacks. */
7756 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7757 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
7758 (XtPointer) bar);
7760 /* Realize the widget. Only after that is the X window created. */
7761 XtRealizeWidget (widget);
7763 #endif /* !USE_MOTIF */
7765 /* Install an action hook that let's us detect when the user
7766 finishes interacting with a scroll bar. */
7767 if (action_hook_id == 0)
7768 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7770 /* Remember X window and widget in the scroll bar vector. */
7771 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7772 xwindow = XtWindow (widget);
7773 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7775 UNBLOCK_INPUT;
7779 /* Set the thumb size and position of scroll bar BAR. We are currently
7780 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7782 static void
7783 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7784 struct scroll_bar *bar;
7785 int portion, position, whole;
7787 float top, shown;
7788 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7790 if (whole == 0)
7791 top = 0, shown = 1;
7792 else
7794 top = (float) position / whole;
7795 shown = (float) portion / whole;
7798 BLOCK_INPUT;
7800 #ifdef USE_MOTIF
7802 int size, value;
7803 Boolean arrow1_selected, arrow2_selected;
7804 unsigned char flags;
7805 XmScrollBarWidget sb;
7807 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7808 is the scroll bar's maximum and MIN is the scroll bar's minimum
7809 value. */
7810 size = shown * XM_SB_RANGE;
7811 size = min (size, XM_SB_RANGE);
7812 size = max (size, 1);
7814 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7815 value = top * XM_SB_RANGE;
7816 value = min (value, XM_SB_MAX - size);
7817 value = max (value, XM_SB_MIN);
7819 /* LessTif: Calling XmScrollBarSetValues after an increment or
7820 decrement turns off auto-repeat LessTif-internally. This can
7821 be seen in ScrollBar.c which resets Arrow1Selected and
7822 Arrow2Selected. It also sets internal flags so that LessTif
7823 believes the mouse is in the slider. We either have to change
7824 our code, or work around that by accessing private data. */
7826 sb = (XmScrollBarWidget) widget;
7827 arrow1_selected = sb->scrollBar.arrow1_selected;
7828 arrow2_selected = sb->scrollBar.arrow2_selected;
7829 flags = sb->scrollBar.flags;
7831 if (NILP (bar->dragging))
7832 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7833 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7834 /* This has the negative side effect that the slider value is
7835 not what it would be if we scrolled here using line-wise or
7836 page-wise movement. */
7837 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7838 else
7840 /* If currently dragging, only update the slider size.
7841 This reduces flicker effects. */
7842 int old_value, old_size, increment, page_increment;
7844 XmScrollBarGetValues (widget, &old_value, &old_size,
7845 &increment, &page_increment);
7846 XmScrollBarSetValues (widget, old_value,
7847 min (size, XM_SB_RANGE - old_value),
7848 0, 0, False);
7851 sb->scrollBar.arrow1_selected = arrow1_selected;
7852 sb->scrollBar.arrow2_selected = arrow2_selected;
7853 sb->scrollBar.flags = flags;
7855 #else /* !USE_MOTIF i.e. use Xaw */
7857 float old_top, old_shown;
7858 Dimension height;
7859 XtVaGetValues (widget,
7860 XtNtopOfThumb, &old_top,
7861 XtNshown, &old_shown,
7862 XtNheight, &height,
7863 NULL);
7865 /* Massage the top+shown values. */
7866 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7867 top = max (0, min (1, top));
7868 else
7869 top = old_top;
7870 /* Keep two pixels available for moving the thumb down. */
7871 shown = max (0, min (1 - top - (2.0 / height), shown));
7873 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7874 check that your system's configuration file contains a define
7875 for `NARROWPROTO'. See s/freebsd.h for an example. */
7876 if (top != old_top || shown != old_shown)
7878 if (NILP (bar->dragging))
7879 XawScrollbarSetThumb (widget, top, shown);
7880 else
7882 #ifdef HAVE_XAW3D
7883 ScrollbarWidget sb = (ScrollbarWidget) widget;
7884 int scroll_mode;
7886 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7887 if (xaw3d_arrow_scroll)
7889 /* Xaw3d stupidly ignores resize requests while dragging
7890 so we have to make it believe it's not in dragging mode. */
7891 scroll_mode = sb->scrollbar.scroll_mode;
7892 if (scroll_mode == 2)
7893 sb->scrollbar.scroll_mode = 0;
7895 #endif
7896 /* Try to make the scrolling a tad smoother. */
7897 if (!xaw3d_pick_top)
7898 shown = min (shown, old_shown);
7900 XawScrollbarSetThumb (widget, top, shown);
7902 #ifdef HAVE_XAW3D
7903 if (xaw3d_arrow_scroll && scroll_mode == 2)
7904 sb->scrollbar.scroll_mode = scroll_mode;
7905 #endif
7909 #endif /* !USE_MOTIF */
7911 UNBLOCK_INPUT;
7914 #endif /* USE_TOOLKIT_SCROLL_BARS */
7918 /************************************************************************
7919 Scroll bars, general
7920 ************************************************************************/
7922 /* Create a scroll bar and return the scroll bar vector for it. W is
7923 the Emacs window on which to create the scroll bar. TOP, LEFT,
7924 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7925 scroll bar. */
7927 static struct scroll_bar *
7928 x_scroll_bar_create (w, top, left, width, height)
7929 struct window *w;
7930 int top, left, width, height;
7932 struct frame *f = XFRAME (w->frame);
7933 struct scroll_bar *bar
7934 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7936 BLOCK_INPUT;
7938 #if USE_TOOLKIT_SCROLL_BARS
7939 x_create_toolkit_scroll_bar (f, bar);
7940 #else /* not USE_TOOLKIT_SCROLL_BARS */
7942 XSetWindowAttributes a;
7943 unsigned long mask;
7944 Window window;
7946 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7947 if (a.background_pixel == -1)
7948 a.background_pixel = f->output_data.x->background_pixel;
7950 a.event_mask = (ButtonPressMask | ButtonReleaseMask
7951 | ButtonMotionMask | PointerMotionHintMask
7952 | ExposureMask);
7953 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
7955 mask = (CWBackPixel | CWEventMask | CWCursor);
7957 /* Clear the area of W that will serve as a scroll bar. This is
7958 for the case that a window has been split horizontally. In
7959 this case, no clear_frame is generated to reduce flickering. */
7960 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7961 left, top, width,
7962 window_box_height (w), False);
7964 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7965 /* Position and size of scroll bar. */
7966 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7967 top,
7968 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7969 height,
7970 /* Border width, depth, class, and visual. */
7972 CopyFromParent,
7973 CopyFromParent,
7974 CopyFromParent,
7975 /* Attributes. */
7976 mask, &a);
7977 SET_SCROLL_BAR_X_WINDOW (bar, window);
7979 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7981 XSETWINDOW (bar->window, w);
7982 XSETINT (bar->top, top);
7983 XSETINT (bar->left, left);
7984 XSETINT (bar->width, width);
7985 XSETINT (bar->height, height);
7986 XSETINT (bar->start, 0);
7987 XSETINT (bar->end, 0);
7988 bar->dragging = Qnil;
7990 /* Add bar to its frame's list of scroll bars. */
7991 bar->next = FRAME_SCROLL_BARS (f);
7992 bar->prev = Qnil;
7993 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7994 if (!NILP (bar->next))
7995 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7997 /* Map the window/widget. */
7998 #if USE_TOOLKIT_SCROLL_BARS
7999 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8000 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8001 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8002 top,
8003 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8004 height, 0);
8005 #else /* not USE_TOOLKIT_SCROLL_BARS */
8006 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8007 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8009 UNBLOCK_INPUT;
8010 return bar;
8014 /* Draw BAR's handle in the proper position.
8016 If the handle is already drawn from START to END, don't bother
8017 redrawing it, unless REBUILD is non-zero; in that case, always
8018 redraw it. (REBUILD is handy for drawing the handle after expose
8019 events.)
8021 Normally, we want to constrain the start and end of the handle to
8022 fit inside its rectangle, but if the user is dragging the scroll
8023 bar handle, we want to let them drag it down all the way, so that
8024 the bar's top is as far down as it goes; otherwise, there's no way
8025 to move to the very end of the buffer. */
8027 #ifndef USE_TOOLKIT_SCROLL_BARS
8029 static void
8030 x_scroll_bar_set_handle (bar, start, end, rebuild)
8031 struct scroll_bar *bar;
8032 int start, end;
8033 int rebuild;
8035 int dragging = ! NILP (bar->dragging);
8036 Window w = SCROLL_BAR_X_WINDOW (bar);
8037 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8038 GC gc = f->output_data.x->normal_gc;
8040 /* If the display is already accurate, do nothing. */
8041 if (! rebuild
8042 && start == XINT (bar->start)
8043 && end == XINT (bar->end))
8044 return;
8046 BLOCK_INPUT;
8049 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8050 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8051 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8053 /* Make sure the values are reasonable, and try to preserve
8054 the distance between start and end. */
8056 int length = end - start;
8058 if (start < 0)
8059 start = 0;
8060 else if (start > top_range)
8061 start = top_range;
8062 end = start + length;
8064 if (end < start)
8065 end = start;
8066 else if (end > top_range && ! dragging)
8067 end = top_range;
8070 /* Store the adjusted setting in the scroll bar. */
8071 XSETINT (bar->start, start);
8072 XSETINT (bar->end, end);
8074 /* Clip the end position, just for display. */
8075 if (end > top_range)
8076 end = top_range;
8078 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8079 below top positions, to make sure the handle is always at least
8080 that many pixels tall. */
8081 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8083 /* Draw the empty space above the handle. Note that we can't clear
8084 zero-height areas; that means "clear to end of window." */
8085 if (0 < start)
8086 XClearArea (FRAME_X_DISPLAY (f), w,
8088 /* x, y, width, height, and exposures. */
8089 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8090 VERTICAL_SCROLL_BAR_TOP_BORDER,
8091 inside_width, start,
8092 False);
8094 /* Change to proper foreground color if one is specified. */
8095 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8096 XSetForeground (FRAME_X_DISPLAY (f), gc,
8097 f->output_data.x->scroll_bar_foreground_pixel);
8099 /* Draw the handle itself. */
8100 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8102 /* x, y, width, height */
8103 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8104 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8105 inside_width, end - start);
8107 /* Restore the foreground color of the GC if we changed it above. */
8108 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8109 XSetForeground (FRAME_X_DISPLAY (f), gc,
8110 f->output_data.x->foreground_pixel);
8112 /* Draw the empty space below the handle. Note that we can't
8113 clear zero-height areas; that means "clear to end of window." */
8114 if (end < inside_height)
8115 XClearArea (FRAME_X_DISPLAY (f), w,
8117 /* x, y, width, height, and exposures. */
8118 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8119 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8120 inside_width, inside_height - end,
8121 False);
8125 UNBLOCK_INPUT;
8128 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8130 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8131 nil. */
8133 static void
8134 x_scroll_bar_remove (bar)
8135 struct scroll_bar *bar;
8137 BLOCK_INPUT;
8139 #if USE_TOOLKIT_SCROLL_BARS
8140 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8141 #else /* not USE_TOOLKIT_SCROLL_BARS */
8143 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8144 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8146 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8148 /* Disassociate this scroll bar from its window. */
8149 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8151 UNBLOCK_INPUT;
8155 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8156 that we are displaying PORTION characters out of a total of WHOLE
8157 characters, starting at POSITION. If WINDOW has no scroll bar,
8158 create one. */
8160 static void
8161 XTset_vertical_scroll_bar (w, portion, whole, position)
8162 struct window *w;
8163 int portion, whole, position;
8165 struct frame *f = XFRAME (w->frame);
8166 struct scroll_bar *bar;
8167 int top, height, left, sb_left, width, sb_width;
8168 int window_x, window_y, window_width, window_height;
8170 /* Get window dimensions. */
8171 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8172 top = window_y;
8173 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8174 height = window_height;
8176 /* Compute the left edge of the scroll bar area. */
8177 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8178 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8179 else
8180 left = XFASTINT (w->left);
8181 left *= CANON_X_UNIT (f);
8182 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8184 /* Compute the width of the scroll bar which might be less than
8185 the width of the area reserved for the scroll bar. */
8186 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8187 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8188 else
8189 sb_width = width;
8191 /* Compute the left edge of the scroll bar. */
8192 #ifdef USE_TOOLKIT_SCROLL_BARS
8193 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8194 sb_left = left + width - sb_width - (width - sb_width) / 2;
8195 else
8196 sb_left = left + (width - sb_width) / 2;
8197 #else
8198 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8199 sb_left = left + width - sb_width;
8200 else
8201 sb_left = left;
8202 #endif
8204 /* Does the scroll bar exist yet? */
8205 if (NILP (w->vertical_scroll_bar))
8207 BLOCK_INPUT;
8208 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8209 left, top, width, height, False);
8210 UNBLOCK_INPUT;
8211 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8213 else
8215 /* It may just need to be moved and resized. */
8216 unsigned int mask = 0;
8218 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8220 BLOCK_INPUT;
8222 if (sb_left != XINT (bar->left))
8223 mask |= CWX;
8224 if (top != XINT (bar->top))
8225 mask |= CWY;
8226 if (sb_width != XINT (bar->width))
8227 mask |= CWWidth;
8228 if (height != XINT (bar->height))
8229 mask |= CWHeight;
8231 #ifdef USE_TOOLKIT_SCROLL_BARS
8233 /* Since toolkit scroll bars are smaller than the space reserved
8234 for them on the frame, we have to clear "under" them. */
8235 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8236 left, top, width, height, False);
8238 /* Move/size the scroll bar widget. */
8239 if (mask)
8240 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8241 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8242 top,
8243 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8244 height, 0);
8246 #else /* not USE_TOOLKIT_SCROLL_BARS */
8248 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8250 /* Clear areas not covered by the scroll bar. This makes sure a
8251 previous mode line display is cleared after C-x 2 C-x 1, for
8252 example. Non-toolkit scroll bars are as wide as the area
8253 reserved for scroll bars - trim at both sides. */
8254 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8255 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8256 height, False);
8257 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8258 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8259 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8260 height, False);
8263 /* Move/size the scroll bar window. */
8264 if (mask)
8266 XWindowChanges wc;
8268 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8269 wc.y = top;
8270 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8271 wc.height = height;
8272 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8273 mask, &wc);
8276 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8278 /* Remember new settings. */
8279 XSETINT (bar->left, sb_left);
8280 XSETINT (bar->top, top);
8281 XSETINT (bar->width, sb_width);
8282 XSETINT (bar->height, height);
8284 UNBLOCK_INPUT;
8287 #if USE_TOOLKIT_SCROLL_BARS
8288 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8289 #else /* not USE_TOOLKIT_SCROLL_BARS */
8290 /* Set the scroll bar's current state, unless we're currently being
8291 dragged. */
8292 if (NILP (bar->dragging))
8294 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8296 if (whole == 0)
8297 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8298 else
8300 int start = ((double) position * top_range) / whole;
8301 int end = ((double) (position + portion) * top_range) / whole;
8302 x_scroll_bar_set_handle (bar, start, end, 0);
8305 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8307 XSETVECTOR (w->vertical_scroll_bar, bar);
8311 /* The following three hooks are used when we're doing a thorough
8312 redisplay of the frame. We don't explicitly know which scroll bars
8313 are going to be deleted, because keeping track of when windows go
8314 away is a real pain - "Can you say set-window-configuration, boys
8315 and girls?" Instead, we just assert at the beginning of redisplay
8316 that *all* scroll bars are to be removed, and then save a scroll bar
8317 from the fiery pit when we actually redisplay its window. */
8319 /* Arrange for all scroll bars on FRAME to be removed at the next call
8320 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8321 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8323 static void
8324 XTcondemn_scroll_bars (frame)
8325 FRAME_PTR frame;
8327 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8328 while (! NILP (FRAME_SCROLL_BARS (frame)))
8330 Lisp_Object bar;
8331 bar = FRAME_SCROLL_BARS (frame);
8332 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8333 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8334 XSCROLL_BAR (bar)->prev = Qnil;
8335 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8336 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8337 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8341 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8342 Note that WINDOW isn't necessarily condemned at all. */
8343 static void
8344 XTredeem_scroll_bar (window)
8345 struct window *window;
8347 struct scroll_bar *bar;
8349 /* We can't redeem this window's scroll bar if it doesn't have one. */
8350 if (NILP (window->vertical_scroll_bar))
8351 abort ();
8353 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8355 /* Unlink it from the condemned list. */
8357 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8359 if (NILP (bar->prev))
8361 /* If the prev pointer is nil, it must be the first in one of
8362 the lists. */
8363 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8364 /* It's not condemned. Everything's fine. */
8365 return;
8366 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8367 window->vertical_scroll_bar))
8368 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8369 else
8370 /* If its prev pointer is nil, it must be at the front of
8371 one or the other! */
8372 abort ();
8374 else
8375 XSCROLL_BAR (bar->prev)->next = bar->next;
8377 if (! NILP (bar->next))
8378 XSCROLL_BAR (bar->next)->prev = bar->prev;
8380 bar->next = FRAME_SCROLL_BARS (f);
8381 bar->prev = Qnil;
8382 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8383 if (! NILP (bar->next))
8384 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8388 /* Remove all scroll bars on FRAME that haven't been saved since the
8389 last call to `*condemn_scroll_bars_hook'. */
8391 static void
8392 XTjudge_scroll_bars (f)
8393 FRAME_PTR f;
8395 Lisp_Object bar, next;
8397 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8399 /* Clear out the condemned list now so we won't try to process any
8400 more events on the hapless scroll bars. */
8401 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8403 for (; ! NILP (bar); bar = next)
8405 struct scroll_bar *b = XSCROLL_BAR (bar);
8407 x_scroll_bar_remove (b);
8409 next = b->next;
8410 b->next = b->prev = Qnil;
8413 /* Now there should be no references to the condemned scroll bars,
8414 and they should get garbage-collected. */
8418 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8419 is a no-op when using toolkit scroll bars.
8421 This may be called from a signal handler, so we have to ignore GC
8422 mark bits. */
8424 static void
8425 x_scroll_bar_expose (bar, event)
8426 struct scroll_bar *bar;
8427 XEvent *event;
8429 #ifndef USE_TOOLKIT_SCROLL_BARS
8431 Window w = SCROLL_BAR_X_WINDOW (bar);
8432 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8433 GC gc = f->output_data.x->normal_gc;
8434 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8436 BLOCK_INPUT;
8438 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8440 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8441 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8443 /* x, y, width, height */
8444 0, 0,
8445 XINT (bar->width) - 1 - width_trim - width_trim,
8446 XINT (bar->height) - 1);
8448 UNBLOCK_INPUT;
8450 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8453 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8454 is set to something other than no_event, it is enqueued.
8456 This may be called from a signal handler, so we have to ignore GC
8457 mark bits. */
8459 #ifndef USE_TOOLKIT_SCROLL_BARS
8461 static void
8462 x_scroll_bar_handle_click (bar, event, emacs_event)
8463 struct scroll_bar *bar;
8464 XEvent *event;
8465 struct input_event *emacs_event;
8467 if (! GC_WINDOWP (bar->window))
8468 abort ();
8470 emacs_event->kind = scroll_bar_click;
8471 emacs_event->code = event->xbutton.button - Button1;
8472 emacs_event->modifiers
8473 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8474 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8475 event->xbutton.state)
8476 | (event->type == ButtonRelease
8477 ? up_modifier
8478 : down_modifier));
8479 emacs_event->frame_or_window = bar->window;
8480 emacs_event->timestamp = event->xbutton.time;
8482 #if 0
8483 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8484 int internal_height
8485 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8486 #endif
8487 int top_range
8488 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8489 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8491 if (y < 0) y = 0;
8492 if (y > top_range) y = top_range;
8494 if (y < XINT (bar->start))
8495 emacs_event->part = scroll_bar_above_handle;
8496 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8497 emacs_event->part = scroll_bar_handle;
8498 else
8499 emacs_event->part = scroll_bar_below_handle;
8501 /* Just because the user has clicked on the handle doesn't mean
8502 they want to drag it. Lisp code needs to be able to decide
8503 whether or not we're dragging. */
8504 #if 0
8505 /* If the user has just clicked on the handle, record where they're
8506 holding it. */
8507 if (event->type == ButtonPress
8508 && emacs_event->part == scroll_bar_handle)
8509 XSETINT (bar->dragging, y - XINT (bar->start));
8510 #endif
8512 /* If the user has released the handle, set it to its final position. */
8513 if (event->type == ButtonRelease
8514 && ! NILP (bar->dragging))
8516 int new_start = y - XINT (bar->dragging);
8517 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8519 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8520 bar->dragging = Qnil;
8523 /* Same deal here as the other #if 0. */
8524 #if 0
8525 /* Clicks on the handle are always reported as occurring at the top of
8526 the handle. */
8527 if (emacs_event->part == scroll_bar_handle)
8528 emacs_event->x = bar->start;
8529 else
8530 XSETINT (emacs_event->x, y);
8531 #else
8532 XSETINT (emacs_event->x, y);
8533 #endif
8535 XSETINT (emacs_event->y, top_range);
8539 /* Handle some mouse motion while someone is dragging the scroll bar.
8541 This may be called from a signal handler, so we have to ignore GC
8542 mark bits. */
8544 static void
8545 x_scroll_bar_note_movement (bar, event)
8546 struct scroll_bar *bar;
8547 XEvent *event;
8549 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8551 last_mouse_movement_time = event->xmotion.time;
8553 f->mouse_moved = 1;
8554 XSETVECTOR (last_mouse_scroll_bar, bar);
8556 /* If we're dragging the bar, display it. */
8557 if (! GC_NILP (bar->dragging))
8559 /* Where should the handle be now? */
8560 int new_start = event->xmotion.y - XINT (bar->dragging);
8562 if (new_start != XINT (bar->start))
8564 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8566 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8571 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8573 /* Return information to the user about the current position of the mouse
8574 on the scroll bar. */
8576 static void
8577 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8578 FRAME_PTR *fp;
8579 Lisp_Object *bar_window;
8580 enum scroll_bar_part *part;
8581 Lisp_Object *x, *y;
8582 unsigned long *time;
8584 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8585 Window w = SCROLL_BAR_X_WINDOW (bar);
8586 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8587 int win_x, win_y;
8588 Window dummy_window;
8589 int dummy_coord;
8590 unsigned int dummy_mask;
8592 BLOCK_INPUT;
8594 /* Get the mouse's position relative to the scroll bar window, and
8595 report that. */
8596 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8598 /* Root, child, root x and root y. */
8599 &dummy_window, &dummy_window,
8600 &dummy_coord, &dummy_coord,
8602 /* Position relative to scroll bar. */
8603 &win_x, &win_y,
8605 /* Mouse buttons and modifier keys. */
8606 &dummy_mask))
8608 else
8610 #if 0
8611 int inside_height
8612 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8613 #endif
8614 int top_range
8615 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8617 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8619 if (! NILP (bar->dragging))
8620 win_y -= XINT (bar->dragging);
8622 if (win_y < 0)
8623 win_y = 0;
8624 if (win_y > top_range)
8625 win_y = top_range;
8627 *fp = f;
8628 *bar_window = bar->window;
8630 if (! NILP (bar->dragging))
8631 *part = scroll_bar_handle;
8632 else if (win_y < XINT (bar->start))
8633 *part = scroll_bar_above_handle;
8634 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8635 *part = scroll_bar_handle;
8636 else
8637 *part = scroll_bar_below_handle;
8639 XSETINT (*x, win_y);
8640 XSETINT (*y, top_range);
8642 f->mouse_moved = 0;
8643 last_mouse_scroll_bar = Qnil;
8646 *time = last_mouse_movement_time;
8648 UNBLOCK_INPUT;
8652 /* The screen has been cleared so we may have changed foreground or
8653 background colors, and the scroll bars may need to be redrawn.
8654 Clear out the scroll bars, and ask for expose events, so we can
8655 redraw them. */
8657 void
8658 x_scroll_bar_clear (f)
8659 FRAME_PTR f;
8661 #ifndef USE_TOOLKIT_SCROLL_BARS
8662 Lisp_Object bar;
8664 /* We can have scroll bars even if this is 0,
8665 if we just turned off scroll bar mode.
8666 But in that case we should not clear them. */
8667 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8668 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8669 bar = XSCROLL_BAR (bar)->next)
8670 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8671 0, 0, 0, 0, True);
8672 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8675 /* This processes Expose events from the menu-bar specific X event
8676 loop in xmenu.c. This allows to redisplay the frame if necessary
8677 when handling menu-bar or pop-up items. */
8680 process_expose_from_menu (event)
8681 XEvent event;
8683 FRAME_PTR f;
8684 struct x_display_info *dpyinfo;
8685 int frame_exposed_p = 0;
8687 BLOCK_INPUT;
8689 dpyinfo = x_display_info_for_display (event.xexpose.display);
8690 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8691 if (f)
8693 if (f->async_visible == 0)
8695 f->async_visible = 1;
8696 f->async_iconified = 0;
8697 f->output_data.x->has_been_visible = 1;
8698 SET_FRAME_GARBAGED (f);
8700 else
8702 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8703 event.xexpose.x, event.xexpose.y,
8704 event.xexpose.width, event.xexpose.height);
8705 frame_exposed_p = 1;
8708 else
8710 struct scroll_bar *bar
8711 = x_window_to_scroll_bar (event.xexpose.window);
8713 if (bar)
8714 x_scroll_bar_expose (bar, &event);
8717 UNBLOCK_INPUT;
8718 return frame_exposed_p;
8721 /* Define a queue to save up SelectionRequest events for later handling. */
8723 struct selection_event_queue
8725 XEvent event;
8726 struct selection_event_queue *next;
8729 static struct selection_event_queue *queue;
8731 /* Nonzero means queue up certain events--don't process them yet. */
8733 static int x_queue_selection_requests;
8735 /* Queue up an X event *EVENT, to be processed later. */
8737 static void
8738 x_queue_event (f, event)
8739 FRAME_PTR f;
8740 XEvent *event;
8742 struct selection_event_queue *queue_tmp
8743 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8745 if (queue_tmp != NULL)
8747 queue_tmp->event = *event;
8748 queue_tmp->next = queue;
8749 queue = queue_tmp;
8753 /* Take all the queued events and put them back
8754 so that they get processed afresh. */
8756 static void
8757 x_unqueue_events (display)
8758 Display *display;
8760 while (queue != NULL)
8762 struct selection_event_queue *queue_tmp = queue;
8763 XPutBackEvent (display, &queue_tmp->event);
8764 queue = queue_tmp->next;
8765 xfree ((char *)queue_tmp);
8769 /* Start queuing SelectionRequest events. */
8771 void
8772 x_start_queuing_selection_requests (display)
8773 Display *display;
8775 x_queue_selection_requests++;
8778 /* Stop queuing SelectionRequest events. */
8780 void
8781 x_stop_queuing_selection_requests (display)
8782 Display *display;
8784 x_queue_selection_requests--;
8785 x_unqueue_events (display);
8788 /* The main X event-reading loop - XTread_socket. */
8790 /* Time stamp of enter window event. This is only used by XTread_socket,
8791 but we have to put it out here, since static variables within functions
8792 sometimes don't work. */
8794 static Time enter_timestamp;
8796 /* This holds the state XLookupString needs to implement dead keys
8797 and other tricks known as "compose processing". _X Window System_
8798 says that a portable program can't use this, but Stephen Gildea assures
8799 me that letting the compiler initialize it to zeros will work okay.
8801 This must be defined outside of XTread_socket, for the same reasons
8802 given for enter_time stamp, above. */
8804 static XComposeStatus compose_status;
8806 /* Record the last 100 characters stored
8807 to help debug the loss-of-chars-during-GC problem. */
8809 static int temp_index;
8810 static short temp_buffer[100];
8812 /* Set this to nonzero to fake an "X I/O error"
8813 on a particular display. */
8815 struct x_display_info *XTread_socket_fake_io_error;
8817 /* When we find no input here, we occasionally do a no-op command
8818 to verify that the X server is still running and we can still talk with it.
8819 We try all the open displays, one by one.
8820 This variable is used for cycling thru the displays. */
8822 static struct x_display_info *next_noop_dpyinfo;
8824 #define SET_SAVED_MENU_EVENT(size) \
8825 do \
8827 if (f->output_data.x->saved_menu_event == 0) \
8828 f->output_data.x->saved_menu_event \
8829 = (XEvent *) xmalloc (sizeof (XEvent)); \
8830 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8831 if (numchars >= 1) \
8833 bufp->kind = menu_bar_activate_event; \
8834 XSETFRAME (bufp->frame_or_window, f); \
8835 bufp++; \
8836 count++; \
8837 numchars--; \
8840 while (0)
8842 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8843 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8845 /* Read events coming from the X server.
8846 This routine is called by the SIGIO handler.
8847 We return as soon as there are no more events to be read.
8849 Events representing keys are stored in buffer BUFP,
8850 which can hold up to NUMCHARS characters.
8851 We return the number of characters stored into the buffer,
8852 thus pretending to be `read'.
8854 EXPECTED is nonzero if the caller knows input is available. */
8857 XTread_socket (sd, bufp, numchars, expected)
8858 register int sd;
8859 /* register */ struct input_event *bufp;
8860 /* register */ int numchars;
8861 int expected;
8863 int count = 0;
8864 int nbytes = 0;
8865 XEvent event;
8866 struct frame *f;
8867 int event_found = 0;
8868 struct x_display_info *dpyinfo;
8870 if (interrupt_input_blocked)
8872 interrupt_input_pending = 1;
8873 return -1;
8876 interrupt_input_pending = 0;
8877 BLOCK_INPUT;
8879 /* So people can tell when we have read the available input. */
8880 input_signal_count++;
8882 if (numchars <= 0)
8883 abort (); /* Don't think this happens. */
8885 /* Find the display we are supposed to read input for.
8886 It's the one communicating on descriptor SD. */
8887 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8889 #if 0 /* This ought to be unnecessary; let's verify it. */
8890 #ifdef FIOSNBIO
8891 /* If available, Xlib uses FIOSNBIO to make the socket
8892 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8893 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8894 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8895 fcntl (dpyinfo->connection, F_SETFL, 0);
8896 #endif /* ! defined (FIOSNBIO) */
8897 #endif
8899 #if 0 /* This code can't be made to work, with multiple displays,
8900 and appears not to be used on any system any more.
8901 Also keyboard.c doesn't turn O_NDELAY on and off
8902 for X connections. */
8903 #ifndef SIGIO
8904 #ifndef HAVE_SELECT
8905 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8907 extern int read_alarm_should_throw;
8908 read_alarm_should_throw = 1;
8909 XPeekEvent (dpyinfo->display, &event);
8910 read_alarm_should_throw = 0;
8912 #endif /* HAVE_SELECT */
8913 #endif /* SIGIO */
8914 #endif
8916 /* For debugging, this gives a way to fake an I/O error. */
8917 if (dpyinfo == XTread_socket_fake_io_error)
8919 XTread_socket_fake_io_error = 0;
8920 x_io_error_quitter (dpyinfo->display);
8923 while (XPending (dpyinfo->display))
8925 XNextEvent (dpyinfo->display, &event);
8927 #ifdef HAVE_X_I18N
8929 /* Filter events for the current X input method.
8930 XFilterEvent returns non-zero if the input method has
8931 consumed the event. We pass the frame's X window to
8932 XFilterEvent because that's the one for which the IC
8933 was created. */
8934 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8935 event.xclient.window);
8936 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
8937 break;
8939 #endif
8940 event_found = 1;
8942 switch (event.type)
8944 case ClientMessage:
8946 if (event.xclient.message_type
8947 == dpyinfo->Xatom_wm_protocols
8948 && event.xclient.format == 32)
8950 if (event.xclient.data.l[0]
8951 == dpyinfo->Xatom_wm_take_focus)
8953 /* Use x_any_window_to_frame because this
8954 could be the shell widget window
8955 if the frame has no title bar. */
8956 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
8957 #ifdef HAVE_X_I18N
8958 /* Not quite sure this is needed -pd */
8959 if (f && FRAME_XIC (f))
8960 XSetICFocus (FRAME_XIC (f));
8961 #endif
8962 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8963 instructs the WM to set the input focus automatically for
8964 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8965 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8966 it has set the focus. So, XSetInputFocus below is not
8967 needed.
8969 The call to XSetInputFocus below has also caused trouble. In
8970 cases where the XSetInputFocus done by the WM and the one
8971 below are temporally close (on a fast machine), the call
8972 below can generate additional FocusIn events which confuse
8973 Emacs. */
8975 /* Since we set WM_TAKE_FOCUS, we must call
8976 XSetInputFocus explicitly. But not if f is null,
8977 since that might be an event for a deleted frame. */
8978 if (f)
8980 Display *d = event.xclient.display;
8981 /* Catch and ignore errors, in case window has been
8982 iconified by a window manager such as GWM. */
8983 int count = x_catch_errors (d);
8984 XSetInputFocus (d, event.xclient.window,
8985 /* The ICCCM says this is
8986 the only valid choice. */
8987 RevertToParent,
8988 event.xclient.data.l[1]);
8989 /* This is needed to detect the error
8990 if there is an error. */
8991 XSync (d, False);
8992 x_uncatch_errors (d, count);
8994 /* Not certain about handling scroll bars here */
8995 #endif /* 0 */
8997 else if (event.xclient.data.l[0]
8998 == dpyinfo->Xatom_wm_save_yourself)
9000 /* Save state modify the WM_COMMAND property to
9001 something which can reinstate us. This notifies
9002 the session manager, who's looking for such a
9003 PropertyNotify. Can restart processing when
9004 a keyboard or mouse event arrives. */
9005 if (numchars > 0)
9007 f = x_top_window_to_frame (dpyinfo,
9008 event.xclient.window);
9010 /* This is just so we only give real data once
9011 for a single Emacs process. */
9012 if (f == SELECTED_FRAME ())
9013 XSetCommand (FRAME_X_DISPLAY (f),
9014 event.xclient.window,
9015 initial_argv, initial_argc);
9016 else if (f)
9017 XSetCommand (FRAME_X_DISPLAY (f),
9018 event.xclient.window,
9019 0, 0);
9022 else if (event.xclient.data.l[0]
9023 == dpyinfo->Xatom_wm_delete_window)
9025 struct frame *f
9026 = x_any_window_to_frame (dpyinfo,
9027 event.xclient.window);
9029 if (f)
9031 if (numchars == 0)
9032 abort ();
9034 bufp->kind = delete_window_event;
9035 XSETFRAME (bufp->frame_or_window, f);
9036 bufp++;
9038 count += 1;
9039 numchars -= 1;
9043 else if (event.xclient.message_type
9044 == dpyinfo->Xatom_wm_configure_denied)
9047 else if (event.xclient.message_type
9048 == dpyinfo->Xatom_wm_window_moved)
9050 int new_x, new_y;
9051 struct frame *f
9052 = x_window_to_frame (dpyinfo, event.xclient.window);
9054 new_x = event.xclient.data.s[0];
9055 new_y = event.xclient.data.s[1];
9057 if (f)
9059 f->output_data.x->left_pos = new_x;
9060 f->output_data.x->top_pos = new_y;
9063 #ifdef HACK_EDITRES
9064 else if (event.xclient.message_type
9065 == dpyinfo->Xatom_editres)
9067 struct frame *f
9068 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9069 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9070 &event, NULL);
9072 #endif /* HACK_EDITRES */
9073 else if ((event.xclient.message_type
9074 == dpyinfo->Xatom_DONE)
9075 || (event.xclient.message_type
9076 == dpyinfo->Xatom_PAGE))
9078 /* Ghostview job completed. Kill it. We could
9079 reply with "Next" if we received "Page", but we
9080 currently never do because we are interested in
9081 images, only, which should have 1 page. */
9082 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9083 struct frame *f
9084 = x_window_to_frame (dpyinfo, event.xclient.window);
9085 x_kill_gs_process (pixmap, f);
9086 expose_frame (f, 0, 0, 0, 0);
9088 #ifdef USE_TOOLKIT_SCROLL_BARS
9089 /* Scroll bar callbacks send a ClientMessage from which
9090 we construct an input_event. */
9091 else if (event.xclient.message_type
9092 == dpyinfo->Xatom_Scrollbar)
9094 x_scroll_bar_to_input_event (&event, bufp);
9095 ++bufp, ++count, --numchars;
9096 goto out;
9098 #endif /* USE_TOOLKIT_SCROLL_BARS */
9099 else
9100 goto OTHER;
9102 break;
9104 case SelectionNotify:
9105 #ifdef USE_X_TOOLKIT
9106 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9107 goto OTHER;
9108 #endif /* not USE_X_TOOLKIT */
9109 x_handle_selection_notify (&event.xselection);
9110 break;
9112 case SelectionClear: /* Someone has grabbed ownership. */
9113 #ifdef USE_X_TOOLKIT
9114 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9115 goto OTHER;
9116 #endif /* USE_X_TOOLKIT */
9118 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9120 if (numchars == 0)
9121 abort ();
9123 bufp->kind = selection_clear_event;
9124 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9125 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9126 SELECTION_EVENT_TIME (bufp) = eventp->time;
9127 bufp->frame_or_window = Qnil;
9128 bufp++;
9130 count += 1;
9131 numchars -= 1;
9133 break;
9135 case SelectionRequest: /* Someone wants our selection. */
9136 #ifdef USE_X_TOOLKIT
9137 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9138 goto OTHER;
9139 #endif /* USE_X_TOOLKIT */
9140 if (x_queue_selection_requests)
9141 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9142 &event);
9143 else
9145 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9147 if (numchars == 0)
9148 abort ();
9150 bufp->kind = selection_request_event;
9151 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9152 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9153 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9154 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9155 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9156 SELECTION_EVENT_TIME (bufp) = eventp->time;
9157 bufp->frame_or_window = Qnil;
9158 bufp++;
9160 count += 1;
9161 numchars -= 1;
9163 break;
9165 case PropertyNotify:
9166 #ifdef USE_X_TOOLKIT
9167 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9168 goto OTHER;
9169 #endif /* not USE_X_TOOLKIT */
9170 x_handle_property_notify (&event.xproperty);
9171 break;
9173 case ReparentNotify:
9174 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9175 if (f)
9177 int x, y;
9178 f->output_data.x->parent_desc = event.xreparent.parent;
9179 x_real_positions (f, &x, &y);
9180 f->output_data.x->left_pos = x;
9181 f->output_data.x->top_pos = y;
9183 break;
9185 case Expose:
9186 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9187 if (f)
9189 if (f->async_visible == 0)
9191 f->async_visible = 1;
9192 f->async_iconified = 0;
9193 f->output_data.x->has_been_visible = 1;
9194 SET_FRAME_GARBAGED (f);
9196 else
9197 expose_frame (x_window_to_frame (dpyinfo,
9198 event.xexpose.window),
9199 event.xexpose.x, event.xexpose.y,
9200 event.xexpose.width, event.xexpose.height);
9202 else
9204 #ifdef USE_TOOLKIT_SCROLL_BARS
9205 /* Dispatch event to the widget. */
9206 goto OTHER;
9207 #else /* not USE_TOOLKIT_SCROLL_BARS */
9208 struct scroll_bar *bar
9209 = x_window_to_scroll_bar (event.xexpose.window);
9211 if (bar)
9212 x_scroll_bar_expose (bar, &event);
9213 #ifdef USE_X_TOOLKIT
9214 else
9215 goto OTHER;
9216 #endif /* USE_X_TOOLKIT */
9217 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9219 break;
9221 case GraphicsExpose: /* This occurs when an XCopyArea's
9222 source area was obscured or not
9223 available.*/
9224 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9225 if (f)
9227 expose_frame (f,
9228 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9229 event.xgraphicsexpose.width,
9230 event.xgraphicsexpose.height);
9232 #ifdef USE_X_TOOLKIT
9233 else
9234 goto OTHER;
9235 #endif /* USE_X_TOOLKIT */
9236 break;
9238 case NoExpose: /* This occurs when an XCopyArea's
9239 source area was completely
9240 available */
9241 break;
9243 case UnmapNotify:
9244 /* Redo the mouse-highlight after the tooltip has gone. */
9245 if (event.xmap.window == tip_window)
9247 tip_window = 0;
9248 redo_mouse_highlight ();
9251 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9252 if (f) /* F may no longer exist if
9253 the frame was deleted. */
9255 /* While a frame is unmapped, display generation is
9256 disabled; you don't want to spend time updating a
9257 display that won't ever be seen. */
9258 f->async_visible = 0;
9259 /* We can't distinguish, from the event, whether the window
9260 has become iconified or invisible. So assume, if it
9261 was previously visible, than now it is iconified.
9262 But x_make_frame_invisible clears both
9263 the visible flag and the iconified flag;
9264 and that way, we know the window is not iconified now. */
9265 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9267 f->async_iconified = 1;
9269 bufp->kind = iconify_event;
9270 XSETFRAME (bufp->frame_or_window, f);
9271 bufp++;
9272 count++;
9273 numchars--;
9276 goto OTHER;
9278 case MapNotify:
9279 if (event.xmap.window == tip_window)
9280 /* The tooltip has been drawn already. Avoid
9281 the SET_FRAME_GARBAGED below. */
9282 goto OTHER;
9284 /* We use x_top_window_to_frame because map events can
9285 come for sub-windows and they don't mean that the
9286 frame is visible. */
9287 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9288 if (f)
9290 f->async_visible = 1;
9291 f->async_iconified = 0;
9292 f->output_data.x->has_been_visible = 1;
9294 /* wait_reading_process_input will notice this and update
9295 the frame's display structures. */
9296 SET_FRAME_GARBAGED (f);
9298 if (f->iconified)
9300 bufp->kind = deiconify_event;
9301 XSETFRAME (bufp->frame_or_window, f);
9302 bufp++;
9303 count++;
9304 numchars--;
9306 else if (! NILP (Vframe_list)
9307 && ! NILP (XCDR (Vframe_list)))
9308 /* Force a redisplay sooner or later
9309 to update the frame titles
9310 in case this is the second frame. */
9311 record_asynch_buffer_change ();
9313 goto OTHER;
9315 case KeyPress:
9316 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9318 #ifdef USE_MOTIF
9319 /* I couldn't find a way to prevent LessTif scroll bars
9320 from consuming key events. */
9321 if (f == 0)
9323 Widget widget = XtWindowToWidget (dpyinfo->display,
9324 event.xkey.window);
9325 if (widget && XmIsScrollBar (widget))
9327 widget = XtParent (widget);
9328 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9331 #endif /* USE_MOTIF */
9333 if (f != 0)
9335 KeySym keysym, orig_keysym;
9336 /* al%imercury@uunet.uu.net says that making this 81 instead of
9337 80 fixed a bug whereby meta chars made his Emacs hang. */
9338 unsigned char copy_buffer[81];
9339 int modifiers;
9341 event.xkey.state
9342 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9343 extra_keyboard_modifiers);
9344 modifiers = event.xkey.state;
9346 /* This will have to go some day... */
9348 /* make_lispy_event turns chars into control chars.
9349 Don't do it here because XLookupString is too eager. */
9350 event.xkey.state &= ~ControlMask;
9351 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9352 | dpyinfo->super_mod_mask
9353 | dpyinfo->hyper_mod_mask
9354 | dpyinfo->alt_mod_mask);
9356 /* In case Meta is ComposeCharacter,
9357 clear its status. According to Markus Ehrnsperger
9358 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9359 this enables ComposeCharacter to work whether or
9360 not it is combined with Meta. */
9361 if (modifiers & dpyinfo->meta_mod_mask)
9362 bzero (&compose_status, sizeof (compose_status));
9364 #ifdef HAVE_X_I18N
9365 if (FRAME_XIC (f))
9367 unsigned char *copy_bufptr = copy_buffer;
9368 int copy_bufsiz = sizeof (copy_buffer);
9369 Status status_return;
9371 nbytes = XmbLookupString (FRAME_XIC (f),
9372 &event.xkey, copy_bufptr,
9373 copy_bufsiz, &keysym,
9374 &status_return);
9375 if (status_return == XBufferOverflow)
9377 copy_bufsiz = nbytes + 1;
9378 copy_bufptr = (char *) alloca (copy_bufsiz);
9379 nbytes = XmbLookupString (FRAME_XIC (f),
9380 &event.xkey, copy_bufptr,
9381 copy_bufsiz, &keysym,
9382 &status_return);
9385 if (status_return == XLookupNone)
9386 break;
9387 else if (status_return == XLookupChars)
9388 keysym = NoSymbol;
9389 else if (status_return != XLookupKeySym
9390 && status_return != XLookupBoth)
9391 abort ();
9393 else
9394 nbytes = XLookupString (&event.xkey, copy_buffer,
9395 80, &keysym, &compose_status);
9396 #else
9397 nbytes = XLookupString (&event.xkey, copy_buffer,
9398 80, &keysym, &compose_status);
9399 #endif
9401 orig_keysym = keysym;
9403 if (numchars > 1)
9405 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9406 || keysym == XK_Delete
9407 #ifdef XK_ISO_Left_Tab
9408 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9409 #endif
9410 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9411 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9412 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9413 #ifdef HPUX
9414 /* This recognizes the "extended function keys".
9415 It seems there's no cleaner way.
9416 Test IsModifierKey to avoid handling mode_switch
9417 incorrectly. */
9418 || ((unsigned) (keysym) >= XK_Select
9419 && (unsigned)(keysym) < XK_KP_Space)
9420 #endif
9421 #ifdef XK_dead_circumflex
9422 || orig_keysym == XK_dead_circumflex
9423 #endif
9424 #ifdef XK_dead_grave
9425 || orig_keysym == XK_dead_grave
9426 #endif
9427 #ifdef XK_dead_tilde
9428 || orig_keysym == XK_dead_tilde
9429 #endif
9430 #ifdef XK_dead_diaeresis
9431 || orig_keysym == XK_dead_diaeresis
9432 #endif
9433 #ifdef XK_dead_macron
9434 || orig_keysym == XK_dead_macron
9435 #endif
9436 #ifdef XK_dead_degree
9437 || orig_keysym == XK_dead_degree
9438 #endif
9439 #ifdef XK_dead_acute
9440 || orig_keysym == XK_dead_acute
9441 #endif
9442 #ifdef XK_dead_cedilla
9443 || orig_keysym == XK_dead_cedilla
9444 #endif
9445 #ifdef XK_dead_breve
9446 || orig_keysym == XK_dead_breve
9447 #endif
9448 #ifdef XK_dead_ogonek
9449 || orig_keysym == XK_dead_ogonek
9450 #endif
9451 #ifdef XK_dead_caron
9452 || orig_keysym == XK_dead_caron
9453 #endif
9454 #ifdef XK_dead_doubleacute
9455 || orig_keysym == XK_dead_doubleacute
9456 #endif
9457 #ifdef XK_dead_abovedot
9458 || orig_keysym == XK_dead_abovedot
9459 #endif
9460 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9461 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9462 /* Any "vendor-specific" key is ok. */
9463 || (orig_keysym & (1 << 28)))
9464 && ! (IsModifierKey (orig_keysym)
9465 #ifndef HAVE_X11R5
9466 #ifdef XK_Mode_switch
9467 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9468 #endif
9469 #ifdef XK_Num_Lock
9470 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9471 #endif
9472 #endif /* not HAVE_X11R5 */
9475 if (temp_index == sizeof temp_buffer / sizeof (short))
9476 temp_index = 0;
9477 temp_buffer[temp_index++] = keysym;
9478 bufp->kind = non_ascii_keystroke;
9479 bufp->code = keysym;
9480 XSETFRAME (bufp->frame_or_window, f);
9481 bufp->modifiers
9482 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9483 modifiers);
9484 bufp->timestamp = event.xkey.time;
9485 bufp++;
9486 count++;
9487 numchars--;
9489 else if (numchars > nbytes)
9491 register int i;
9493 for (i = 0; i < nbytes; i++)
9495 if (temp_index == sizeof temp_buffer / sizeof (short))
9496 temp_index = 0;
9497 temp_buffer[temp_index++] = copy_buffer[i];
9498 bufp->kind = ascii_keystroke;
9499 bufp->code = copy_buffer[i];
9500 XSETFRAME (bufp->frame_or_window, f);
9501 bufp->modifiers
9502 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9503 modifiers);
9504 bufp->timestamp = event.xkey.time;
9505 bufp++;
9508 count += nbytes;
9509 numchars -= nbytes;
9511 if (keysym == NoSymbol)
9512 break;
9514 else
9515 abort ();
9517 else
9518 abort ();
9520 #ifdef HAVE_X_I18N
9521 /* Don't dispatch this event since XtDispatchEvent calls
9522 XFilterEvent, and two calls in a row may freeze the
9523 client. */
9524 break;
9525 #else
9526 goto OTHER;
9527 #endif
9529 case KeyRelease:
9530 #ifdef HAVE_X_I18N
9531 /* Don't dispatch this event since XtDispatchEvent calls
9532 XFilterEvent, and two calls in a row may freeze the
9533 client. */
9534 break;
9535 #else
9536 goto OTHER;
9537 #endif
9539 /* Here's a possible interpretation of the whole
9540 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9541 you get a FocusIn event, you have to get a FocusOut
9542 event before you relinquish the focus. If you
9543 haven't received a FocusIn event, then a mere
9544 LeaveNotify is enough to free you. */
9546 case EnterNotify:
9548 int from_menu_bar_p = 0;
9550 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9552 #ifdef LESSTIF_VERSION
9553 /* When clicking outside of a menu bar popup to close
9554 it, we get a FocusIn/ EnterNotify sequence of
9555 events. The flag event.xcrossing.focus is not set
9556 in the EnterNotify event of that sequence because
9557 the focus is in the menu bar,
9558 event.xcrossing.window is the frame's X window.
9559 Unconditionally setting the focus frame to null in
9560 this case is not the right thing, because no event
9561 follows that could set the focus frame to the right
9562 value.
9564 This could be a LessTif bug, but I wasn't able to
9565 reproduce the behavior in a simple test program.
9567 (gerd, LessTif 0.88.1). */
9569 if (!event.xcrossing.focus
9570 && f
9571 && f->output_data.x->menubar_widget)
9573 Window focus;
9574 int revert;
9576 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9577 if (focus == XtWindow (f->output_data.x->menubar_widget))
9578 from_menu_bar_p = 1;
9580 #endif /* LESSTIF_VERSION */
9582 if (event.xcrossing.focus || from_menu_bar_p)
9584 /* Avoid nasty pop/raise loops. */
9585 if (f && (!(f->auto_raise)
9586 || !(f->auto_lower)
9587 || (event.xcrossing.time - enter_timestamp) > 500))
9589 x_new_focus_frame (dpyinfo, f);
9590 enter_timestamp = event.xcrossing.time;
9593 else if (f == dpyinfo->x_focus_frame)
9594 x_new_focus_frame (dpyinfo, 0);
9596 /* EnterNotify counts as mouse movement,
9597 so update things that depend on mouse position. */
9598 if (f && !f->output_data.x->busy_p)
9599 note_mouse_movement (f, &event.xmotion);
9600 goto OTHER;
9603 case FocusIn:
9604 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9605 if (event.xfocus.detail != NotifyPointer)
9606 dpyinfo->x_focus_event_frame = f;
9607 if (f)
9608 x_new_focus_frame (dpyinfo, f);
9610 #ifdef HAVE_X_I18N
9611 if (f && FRAME_XIC (f))
9612 XSetICFocus (FRAME_XIC (f));
9613 #endif
9615 goto OTHER;
9617 case LeaveNotify:
9618 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9619 if (f)
9621 Lisp_Object frame;
9622 int from_menu_bar_p = 0;
9624 if (f == dpyinfo->mouse_face_mouse_frame)
9626 /* If we move outside the frame, then we're
9627 certainly no longer on any text in the frame. */
9628 clear_mouse_face (dpyinfo);
9629 dpyinfo->mouse_face_mouse_frame = 0;
9632 /* Generate a nil HELP_EVENT to cancel a help-echo.
9633 Do it only if there's something to cancel.
9634 Otherwise, the startup message is cleared when
9635 the mouse leaves the frame. */
9636 if (any_help_event_p)
9638 XSETFRAME (frame, f);
9639 bufp->kind = HELP_EVENT;
9640 bufp->frame_or_window = Fcons (frame, Qnil);
9641 ++bufp, ++count, --numchars;
9644 #ifdef LESSTIF_VERSION
9645 /* Please see the comment at the start of the
9646 EnterNotify case. */
9647 if (!event.xcrossing.focus
9648 && f->output_data.x->menubar_widget)
9650 Window focus;
9651 int revert;
9652 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9653 if (focus == XtWindow (f->output_data.x->menubar_widget))
9654 from_menu_bar_p = 1;
9656 #endif /* LESSTIF_VERSION */
9658 if (event.xcrossing.focus || from_menu_bar_p)
9659 x_mouse_leave (dpyinfo);
9660 else
9662 if (f == dpyinfo->x_focus_event_frame)
9663 dpyinfo->x_focus_event_frame = 0;
9664 if (f == dpyinfo->x_focus_frame)
9665 x_new_focus_frame (dpyinfo, 0);
9668 goto OTHER;
9670 case FocusOut:
9671 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9672 if (event.xfocus.detail != NotifyPointer
9673 && f == dpyinfo->x_focus_event_frame)
9674 dpyinfo->x_focus_event_frame = 0;
9675 if (f && f == dpyinfo->x_focus_frame)
9676 x_new_focus_frame (dpyinfo, 0);
9678 #ifdef HAVE_X_I18N
9679 if (f && FRAME_XIC (f))
9680 XUnsetICFocus (FRAME_XIC (f));
9681 #endif
9683 goto OTHER;
9685 case MotionNotify:
9687 previous_help_echo = help_echo;
9688 help_echo = Qnil;
9690 if (dpyinfo->grabbed && last_mouse_frame
9691 && FRAME_LIVE_P (last_mouse_frame))
9692 f = last_mouse_frame;
9693 else
9694 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9696 if (f)
9697 note_mouse_movement (f, &event.xmotion);
9698 else
9700 #ifndef USE_TOOLKIT_SCROLL_BARS
9701 struct scroll_bar *bar
9702 = x_window_to_scroll_bar (event.xmotion.window);
9704 if (bar)
9705 x_scroll_bar_note_movement (bar, &event);
9706 #endif /* USE_TOOLKIT_SCROLL_BARS */
9708 /* If we move outside the frame, then we're
9709 certainly no longer on any text in the frame. */
9710 clear_mouse_face (dpyinfo);
9713 /* If the contents of the global variable help_echo
9714 has changed, generate a HELP_EVENT. */
9715 if (STRINGP (help_echo)
9716 || STRINGP (previous_help_echo))
9718 Lisp_Object frame;
9720 if (f)
9721 XSETFRAME (frame, f);
9722 else
9723 frame = Qnil;
9725 any_help_event_p = 1;
9726 bufp->kind = HELP_EVENT;
9727 bufp->frame_or_window = Fcons (frame, help_echo);
9728 ++bufp, ++count, --numchars;
9731 goto OTHER;
9734 case ConfigureNotify:
9735 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9736 if (f)
9738 #ifndef USE_X_TOOLKIT
9739 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9740 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
9742 /* In the toolkit version, change_frame_size
9743 is called by the code that handles resizing
9744 of the EmacsFrame widget. */
9746 /* Even if the number of character rows and columns has
9747 not changed, the font size may have changed, so we need
9748 to check the pixel dimensions as well. */
9749 if (columns != f->width
9750 || rows != f->height
9751 || event.xconfigure.width != f->output_data.x->pixel_width
9752 || event.xconfigure.height != f->output_data.x->pixel_height)
9754 change_frame_size (f, rows, columns, 0, 1, 0);
9755 SET_FRAME_GARBAGED (f);
9756 cancel_mouse_face (f);
9758 #endif
9760 f->output_data.x->pixel_width = event.xconfigure.width;
9761 f->output_data.x->pixel_height = event.xconfigure.height;
9763 /* What we have now is the position of Emacs's own window.
9764 Convert that to the position of the window manager window. */
9765 x_real_positions (f, &f->output_data.x->left_pos,
9766 &f->output_data.x->top_pos);
9768 #ifdef HAVE_X_I18N
9769 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9770 xic_set_statusarea (f);
9771 #endif
9773 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9775 /* Since the WM decorations come below top_pos now,
9776 we must put them below top_pos in the future. */
9777 f->output_data.x->win_gravity = NorthWestGravity;
9778 x_wm_set_size_hint (f, (long) 0, 0);
9780 #ifdef USE_MOTIF
9781 /* Some window managers pass (0,0) as the location of
9782 the window, and the Motif event handler stores it
9783 in the emacs widget, which messes up Motif menus. */
9784 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9786 event.xconfigure.x = f->output_data.x->widget->core.x;
9787 event.xconfigure.y = f->output_data.x->widget->core.y;
9789 #endif /* USE_MOTIF */
9791 goto OTHER;
9793 case ButtonPress:
9794 case ButtonRelease:
9796 /* If we decide we want to generate an event to be seen
9797 by the rest of Emacs, we put it here. */
9798 struct input_event emacs_event;
9799 int tool_bar_p = 0;
9801 emacs_event.kind = no_event;
9802 bzero (&compose_status, sizeof (compose_status));
9804 if (dpyinfo->grabbed
9805 && last_mouse_frame
9806 && FRAME_LIVE_P (last_mouse_frame))
9807 f = last_mouse_frame;
9808 else
9809 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9811 if (f)
9813 /* Is this in the tool-bar? */
9814 if (WINDOWP (f->tool_bar_window)
9815 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
9817 Lisp_Object window;
9818 int p, x, y;
9820 x = event.xbutton.x;
9821 y = event.xbutton.y;
9823 /* Set x and y. */
9824 window = window_from_coordinates (f, x, y, &p, 1);
9825 if (EQ (window, f->tool_bar_window))
9827 x_handle_tool_bar_click (f, &event.xbutton);
9828 tool_bar_p = 1;
9832 if (!tool_bar_p)
9833 if (!dpyinfo->x_focus_frame
9834 || f == dpyinfo->x_focus_frame)
9835 construct_mouse_click (&emacs_event, &event, f);
9837 else
9839 #ifndef USE_TOOLKIT_SCROLL_BARS
9840 struct scroll_bar *bar
9841 = x_window_to_scroll_bar (event.xbutton.window);
9843 if (bar)
9844 x_scroll_bar_handle_click (bar, &event, &emacs_event);
9845 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9848 if (event.type == ButtonPress)
9850 dpyinfo->grabbed |= (1 << event.xbutton.button);
9851 last_mouse_frame = f;
9852 /* Ignore any mouse motion that happened
9853 before this event; any subsequent mouse-movement
9854 Emacs events should reflect only motion after
9855 the ButtonPress. */
9856 if (f != 0)
9857 f->mouse_moved = 0;
9859 if (!tool_bar_p)
9860 last_tool_bar_item = -1;
9862 else
9864 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
9867 if (numchars >= 1 && emacs_event.kind != no_event)
9869 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9870 bufp++;
9871 count++;
9872 numchars--;
9875 #ifdef USE_X_TOOLKIT
9876 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9877 /* For a down-event in the menu bar,
9878 don't pass it to Xt right now.
9879 Instead, save it away
9880 and we will pass it to Xt from kbd_buffer_get_event.
9881 That way, we can run some Lisp code first. */
9882 if (f && event.type == ButtonPress
9883 /* Verify the event is really within the menu bar
9884 and not just sent to it due to grabbing. */
9885 && event.xbutton.x >= 0
9886 && event.xbutton.x < f->output_data.x->pixel_width
9887 && event.xbutton.y >= 0
9888 && event.xbutton.y < f->output_data.x->menubar_height
9889 && event.xbutton.same_screen)
9891 SET_SAVED_BUTTON_EVENT;
9892 XSETFRAME (last_mouse_press_frame, f);
9894 else if (event.type == ButtonPress)
9896 last_mouse_press_frame = Qnil;
9897 goto OTHER;
9900 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9901 but I am trying to be cautious. */
9902 else if (event.type == ButtonRelease)
9904 if (!NILP (last_mouse_press_frame))
9906 f = XFRAME (last_mouse_press_frame);
9907 if (f->output_data.x)
9908 SET_SAVED_BUTTON_EVENT;
9910 else
9911 goto OTHER;
9913 #endif /* USE_MOTIF */
9914 else
9915 goto OTHER;
9916 #endif /* USE_X_TOOLKIT */
9918 break;
9920 case CirculateNotify:
9921 goto OTHER;
9923 case CirculateRequest:
9924 goto OTHER;
9926 case VisibilityNotify:
9927 goto OTHER;
9929 case MappingNotify:
9930 /* Someone has changed the keyboard mapping - update the
9931 local cache. */
9932 switch (event.xmapping.request)
9934 case MappingModifier:
9935 x_find_modifier_meanings (dpyinfo);
9936 /* This is meant to fall through. */
9937 case MappingKeyboard:
9938 XRefreshKeyboardMapping (&event.xmapping);
9940 goto OTHER;
9942 default:
9943 OTHER:
9944 #ifdef USE_X_TOOLKIT
9945 BLOCK_INPUT;
9946 XtDispatchEvent (&event);
9947 UNBLOCK_INPUT;
9948 #endif /* USE_X_TOOLKIT */
9949 break;
9954 out:;
9956 /* On some systems, an X bug causes Emacs to get no more events
9957 when the window is destroyed. Detect that. (1994.) */
9958 if (! event_found)
9960 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9961 One XNOOP in 100 loops will make Emacs terminate.
9962 B. Bretthauer, 1994 */
9963 x_noop_count++;
9964 if (x_noop_count >= 100)
9966 x_noop_count=0;
9968 if (next_noop_dpyinfo == 0)
9969 next_noop_dpyinfo = x_display_list;
9971 XNoOp (next_noop_dpyinfo->display);
9973 /* Each time we get here, cycle through the displays now open. */
9974 next_noop_dpyinfo = next_noop_dpyinfo->next;
9978 /* If the focus was just given to an auto-raising frame,
9979 raise it now. */
9980 /* ??? This ought to be able to handle more than one such frame. */
9981 if (pending_autoraise_frame)
9983 x_raise_frame (pending_autoraise_frame);
9984 pending_autoraise_frame = 0;
9987 UNBLOCK_INPUT;
9988 return count;
9994 /***********************************************************************
9995 Text Cursor
9996 ***********************************************************************/
9998 /* Note if the text cursor of window W has been overwritten by a
9999 drawing operation that outputs N glyphs starting at HPOS in the
10000 line given by output_cursor.vpos. N < 0 means all the rest of the
10001 line after HPOS has been written. */
10003 static void
10004 note_overwritten_text_cursor (w, hpos, n)
10005 struct window *w;
10006 int hpos, n;
10008 if (updated_area == TEXT_AREA
10009 && output_cursor.vpos == w->phys_cursor.vpos
10010 && hpos <= w->phys_cursor.hpos
10011 && (n < 0
10012 || hpos + n > w->phys_cursor.hpos))
10013 w->phys_cursor_on_p = 0;
10017 /* Set clipping for output in glyph row ROW. W is the window in which
10018 we operate. GC is the graphics context to set clipping in.
10019 WHOLE_LINE_P non-zero means include the areas used for truncation
10020 mark display and alike in the clipping rectangle.
10022 ROW may be a text row or, e.g., a mode line. Text rows must be
10023 clipped to the interior of the window dedicated to text display,
10024 mode lines must be clipped to the whole window. */
10026 static void
10027 x_clip_to_row (w, row, gc, whole_line_p)
10028 struct window *w;
10029 struct glyph_row *row;
10030 GC gc;
10031 int whole_line_p;
10033 struct frame *f = XFRAME (WINDOW_FRAME (w));
10034 XRectangle clip_rect;
10035 int window_x, window_y, window_width, window_height;
10037 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10039 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10040 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10041 clip_rect.y = max (clip_rect.y, window_y);
10042 clip_rect.width = window_width;
10043 clip_rect.height = row->visible_height;
10045 /* If clipping to the whole line, including trunc marks, extend
10046 the rectangle to the left and increase its width. */
10047 if (whole_line_p)
10049 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10050 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10053 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10057 /* Draw a hollow box cursor on window W in glyph row ROW. */
10059 static void
10060 x_draw_hollow_cursor (w, row)
10061 struct window *w;
10062 struct glyph_row *row;
10064 struct frame *f = XFRAME (WINDOW_FRAME (w));
10065 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10066 Display *dpy = FRAME_X_DISPLAY (f);
10067 int x, y, wd, h;
10068 XGCValues xgcv;
10069 struct glyph *cursor_glyph;
10070 GC gc;
10072 /* Compute frame-relative coordinates from window-relative
10073 coordinates. */
10074 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10075 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10076 + row->ascent - w->phys_cursor_ascent);
10077 h = row->height - 1;
10079 /* Get the glyph the cursor is on. If we can't tell because
10080 the current matrix is invalid or such, give up. */
10081 cursor_glyph = get_phys_cursor_glyph (w);
10082 if (cursor_glyph == NULL)
10083 return;
10085 /* Compute the width of the rectangle to draw. If on a stretch
10086 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10087 rectangle as wide as the glyph, but use a canonical character
10088 width instead. */
10089 wd = cursor_glyph->pixel_width - 1;
10090 if (cursor_glyph->type == STRETCH_GLYPH
10091 && !x_stretch_cursor_p)
10092 wd = min (CANON_X_UNIT (f), wd);
10094 /* The foreground of cursor_gc is typically the same as the normal
10095 background color, which can cause the cursor box to be invisible. */
10096 xgcv.foreground = f->output_data.x->cursor_pixel;
10097 if (dpyinfo->scratch_cursor_gc)
10098 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10099 else
10100 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10101 GCForeground, &xgcv);
10102 gc = dpyinfo->scratch_cursor_gc;
10104 /* Set clipping, draw the rectangle, and reset clipping again. */
10105 x_clip_to_row (w, row, gc, 0);
10106 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10107 XSetClipMask (dpy, gc, None);
10111 /* Draw a bar cursor on window W in glyph row ROW.
10113 Implementation note: One would like to draw a bar cursor with an
10114 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10115 Unfortunately, I didn't find a font yet that has this property set.
10116 --gerd. */
10118 static void
10119 x_draw_bar_cursor (w, row, width)
10120 struct window *w;
10121 struct glyph_row *row;
10122 int width;
10124 /* If cursor hpos is out of bounds, don't draw garbage. This can
10125 happen in mini-buffer windows when switching between echo area
10126 glyphs and mini-buffer. */
10127 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10129 struct frame *f = XFRAME (w->frame);
10130 struct glyph *cursor_glyph;
10131 GC gc;
10132 int x;
10133 unsigned long mask;
10134 XGCValues xgcv;
10135 Display *dpy;
10136 Window window;
10138 cursor_glyph = get_phys_cursor_glyph (w);
10139 if (cursor_glyph == NULL)
10140 return;
10142 xgcv.background = f->output_data.x->cursor_pixel;
10143 xgcv.foreground = f->output_data.x->cursor_pixel;
10144 xgcv.graphics_exposures = 0;
10145 mask = GCForeground | GCBackground | GCGraphicsExposures;
10146 dpy = FRAME_X_DISPLAY (f);
10147 window = FRAME_X_WINDOW (f);
10148 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10150 if (gc)
10151 XChangeGC (dpy, gc, mask, &xgcv);
10152 else
10154 gc = XCreateGC (dpy, window, mask, &xgcv);
10155 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10158 if (width < 0)
10159 width = f->output_data.x->cursor_width;
10161 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10162 x_clip_to_row (w, row, gc, 0);
10163 XFillRectangle (dpy, window, gc,
10165 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10166 min (cursor_glyph->pixel_width, width),
10167 row->height);
10168 XSetClipMask (dpy, gc, None);
10173 /* Clear the cursor of window W to background color, and mark the
10174 cursor as not shown. This is used when the text where the cursor
10175 is is about to be rewritten. */
10177 static void
10178 x_clear_cursor (w)
10179 struct window *w;
10181 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10182 x_update_window_cursor (w, 0);
10186 /* Draw the cursor glyph of window W in glyph row ROW. See the
10187 comment of x_draw_glyphs for the meaning of HL. */
10189 static void
10190 x_draw_phys_cursor_glyph (w, row, hl)
10191 struct window *w;
10192 struct glyph_row *row;
10193 enum draw_glyphs_face hl;
10195 /* If cursor hpos is out of bounds, don't draw garbage. This can
10196 happen in mini-buffer windows when switching between echo area
10197 glyphs and mini-buffer. */
10198 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10200 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10201 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10202 hl, 0, 0, 0);
10204 /* When we erase the cursor, and ROW is overlapped by other
10205 rows, make sure that these overlapping parts of other rows
10206 are redrawn. */
10207 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10209 if (row > w->current_matrix->rows
10210 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10211 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10213 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10214 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10215 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10221 /* Erase the image of a cursor of window W from the screen. */
10223 static void
10224 x_erase_phys_cursor (w)
10225 struct window *w;
10227 struct frame *f = XFRAME (w->frame);
10228 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10229 int hpos = w->phys_cursor.hpos;
10230 int vpos = w->phys_cursor.vpos;
10231 int mouse_face_here_p = 0;
10232 struct glyph_matrix *active_glyphs = w->current_matrix;
10233 struct glyph_row *cursor_row;
10234 struct glyph *cursor_glyph;
10235 enum draw_glyphs_face hl;
10237 /* No cursor displayed or row invalidated => nothing to do on the
10238 screen. */
10239 if (w->phys_cursor_type == NO_CURSOR)
10240 goto mark_cursor_off;
10242 /* VPOS >= active_glyphs->nrows means that window has been resized.
10243 Don't bother to erase the cursor. */
10244 if (vpos >= active_glyphs->nrows)
10245 goto mark_cursor_off;
10247 /* If row containing cursor is marked invalid, there is nothing we
10248 can do. */
10249 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10250 if (!cursor_row->enabled_p)
10251 goto mark_cursor_off;
10253 /* This can happen when the new row is shorter than the old one.
10254 In this case, either x_draw_glyphs or clear_end_of_line
10255 should have cleared the cursor. Note that we wouldn't be
10256 able to erase the cursor in this case because we don't have a
10257 cursor glyph at hand. */
10258 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10259 goto mark_cursor_off;
10261 /* If the cursor is in the mouse face area, redisplay that when
10262 we clear the cursor. */
10263 if (! NILP (dpyinfo->mouse_face_window)
10264 && w == XWINDOW (dpyinfo->mouse_face_window)
10265 && (vpos > dpyinfo->mouse_face_beg_row
10266 || (vpos == dpyinfo->mouse_face_beg_row
10267 && hpos >= dpyinfo->mouse_face_beg_col))
10268 && (vpos < dpyinfo->mouse_face_end_row
10269 || (vpos == dpyinfo->mouse_face_end_row
10270 && hpos < dpyinfo->mouse_face_end_col))
10271 /* Don't redraw the cursor's spot in mouse face if it is at the
10272 end of a line (on a newline). The cursor appears there, but
10273 mouse highlighting does not. */
10274 && cursor_row->used[TEXT_AREA] > hpos)
10275 mouse_face_here_p = 1;
10277 /* Maybe clear the display under the cursor. */
10278 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10280 int x;
10281 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10283 cursor_glyph = get_phys_cursor_glyph (w);
10284 if (cursor_glyph == NULL)
10285 goto mark_cursor_off;
10287 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10289 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10291 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10292 cursor_row->y)),
10293 cursor_glyph->pixel_width,
10294 cursor_row->visible_height,
10295 False);
10298 /* Erase the cursor by redrawing the character underneath it. */
10299 if (mouse_face_here_p)
10300 hl = DRAW_MOUSE_FACE;
10301 else if (cursor_row->inverse_p)
10302 hl = DRAW_INVERSE_VIDEO;
10303 else
10304 hl = DRAW_NORMAL_TEXT;
10305 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10307 mark_cursor_off:
10308 w->phys_cursor_on_p = 0;
10309 w->phys_cursor_type = NO_CURSOR;
10313 /* Display or clear cursor of window W. If ON is zero, clear the
10314 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10315 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10317 void
10318 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10319 struct window *w;
10320 int on, hpos, vpos, x, y;
10322 struct frame *f = XFRAME (w->frame);
10323 int new_cursor_type;
10324 int new_cursor_width;
10325 struct glyph_matrix *current_glyphs;
10326 struct glyph_row *glyph_row;
10327 struct glyph *glyph;
10329 /* This is pointless on invisible frames, and dangerous on garbaged
10330 windows and frames; in the latter case, the frame or window may
10331 be in the midst of changing its size, and x and y may be off the
10332 window. */
10333 if (! FRAME_VISIBLE_P (f)
10334 || FRAME_GARBAGED_P (f)
10335 || vpos >= w->current_matrix->nrows
10336 || hpos >= w->current_matrix->matrix_w)
10337 return;
10339 /* If cursor is off and we want it off, return quickly. */
10340 if (!on && !w->phys_cursor_on_p)
10341 return;
10343 current_glyphs = w->current_matrix;
10344 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10345 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10347 /* If cursor row is not enabled, we don't really know where to
10348 display the cursor. */
10349 if (!glyph_row->enabled_p)
10351 w->phys_cursor_on_p = 0;
10352 return;
10355 xassert (interrupt_input_blocked);
10357 /* Set new_cursor_type to the cursor we want to be displayed. In a
10358 mini-buffer window, we want the cursor only to appear if we are
10359 reading input from this window. For the selected window, we want
10360 the cursor type given by the frame parameter. If explicitly
10361 marked off, draw no cursor. In all other cases, we want a hollow
10362 box cursor. */
10363 new_cursor_width = -1;
10364 if (cursor_in_echo_area
10365 && FRAME_HAS_MINIBUF_P (f)
10366 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10368 if (w == XWINDOW (echo_area_window))
10369 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10370 else
10371 new_cursor_type = HOLLOW_BOX_CURSOR;
10373 else
10375 if (w != XWINDOW (selected_window)
10376 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10378 extern int cursor_in_non_selected_windows;
10380 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
10381 new_cursor_type = NO_CURSOR;
10382 else
10383 new_cursor_type = HOLLOW_BOX_CURSOR;
10385 else if (w->cursor_off_p)
10386 new_cursor_type = NO_CURSOR;
10387 else
10389 struct buffer *b = XBUFFER (w->buffer);
10391 if (EQ (b->cursor_type, Qt))
10392 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10393 else
10394 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10395 &new_cursor_width);
10399 /* If cursor is currently being shown and we don't want it to be or
10400 it is in the wrong place, or the cursor type is not what we want,
10401 erase it. */
10402 if (w->phys_cursor_on_p
10403 && (!on
10404 || w->phys_cursor.x != x
10405 || w->phys_cursor.y != y
10406 || new_cursor_type != w->phys_cursor_type))
10407 x_erase_phys_cursor (w);
10409 /* If the cursor is now invisible and we want it to be visible,
10410 display it. */
10411 if (on && !w->phys_cursor_on_p)
10413 w->phys_cursor_ascent = glyph_row->ascent;
10414 w->phys_cursor_height = glyph_row->height;
10416 /* Set phys_cursor_.* before x_draw_.* is called because some
10417 of them may need the information. */
10418 w->phys_cursor.x = x;
10419 w->phys_cursor.y = glyph_row->y;
10420 w->phys_cursor.hpos = hpos;
10421 w->phys_cursor.vpos = vpos;
10422 w->phys_cursor_type = new_cursor_type;
10423 w->phys_cursor_on_p = 1;
10425 switch (new_cursor_type)
10427 case HOLLOW_BOX_CURSOR:
10428 x_draw_hollow_cursor (w, glyph_row);
10429 break;
10431 case FILLED_BOX_CURSOR:
10432 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10433 break;
10435 case BAR_CURSOR:
10436 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10437 break;
10439 case NO_CURSOR:
10440 break;
10442 default:
10443 abort ();
10446 #ifdef HAVE_X_I18N
10447 if (w == XWINDOW (f->selected_window))
10448 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10449 xic_set_preeditarea (w, x, y);
10450 #endif
10453 #ifndef XFlush
10454 if (updating_frame != f)
10455 XFlush (FRAME_X_DISPLAY (f));
10456 #endif
10460 /* Display the cursor on window W, or clear it. X and Y are window
10461 relative pixel coordinates. HPOS and VPOS are glyph matrix
10462 positions. If W is not the selected window, display a hollow
10463 cursor. ON non-zero means display the cursor at X, Y which
10464 correspond to HPOS, VPOS, otherwise it is cleared. */
10466 void
10467 x_display_cursor (w, on, hpos, vpos, x, y)
10468 struct window *w;
10469 int on, hpos, vpos, x, y;
10471 BLOCK_INPUT;
10472 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10473 UNBLOCK_INPUT;
10477 /* Display the cursor on window W, or clear it, according to ON_P.
10478 Don't change the cursor's position. */
10480 void
10481 x_update_cursor (f, on_p)
10482 struct frame *f;
10484 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10488 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10489 in the window tree rooted at W. */
10491 static void
10492 x_update_cursor_in_window_tree (w, on_p)
10493 struct window *w;
10494 int on_p;
10496 while (w)
10498 if (!NILP (w->hchild))
10499 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10500 else if (!NILP (w->vchild))
10501 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10502 else
10503 x_update_window_cursor (w, on_p);
10505 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10510 /* Switch the display of W's cursor on or off, according to the value
10511 of ON. */
10513 static void
10514 x_update_window_cursor (w, on)
10515 struct window *w;
10516 int on;
10518 /* Don't update cursor in windows whose frame is in the process
10519 of being deleted. */
10520 if (w->current_matrix)
10522 BLOCK_INPUT;
10523 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10524 w->phys_cursor.x, w->phys_cursor.y);
10525 UNBLOCK_INPUT;
10532 /* Icons. */
10534 /* Refresh bitmap kitchen sink icon for frame F
10535 when we get an expose event for it. */
10537 void
10538 refreshicon (f)
10539 struct frame *f;
10541 /* Normally, the window manager handles this function. */
10544 /* Make the x-window of frame F use the gnu icon bitmap. */
10547 x_bitmap_icon (f, file)
10548 struct frame *f;
10549 Lisp_Object file;
10551 int bitmap_id;
10553 if (FRAME_X_WINDOW (f) == 0)
10554 return 1;
10556 /* Free up our existing icon bitmap if any. */
10557 if (f->output_data.x->icon_bitmap > 0)
10558 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10559 f->output_data.x->icon_bitmap = 0;
10561 if (STRINGP (file))
10562 bitmap_id = x_create_bitmap_from_file (f, file);
10563 else
10565 /* Create the GNU bitmap if necessary. */
10566 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10567 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10568 = x_create_bitmap_from_data (f, gnu_bits,
10569 gnu_width, gnu_height);
10571 /* The first time we create the GNU bitmap,
10572 this increments the ref-count one extra time.
10573 As a result, the GNU bitmap is never freed.
10574 That way, we don't have to worry about allocating it again. */
10575 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10577 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10580 x_wm_set_icon_pixmap (f, bitmap_id);
10581 f->output_data.x->icon_bitmap = bitmap_id;
10583 return 0;
10587 /* Make the x-window of frame F use a rectangle with text.
10588 Use ICON_NAME as the text. */
10591 x_text_icon (f, icon_name)
10592 struct frame *f;
10593 char *icon_name;
10595 if (FRAME_X_WINDOW (f) == 0)
10596 return 1;
10598 #ifdef HAVE_X11R4
10600 XTextProperty text;
10601 text.value = (unsigned char *) icon_name;
10602 text.encoding = XA_STRING;
10603 text.format = 8;
10604 text.nitems = strlen (icon_name);
10605 #ifdef USE_X_TOOLKIT
10606 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10607 &text);
10608 #else /* not USE_X_TOOLKIT */
10609 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10610 #endif /* not USE_X_TOOLKIT */
10612 #else /* not HAVE_X11R4 */
10613 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10614 #endif /* not HAVE_X11R4 */
10616 if (f->output_data.x->icon_bitmap > 0)
10617 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10618 f->output_data.x->icon_bitmap = 0;
10619 x_wm_set_icon_pixmap (f, 0);
10621 return 0;
10624 #define X_ERROR_MESSAGE_SIZE 200
10626 /* If non-nil, this should be a string.
10627 It means catch X errors and store the error message in this string. */
10629 static Lisp_Object x_error_message_string;
10631 /* An X error handler which stores the error message in
10632 x_error_message_string. This is called from x_error_handler if
10633 x_catch_errors is in effect. */
10635 static void
10636 x_error_catcher (display, error)
10637 Display *display;
10638 XErrorEvent *error;
10640 XGetErrorText (display, error->error_code,
10641 XSTRING (x_error_message_string)->data,
10642 X_ERROR_MESSAGE_SIZE);
10645 /* Begin trapping X errors for display DPY. Actually we trap X errors
10646 for all displays, but DPY should be the display you are actually
10647 operating on.
10649 After calling this function, X protocol errors no longer cause
10650 Emacs to exit; instead, they are recorded in the string
10651 stored in x_error_message_string.
10653 Calling x_check_errors signals an Emacs error if an X error has
10654 occurred since the last call to x_catch_errors or x_check_errors.
10656 Calling x_uncatch_errors resumes the normal error handling. */
10658 void x_check_errors ();
10659 static Lisp_Object x_catch_errors_unwind ();
10662 x_catch_errors (dpy)
10663 Display *dpy;
10665 int count = specpdl_ptr - specpdl;
10667 /* Make sure any errors from previous requests have been dealt with. */
10668 XSync (dpy, False);
10670 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10672 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10673 XSTRING (x_error_message_string)->data[0] = 0;
10675 return count;
10678 /* Unbind the binding that we made to check for X errors. */
10680 static Lisp_Object
10681 x_catch_errors_unwind (old_val)
10682 Lisp_Object old_val;
10684 x_error_message_string = old_val;
10685 return Qnil;
10688 /* If any X protocol errors have arrived since the last call to
10689 x_catch_errors or x_check_errors, signal an Emacs error using
10690 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10692 void
10693 x_check_errors (dpy, format)
10694 Display *dpy;
10695 char *format;
10697 /* Make sure to catch any errors incurred so far. */
10698 XSync (dpy, False);
10700 if (XSTRING (x_error_message_string)->data[0])
10701 error (format, XSTRING (x_error_message_string)->data);
10704 /* Nonzero if we had any X protocol errors
10705 since we did x_catch_errors on DPY. */
10708 x_had_errors_p (dpy)
10709 Display *dpy;
10711 /* Make sure to catch any errors incurred so far. */
10712 XSync (dpy, False);
10714 return XSTRING (x_error_message_string)->data[0] != 0;
10717 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10719 void
10720 x_clear_errors (dpy)
10721 Display *dpy;
10723 XSTRING (x_error_message_string)->data[0] = 0;
10726 /* Stop catching X protocol errors and let them make Emacs die.
10727 DPY should be the display that was passed to x_catch_errors.
10728 COUNT should be the value that was returned by
10729 the corresponding call to x_catch_errors. */
10731 void
10732 x_uncatch_errors (dpy, count)
10733 Display *dpy;
10734 int count;
10736 unbind_to (count, Qnil);
10739 #if 0
10740 static unsigned int x_wire_count;
10741 x_trace_wire ()
10743 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10745 #endif /* ! 0 */
10748 /* Handle SIGPIPE, which can happen when the connection to a server
10749 simply goes away. SIGPIPE is handled by x_connection_signal.
10750 Don't need to do anything, because the write which caused the
10751 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10752 which will do the appropriate cleanup for us. */
10754 static SIGTYPE
10755 x_connection_signal (signalnum) /* If we don't have an argument, */
10756 int signalnum; /* some compilers complain in signal calls. */
10758 #ifdef USG
10759 /* USG systems forget handlers when they are used;
10760 must reestablish each time */
10761 signal (signalnum, x_connection_signal);
10762 #endif /* USG */
10765 /* Handling X errors. */
10767 /* Handle the loss of connection to display DISPLAY. */
10769 static SIGTYPE
10770 x_connection_closed (display, error_message)
10771 Display *display;
10772 char *error_message;
10774 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10775 Lisp_Object frame, tail;
10777 /* Indicate that this display is dead. */
10779 #if 0 /* Closing the display caused a bus error on OpenWindows. */
10780 #ifdef USE_X_TOOLKIT
10781 XtCloseDisplay (display);
10782 #endif
10783 #endif
10785 dpyinfo->display = 0;
10787 /* First delete frames whose mini-buffers are on frames
10788 that are on the dead display. */
10789 FOR_EACH_FRAME (tail, frame)
10791 Lisp_Object minibuf_frame;
10792 minibuf_frame
10793 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10794 if (FRAME_X_P (XFRAME (frame))
10795 && FRAME_X_P (XFRAME (minibuf_frame))
10796 && ! EQ (frame, minibuf_frame)
10797 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10798 Fdelete_frame (frame, Qt);
10801 /* Now delete all remaining frames on the dead display.
10802 We are now sure none of these is used as the mini-buffer
10803 for another frame that we need to delete. */
10804 FOR_EACH_FRAME (tail, frame)
10805 if (FRAME_X_P (XFRAME (frame))
10806 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10808 /* Set this to t so that Fdelete_frame won't get confused
10809 trying to find a replacement. */
10810 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10811 Fdelete_frame (frame, Qt);
10814 if (dpyinfo)
10815 x_delete_display (dpyinfo);
10817 if (x_display_list == 0)
10819 fprintf (stderr, "%s\n", error_message);
10820 shut_down_emacs (0, 0, Qnil);
10821 exit (70);
10824 /* Ordinary stack unwind doesn't deal with these. */
10825 #ifdef SIGIO
10826 sigunblock (sigmask (SIGIO));
10827 #endif
10828 sigunblock (sigmask (SIGALRM));
10829 TOTALLY_UNBLOCK_INPUT;
10831 clear_waiting_for_input ();
10832 error ("%s", error_message);
10835 /* This is the usual handler for X protocol errors.
10836 It kills all frames on the display that we got the error for.
10837 If that was the only one, it prints an error message and kills Emacs. */
10839 static void
10840 x_error_quitter (display, error)
10841 Display *display;
10842 XErrorEvent *error;
10844 char buf[256], buf1[356];
10846 /* Note that there is no real way portable across R3/R4 to get the
10847 original error handler. */
10849 XGetErrorText (display, error->error_code, buf, sizeof (buf));
10850 sprintf (buf1, "X protocol error: %s on protocol request %d",
10851 buf, error->request_code);
10852 x_connection_closed (display, buf1);
10855 /* This is the first-level handler for X protocol errors.
10856 It calls x_error_quitter or x_error_catcher. */
10858 static int
10859 x_error_handler (display, error)
10860 Display *display;
10861 XErrorEvent *error;
10863 if (! NILP (x_error_message_string))
10864 x_error_catcher (display, error);
10865 else
10866 x_error_quitter (display, error);
10867 return 0;
10870 /* This is the handler for X IO errors, always.
10871 It kills all frames on the display that we lost touch with.
10872 If that was the only one, it prints an error message and kills Emacs. */
10874 static int
10875 x_io_error_quitter (display)
10876 Display *display;
10878 char buf[256];
10880 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10881 x_connection_closed (display, buf);
10882 return 0;
10885 /* Changing the font of the frame. */
10887 /* Give frame F the font named FONTNAME as its default font, and
10888 return the full name of that font. FONTNAME may be a wildcard
10889 pattern; in that case, we choose some font that fits the pattern.
10890 The return value shows which font we chose. */
10892 Lisp_Object
10893 x_new_font (f, fontname)
10894 struct frame *f;
10895 register char *fontname;
10897 struct font_info *fontp
10898 = FS_LOAD_FONT (f, 0, fontname, -1);
10900 if (!fontp)
10901 return Qnil;
10903 f->output_data.x->font = (XFontStruct *) (fontp->font);
10904 f->output_data.x->baseline_offset = fontp->baseline_offset;
10905 f->output_data.x->fontset = -1;
10907 /* Compute the scroll bar width in character columns. */
10908 if (f->scroll_bar_pixel_width > 0)
10910 int wid = FONT_WIDTH (f->output_data.x->font);
10911 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10913 else
10915 int wid = FONT_WIDTH (f->output_data.x->font);
10916 f->scroll_bar_cols = (14 + wid - 1) / wid;
10919 /* Now make the frame display the given font. */
10920 if (FRAME_X_WINDOW (f) != 0)
10922 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10923 f->output_data.x->font->fid);
10924 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10925 f->output_data.x->font->fid);
10926 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10927 f->output_data.x->font->fid);
10929 frame_update_line_height (f);
10930 x_set_window_size (f, 0, f->width, f->height);
10932 else
10933 /* If we are setting a new frame's font for the first time,
10934 there are no faces yet, so this font's height is the line height. */
10935 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
10937 return build_string (fontp->full_name);
10940 /* Give frame F the fontset named FONTSETNAME as its default font, and
10941 return the full name of that fontset. FONTSETNAME may be a wildcard
10942 pattern; in that case, we choose some fontset that fits the pattern.
10943 The return value shows which fontset we chose. */
10945 Lisp_Object
10946 x_new_fontset (f, fontsetname)
10947 struct frame *f;
10948 char *fontsetname;
10950 int fontset = fs_query_fontset (build_string (fontsetname), 0);
10951 Lisp_Object result;
10952 char *fontname;
10954 if (fontset < 0)
10955 return Qnil;
10957 if (f->output_data.x->fontset == fontset)
10958 /* This fontset is already set in frame F. There's nothing more
10959 to do. */
10960 return fontset_name (fontset);
10962 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
10964 if (!STRINGP (result))
10965 /* Can't load ASCII font. */
10966 return Qnil;
10968 /* Since x_new_font doesn't update any fontset information, do it now. */
10969 f->output_data.x->fontset = fontset;
10971 #ifdef HAVE_X_I18N
10972 if (FRAME_XIC (f)
10973 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
10974 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
10975 #endif
10977 return build_string (fontsetname);
10981 /***********************************************************************
10982 X Input Methods
10983 ***********************************************************************/
10985 #ifdef HAVE_X_I18N
10987 #ifdef HAVE_X11R6
10989 /* XIM destroy callback function, which is called whenever the
10990 connection to input method XIM dies. CLIENT_DATA contains a
10991 pointer to the x_display_info structure corresponding to XIM. */
10993 static void
10994 xim_destroy_callback (xim, client_data, call_data)
10995 XIM xim;
10996 XPointer client_data;
10997 XPointer call_data;
10999 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11000 Lisp_Object frame, tail;
11002 BLOCK_INPUT;
11004 /* No need to call XDestroyIC.. */
11005 FOR_EACH_FRAME (tail, frame)
11007 struct frame *f = XFRAME (frame);
11008 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11010 FRAME_XIC (f) = NULL;
11011 if (FRAME_XIC_FONTSET (f))
11013 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11014 FRAME_XIC_FONTSET (f) = NULL;
11019 /* No need to call XCloseIM. */
11020 dpyinfo->xim = NULL;
11021 XFree (dpyinfo->xim_styles);
11022 UNBLOCK_INPUT;
11025 #endif /* HAVE_X11R6 */
11027 /* Open the connection to the XIM server on display DPYINFO.
11028 RESOURCE_NAME is the resource name Emacs uses. */
11030 static void
11031 xim_open_dpy (dpyinfo, resource_name)
11032 struct x_display_info *dpyinfo;
11033 char *resource_name;
11035 XIM xim;
11037 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11038 dpyinfo->xim = xim;
11040 if (xim)
11042 #ifdef HAVE_X11R6
11043 XIMCallback destroy;
11044 #endif
11046 /* Get supported styles and XIM values. */
11047 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11049 #ifdef HAVE_X11R6
11050 destroy.callback = xim_destroy_callback;
11051 destroy.client_data = (XPointer)dpyinfo;
11052 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11053 #endif
11058 #ifdef HAVE_X11R6_XIM
11060 struct xim_inst_t
11062 struct x_display_info *dpyinfo;
11063 char *resource_name;
11066 /* XIM instantiate callback function, which is called whenever an XIM
11067 server is available. DISPLAY is teh display of the XIM.
11068 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11069 when the callback was registered. */
11071 static void
11072 xim_instantiate_callback (display, client_data, call_data)
11073 Display *display;
11074 XPointer client_data;
11075 XPointer call_data;
11077 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11078 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11080 /* We don't support multiple XIM connections. */
11081 if (dpyinfo->xim)
11082 return;
11084 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11086 /* Create XIC for the existing frames on the same display, as long
11087 as they have no XIC. */
11088 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11090 Lisp_Object tail, frame;
11092 BLOCK_INPUT;
11093 FOR_EACH_FRAME (tail, frame)
11095 struct frame *f = XFRAME (frame);
11097 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11098 if (FRAME_XIC (f) == NULL)
11100 create_frame_xic (f);
11101 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11102 xic_set_statusarea (f);
11103 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11105 struct window *w = XWINDOW (f->selected_window);
11106 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11111 UNBLOCK_INPUT;
11115 #endif /* HAVE_X11R6_XIM */
11118 /* Open a connection to the XIM server on display DPYINFO.
11119 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11120 connection only at the first time. On X11R6, open the connection
11121 in the XIM instantiate callback function. */
11123 static void
11124 xim_initialize (dpyinfo, resource_name)
11125 struct x_display_info *dpyinfo;
11126 char *resource_name;
11128 #ifdef HAVE_X11R6_XIM
11129 struct xim_inst_t *xim_inst;
11130 int len;
11132 dpyinfo->xim = NULL;
11133 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11134 xim_inst->dpyinfo = dpyinfo;
11135 len = strlen (resource_name);
11136 xim_inst->resource_name = (char *) xmalloc (len + 1);
11137 bcopy (resource_name, xim_inst->resource_name, len + 1);
11138 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11139 resource_name, EMACS_CLASS,
11140 xim_instantiate_callback,
11141 (XPointer)xim_inst);
11142 #else /* not HAVE_X11R6_XIM */
11143 dpyinfo->xim = NULL;
11144 xim_open_dpy (dpyinfo, resource_name);
11145 #endif /* not HAVE_X11R6_XIM */
11149 /* Close the connection to the XIM server on display DPYINFO. */
11151 static void
11152 xim_close_dpy (dpyinfo)
11153 struct x_display_info *dpyinfo;
11155 #ifdef HAVE_X11R6_XIM
11156 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11157 NULL, EMACS_CLASS,
11158 xim_instantiate_callback, NULL);
11159 #endif /* not HAVE_X11R6_XIM */
11160 XCloseIM (dpyinfo->xim);
11161 dpyinfo->xim = NULL;
11162 XFree (dpyinfo->xim_styles);
11165 #endif /* not HAVE_X11R6_XIM */
11169 /* Calculate the absolute position in frame F
11170 from its current recorded position values and gravity. */
11172 void
11173 x_calc_absolute_position (f)
11174 struct frame *f;
11176 Window child;
11177 int win_x = 0, win_y = 0;
11178 int flags = f->output_data.x->size_hint_flags;
11179 int this_window;
11181 /* We have nothing to do if the current position
11182 is already for the top-left corner. */
11183 if (! ((flags & XNegative) || (flags & YNegative)))
11184 return;
11186 #ifdef USE_X_TOOLKIT
11187 this_window = XtWindow (f->output_data.x->widget);
11188 #else
11189 this_window = FRAME_X_WINDOW (f);
11190 #endif
11192 /* Find the position of the outside upper-left corner of
11193 the inner window, with respect to the outer window.
11194 But do this only if we will need the results. */
11195 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11197 int count;
11199 BLOCK_INPUT;
11200 count = x_catch_errors (FRAME_X_DISPLAY (f));
11201 while (1)
11203 x_clear_errors (FRAME_X_DISPLAY (f));
11204 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11206 /* From-window, to-window. */
11207 this_window,
11208 f->output_data.x->parent_desc,
11210 /* From-position, to-position. */
11211 0, 0, &win_x, &win_y,
11213 /* Child of win. */
11214 &child);
11215 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11217 Window newroot, newparent = 0xdeadbeef;
11218 Window *newchildren;
11219 int nchildren;
11221 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11222 &newparent, &newchildren, &nchildren))
11223 break;
11225 XFree ((char *) newchildren);
11227 f->output_data.x->parent_desc = newparent;
11229 else
11230 break;
11233 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11234 UNBLOCK_INPUT;
11237 /* Treat negative positions as relative to the leftmost bottommost
11238 position that fits on the screen. */
11239 if (flags & XNegative)
11240 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11241 - 2 * f->output_data.x->border_width - win_x
11242 - PIXEL_WIDTH (f)
11243 + f->output_data.x->left_pos);
11245 if (flags & YNegative)
11247 int menubar_height = 0;
11249 #ifdef USE_X_TOOLKIT
11250 if (f->output_data.x->menubar_widget)
11251 menubar_height
11252 = (f->output_data.x->menubar_widget->core.height
11253 + f->output_data.x->menubar_widget->core.border_width);
11254 #endif
11256 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11257 - 2 * f->output_data.x->border_width
11258 - win_y
11259 - PIXEL_HEIGHT (f)
11260 - menubar_height
11261 + f->output_data.x->top_pos);
11264 /* The left_pos and top_pos
11265 are now relative to the top and left screen edges,
11266 so the flags should correspond. */
11267 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11270 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11271 to really change the position, and 0 when calling from
11272 x_make_frame_visible (in that case, XOFF and YOFF are the current
11273 position values). It is -1 when calling from x_set_frame_parameters,
11274 which means, do adjust for borders but don't change the gravity. */
11276 void
11277 x_set_offset (f, xoff, yoff, change_gravity)
11278 struct frame *f;
11279 register int xoff, yoff;
11280 int change_gravity;
11282 int modified_top, modified_left;
11284 if (change_gravity > 0)
11286 f->output_data.x->top_pos = yoff;
11287 f->output_data.x->left_pos = xoff;
11288 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11289 if (xoff < 0)
11290 f->output_data.x->size_hint_flags |= XNegative;
11291 if (yoff < 0)
11292 f->output_data.x->size_hint_flags |= YNegative;
11293 f->output_data.x->win_gravity = NorthWestGravity;
11295 x_calc_absolute_position (f);
11297 BLOCK_INPUT;
11298 x_wm_set_size_hint (f, (long) 0, 0);
11300 modified_left = f->output_data.x->left_pos;
11301 modified_top = f->output_data.x->top_pos;
11302 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11303 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11304 /* It is a mystery why we need to add the border_width here
11305 when the frame is already visible, but experiment says we do. */
11306 if (change_gravity != 0)
11308 modified_left += f->output_data.x->border_width;
11309 modified_top += f->output_data.x->border_width;
11311 #endif
11313 #ifdef USE_X_TOOLKIT
11314 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11315 modified_left, modified_top);
11316 #else /* not USE_X_TOOLKIT */
11317 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11318 modified_left, modified_top);
11319 #endif /* not USE_X_TOOLKIT */
11320 UNBLOCK_INPUT;
11323 /* Call this to change the size of frame F's x-window.
11324 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11325 for this size change and subsequent size changes.
11326 Otherwise we leave the window gravity unchanged. */
11328 void
11329 x_set_window_size (f, change_gravity, cols, rows)
11330 struct frame *f;
11331 int change_gravity;
11332 int cols, rows;
11334 #ifndef USE_X_TOOLKIT
11335 int pixelwidth, pixelheight;
11336 #endif
11338 BLOCK_INPUT;
11340 #ifdef USE_X_TOOLKIT
11342 /* The x and y position of the widget is clobbered by the
11343 call to XtSetValues within EmacsFrameSetCharSize.
11344 This is a real kludge, but I don't understand Xt so I can't
11345 figure out a correct fix. Can anyone else tell me? -- rms. */
11346 int xpos = f->output_data.x->widget->core.x;
11347 int ypos = f->output_data.x->widget->core.y;
11348 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11349 f->output_data.x->widget->core.x = xpos;
11350 f->output_data.x->widget->core.y = ypos;
11353 #else /* not USE_X_TOOLKIT */
11355 check_frame_size (f, &rows, &cols);
11356 f->output_data.x->vertical_scroll_bar_extra
11357 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11359 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11360 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11361 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11362 f->output_data.x->flags_areas_extra
11363 = FRAME_FLAGS_AREA_WIDTH (f);
11364 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11365 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11367 f->output_data.x->win_gravity = NorthWestGravity;
11368 x_wm_set_size_hint (f, (long) 0, 0);
11370 XSync (FRAME_X_DISPLAY (f), False);
11371 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11372 pixelwidth, pixelheight);
11374 /* Now, strictly speaking, we can't be sure that this is accurate,
11375 but the window manager will get around to dealing with the size
11376 change request eventually, and we'll hear how it went when the
11377 ConfigureNotify event gets here.
11379 We could just not bother storing any of this information here,
11380 and let the ConfigureNotify event set everything up, but that
11381 might be kind of confusing to the Lisp code, since size changes
11382 wouldn't be reported in the frame parameters until some random
11383 point in the future when the ConfigureNotify event arrives.
11385 We pass 1 for DELAY since we can't run Lisp code inside of
11386 a BLOCK_INPUT. */
11387 change_frame_size (f, rows, cols, 0, 1, 0);
11388 PIXEL_WIDTH (f) = pixelwidth;
11389 PIXEL_HEIGHT (f) = pixelheight;
11391 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11392 receive in the ConfigureNotify event; if we get what we asked
11393 for, then the event won't cause the screen to become garbaged, so
11394 we have to make sure to do it here. */
11395 SET_FRAME_GARBAGED (f);
11397 XFlush (FRAME_X_DISPLAY (f));
11399 #endif /* not USE_X_TOOLKIT */
11401 /* If cursor was outside the new size, mark it as off. */
11402 mark_window_cursors_off (XWINDOW (f->root_window));
11404 /* Clear out any recollection of where the mouse highlighting was,
11405 since it might be in a place that's outside the new frame size.
11406 Actually checking whether it is outside is a pain in the neck,
11407 so don't try--just let the highlighting be done afresh with new size. */
11408 cancel_mouse_face (f);
11410 UNBLOCK_INPUT;
11413 /* Mouse warping. */
11415 void
11416 x_set_mouse_position (f, x, y)
11417 struct frame *f;
11418 int x, y;
11420 int pix_x, pix_y;
11422 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11423 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11425 if (pix_x < 0) pix_x = 0;
11426 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11428 if (pix_y < 0) pix_y = 0;
11429 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11431 BLOCK_INPUT;
11433 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11434 0, 0, 0, 0, pix_x, pix_y);
11435 UNBLOCK_INPUT;
11438 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11440 void
11441 x_set_mouse_pixel_position (f, pix_x, pix_y)
11442 struct frame *f;
11443 int pix_x, pix_y;
11445 BLOCK_INPUT;
11447 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11448 0, 0, 0, 0, pix_x, pix_y);
11449 UNBLOCK_INPUT;
11452 /* focus shifting, raising and lowering. */
11454 void
11455 x_focus_on_frame (f)
11456 struct frame *f;
11458 #if 0 /* This proves to be unpleasant. */
11459 x_raise_frame (f);
11460 #endif
11461 #if 0
11462 /* I don't think that the ICCCM allows programs to do things like this
11463 without the interaction of the window manager. Whatever you end up
11464 doing with this code, do it to x_unfocus_frame too. */
11465 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11466 RevertToPointerRoot, CurrentTime);
11467 #endif /* ! 0 */
11470 void
11471 x_unfocus_frame (f)
11472 struct frame *f;
11474 #if 0
11475 /* Look at the remarks in x_focus_on_frame. */
11476 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11477 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11478 RevertToPointerRoot, CurrentTime);
11479 #endif /* ! 0 */
11482 /* Raise frame F. */
11484 void
11485 x_raise_frame (f)
11486 struct frame *f;
11488 if (f->async_visible)
11490 BLOCK_INPUT;
11491 #ifdef USE_X_TOOLKIT
11492 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11493 #else /* not USE_X_TOOLKIT */
11494 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11495 #endif /* not USE_X_TOOLKIT */
11496 XFlush (FRAME_X_DISPLAY (f));
11497 UNBLOCK_INPUT;
11501 /* Lower frame F. */
11503 void
11504 x_lower_frame (f)
11505 struct frame *f;
11507 if (f->async_visible)
11509 BLOCK_INPUT;
11510 #ifdef USE_X_TOOLKIT
11511 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11512 #else /* not USE_X_TOOLKIT */
11513 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11514 #endif /* not USE_X_TOOLKIT */
11515 XFlush (FRAME_X_DISPLAY (f));
11516 UNBLOCK_INPUT;
11520 static void
11521 XTframe_raise_lower (f, raise_flag)
11522 FRAME_PTR f;
11523 int raise_flag;
11525 if (raise_flag)
11526 x_raise_frame (f);
11527 else
11528 x_lower_frame (f);
11531 /* Change of visibility. */
11533 /* This tries to wait until the frame is really visible.
11534 However, if the window manager asks the user where to position
11535 the frame, this will return before the user finishes doing that.
11536 The frame will not actually be visible at that time,
11537 but it will become visible later when the window manager
11538 finishes with it. */
11540 void
11541 x_make_frame_visible (f)
11542 struct frame *f;
11544 Lisp_Object type;
11545 int original_top, original_left;
11547 BLOCK_INPUT;
11549 type = x_icon_type (f);
11550 if (!NILP (type))
11551 x_bitmap_icon (f, type);
11553 if (! FRAME_VISIBLE_P (f))
11555 /* We test FRAME_GARBAGED_P here to make sure we don't
11556 call x_set_offset a second time
11557 if we get to x_make_frame_visible a second time
11558 before the window gets really visible. */
11559 if (! FRAME_ICONIFIED_P (f)
11560 && ! f->output_data.x->asked_for_visible)
11561 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11563 f->output_data.x->asked_for_visible = 1;
11565 if (! EQ (Vx_no_window_manager, Qt))
11566 x_wm_set_window_state (f, NormalState);
11567 #ifdef USE_X_TOOLKIT
11568 /* This was XtPopup, but that did nothing for an iconified frame. */
11569 XtMapWidget (f->output_data.x->widget);
11570 #else /* not USE_X_TOOLKIT */
11571 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11572 #endif /* not USE_X_TOOLKIT */
11573 #if 0 /* This seems to bring back scroll bars in the wrong places
11574 if the window configuration has changed. They seem
11575 to come back ok without this. */
11576 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11577 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11578 #endif
11581 XFlush (FRAME_X_DISPLAY (f));
11583 /* Synchronize to ensure Emacs knows the frame is visible
11584 before we do anything else. We do this loop with input not blocked
11585 so that incoming events are handled. */
11587 Lisp_Object frame;
11588 int count;
11589 /* This must be before UNBLOCK_INPUT
11590 since events that arrive in response to the actions above
11591 will set it when they are handled. */
11592 int previously_visible = f->output_data.x->has_been_visible;
11594 original_left = f->output_data.x->left_pos;
11595 original_top = f->output_data.x->top_pos;
11597 /* This must come after we set COUNT. */
11598 UNBLOCK_INPUT;
11600 /* We unblock here so that arriving X events are processed. */
11602 /* Now move the window back to where it was "supposed to be".
11603 But don't do it if the gravity is negative.
11604 When the gravity is negative, this uses a position
11605 that is 3 pixels too low. Perhaps that's really the border width.
11607 Don't do this if the window has never been visible before,
11608 because the window manager may choose the position
11609 and we don't want to override it. */
11611 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11612 && f->output_data.x->win_gravity == NorthWestGravity
11613 && previously_visible)
11615 Drawable rootw;
11616 int x, y;
11617 unsigned int width, height, border, depth;
11619 BLOCK_INPUT;
11621 /* On some window managers (such as FVWM) moving an existing
11622 window, even to the same place, causes the window manager
11623 to introduce an offset. This can cause the window to move
11624 to an unexpected location. Check the geometry (a little
11625 slow here) and then verify that the window is in the right
11626 place. If the window is not in the right place, move it
11627 there, and take the potential window manager hit. */
11628 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11629 &rootw, &x, &y, &width, &height, &border, &depth);
11631 if (original_left != x || original_top != y)
11632 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11633 original_left, original_top);
11635 UNBLOCK_INPUT;
11638 XSETFRAME (frame, f);
11640 /* Wait until the frame is visible. Process X events until a
11641 MapNotify event has been seen, or until we think we won't get a
11642 MapNotify at all.. */
11643 for (count = input_signal_count + 10;
11644 input_signal_count < count && !FRAME_VISIBLE_P (f);)
11646 /* Force processing of queued events. */
11647 x_sync (f);
11649 /* Machines that do polling rather than SIGIO have been
11650 observed to go into a busy-wait here. So we'll fake an
11651 alarm signal to let the handler know that there's something
11652 to be read. We used to raise a real alarm, but it seems
11653 that the handler isn't always enabled here. This is
11654 probably a bug. */
11655 if (input_polling_used ())
11657 /* It could be confusing if a real alarm arrives while
11658 processing the fake one. Turn it off and let the
11659 handler reset it. */
11660 int old_poll_suppress_count = poll_suppress_count;
11661 poll_suppress_count = 1;
11662 poll_for_input_1 ();
11663 poll_suppress_count = old_poll_suppress_count;
11666 /* See if a MapNotify event has been processed. */
11667 FRAME_SAMPLE_VISIBILITY (f);
11672 /* Change from mapped state to withdrawn state. */
11674 /* Make the frame visible (mapped and not iconified). */
11676 void
11677 x_make_frame_invisible (f)
11678 struct frame *f;
11680 Window window;
11682 #ifdef USE_X_TOOLKIT
11683 /* Use the frame's outermost window, not the one we normally draw on. */
11684 window = XtWindow (f->output_data.x->widget);
11685 #else /* not USE_X_TOOLKIT */
11686 window = FRAME_X_WINDOW (f);
11687 #endif /* not USE_X_TOOLKIT */
11689 /* Don't keep the highlight on an invisible frame. */
11690 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11691 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11693 #if 0/* This might add unreliability; I don't trust it -- rms. */
11694 if (! f->async_visible && ! f->async_iconified)
11695 return;
11696 #endif
11698 BLOCK_INPUT;
11700 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11701 that the current position of the window is user-specified, rather than
11702 program-specified, so that when the window is mapped again, it will be
11703 placed at the same location, without forcing the user to position it
11704 by hand again (they have already done that once for this window.) */
11705 x_wm_set_size_hint (f, (long) 0, 1);
11707 #ifdef HAVE_X11R4
11709 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11710 DefaultScreen (FRAME_X_DISPLAY (f))))
11712 UNBLOCK_INPUT_RESIGNAL;
11713 error ("Can't notify window manager of window withdrawal");
11715 #else /* ! defined (HAVE_X11R4) */
11717 /* Tell the window manager what we're going to do. */
11718 if (! EQ (Vx_no_window_manager, Qt))
11720 XEvent unmap;
11722 unmap.xunmap.type = UnmapNotify;
11723 unmap.xunmap.window = window;
11724 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
11725 unmap.xunmap.from_configure = False;
11726 if (! XSendEvent (FRAME_X_DISPLAY (f),
11727 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11728 False,
11729 SubstructureRedirectMaskSubstructureNotifyMask,
11730 &unmap))
11732 UNBLOCK_INPUT_RESIGNAL;
11733 error ("Can't notify window manager of withdrawal");
11737 /* Unmap the window ourselves. Cheeky! */
11738 XUnmapWindow (FRAME_X_DISPLAY (f), window);
11739 #endif /* ! defined (HAVE_X11R4) */
11741 /* We can't distinguish this from iconification
11742 just by the event that we get from the server.
11743 So we can't win using the usual strategy of letting
11744 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11745 and synchronize with the server to make sure we agree. */
11746 f->visible = 0;
11747 FRAME_ICONIFIED_P (f) = 0;
11748 f->async_visible = 0;
11749 f->async_iconified = 0;
11751 x_sync (f);
11753 UNBLOCK_INPUT;
11756 /* Change window state from mapped to iconified. */
11758 void
11759 x_iconify_frame (f)
11760 struct frame *f;
11762 int result;
11763 Lisp_Object type;
11765 /* Don't keep the highlight on an invisible frame. */
11766 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11767 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11769 if (f->async_iconified)
11770 return;
11772 BLOCK_INPUT;
11774 FRAME_SAMPLE_VISIBILITY (f);
11776 type = x_icon_type (f);
11777 if (!NILP (type))
11778 x_bitmap_icon (f, type);
11780 #ifdef USE_X_TOOLKIT
11782 if (! FRAME_VISIBLE_P (f))
11784 if (! EQ (Vx_no_window_manager, Qt))
11785 x_wm_set_window_state (f, IconicState);
11786 /* This was XtPopup, but that did nothing for an iconified frame. */
11787 XtMapWidget (f->output_data.x->widget);
11788 /* The server won't give us any event to indicate
11789 that an invisible frame was changed to an icon,
11790 so we have to record it here. */
11791 f->iconified = 1;
11792 f->visible = 1;
11793 f->async_iconified = 1;
11794 f->async_visible = 0;
11795 UNBLOCK_INPUT;
11796 return;
11799 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11800 XtWindow (f->output_data.x->widget),
11801 DefaultScreen (FRAME_X_DISPLAY (f)));
11802 UNBLOCK_INPUT;
11804 if (!result)
11805 error ("Can't notify window manager of iconification");
11807 f->async_iconified = 1;
11808 f->async_visible = 0;
11811 BLOCK_INPUT;
11812 XFlush (FRAME_X_DISPLAY (f));
11813 UNBLOCK_INPUT;
11814 #else /* not USE_X_TOOLKIT */
11816 /* Make sure the X server knows where the window should be positioned,
11817 in case the user deiconifies with the window manager. */
11818 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
11819 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11821 /* Since we don't know which revision of X we're running, we'll use both
11822 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11824 /* X11R4: send a ClientMessage to the window manager using the
11825 WM_CHANGE_STATE type. */
11827 XEvent message;
11829 message.xclient.window = FRAME_X_WINDOW (f);
11830 message.xclient.type = ClientMessage;
11831 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
11832 message.xclient.format = 32;
11833 message.xclient.data.l[0] = IconicState;
11835 if (! XSendEvent (FRAME_X_DISPLAY (f),
11836 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11837 False,
11838 SubstructureRedirectMask | SubstructureNotifyMask,
11839 &message))
11841 UNBLOCK_INPUT_RESIGNAL;
11842 error ("Can't notify window manager of iconification");
11846 /* X11R3: set the initial_state field of the window manager hints to
11847 IconicState. */
11848 x_wm_set_window_state (f, IconicState);
11850 if (!FRAME_VISIBLE_P (f))
11852 /* If the frame was withdrawn, before, we must map it. */
11853 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11856 f->async_iconified = 1;
11857 f->async_visible = 0;
11859 XFlush (FRAME_X_DISPLAY (f));
11860 UNBLOCK_INPUT;
11861 #endif /* not USE_X_TOOLKIT */
11864 /* Destroy the X window of frame F. */
11866 void
11867 x_destroy_window (f)
11868 struct frame *f;
11870 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11872 BLOCK_INPUT;
11874 /* If a display connection is dead, don't try sending more
11875 commands to the X server. */
11876 if (dpyinfo->display != 0)
11878 if (f->output_data.x->icon_desc != 0)
11879 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
11880 #ifdef HAVE_X_I18N
11881 if (FRAME_XIC (f))
11882 free_frame_xic (f);
11883 #endif
11884 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
11885 #ifdef USE_X_TOOLKIT
11886 if (f->output_data.x->widget)
11887 XtDestroyWidget (f->output_data.x->widget);
11888 free_frame_menubar (f);
11889 #endif /* USE_X_TOOLKIT */
11891 free_frame_faces (f);
11892 XFlush (FRAME_X_DISPLAY (f));
11895 if (f->output_data.x->saved_menu_event)
11896 xfree (f->output_data.x->saved_menu_event);
11898 xfree (f->output_data.x);
11899 f->output_data.x = 0;
11900 if (f == dpyinfo->x_focus_frame)
11901 dpyinfo->x_focus_frame = 0;
11902 if (f == dpyinfo->x_focus_event_frame)
11903 dpyinfo->x_focus_event_frame = 0;
11904 if (f == dpyinfo->x_highlight_frame)
11905 dpyinfo->x_highlight_frame = 0;
11907 dpyinfo->reference_count--;
11909 if (f == dpyinfo->mouse_face_mouse_frame)
11911 dpyinfo->mouse_face_beg_row
11912 = dpyinfo->mouse_face_beg_col = -1;
11913 dpyinfo->mouse_face_end_row
11914 = dpyinfo->mouse_face_end_col = -1;
11915 dpyinfo->mouse_face_window = Qnil;
11916 dpyinfo->mouse_face_deferred_gc = 0;
11917 dpyinfo->mouse_face_mouse_frame = 0;
11920 UNBLOCK_INPUT;
11923 /* Setting window manager hints. */
11925 /* Set the normal size hints for the window manager, for frame F.
11926 FLAGS is the flags word to use--or 0 meaning preserve the flags
11927 that the window now has.
11928 If USER_POSITION is nonzero, we set the USPosition
11929 flag (this is useful when FLAGS is 0). */
11931 void
11932 x_wm_set_size_hint (f, flags, user_position)
11933 struct frame *f;
11934 long flags;
11935 int user_position;
11937 XSizeHints size_hints;
11939 #ifdef USE_X_TOOLKIT
11940 Arg al[2];
11941 int ac = 0;
11942 Dimension widget_width, widget_height;
11943 Window window = XtWindow (f->output_data.x->widget);
11944 #else /* not USE_X_TOOLKIT */
11945 Window window = FRAME_X_WINDOW (f);
11946 #endif /* not USE_X_TOOLKIT */
11948 /* Setting PMaxSize caused various problems. */
11949 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
11951 size_hints.x = f->output_data.x->left_pos;
11952 size_hints.y = f->output_data.x->top_pos;
11954 #ifdef USE_X_TOOLKIT
11955 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11956 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
11957 XtGetValues (f->output_data.x->widget, al, ac);
11958 size_hints.height = widget_height;
11959 size_hints.width = widget_width;
11960 #else /* not USE_X_TOOLKIT */
11961 size_hints.height = PIXEL_HEIGHT (f);
11962 size_hints.width = PIXEL_WIDTH (f);
11963 #endif /* not USE_X_TOOLKIT */
11965 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11966 size_hints.height_inc = f->output_data.x->line_height;
11967 size_hints.max_width
11968 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11969 size_hints.max_height
11970 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
11972 /* Calculate the base and minimum sizes.
11974 (When we use the X toolkit, we don't do it here.
11975 Instead we copy the values that the widgets are using, below.) */
11976 #ifndef USE_X_TOOLKIT
11978 int base_width, base_height;
11979 int min_rows = 0, min_cols = 0;
11981 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11982 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
11984 check_frame_size (f, &min_rows, &min_cols);
11986 /* The window manager uses the base width hints to calculate the
11987 current number of rows and columns in the frame while
11988 resizing; min_width and min_height aren't useful for this
11989 purpose, since they might not give the dimensions for a
11990 zero-row, zero-column frame.
11992 We use the base_width and base_height members if we have
11993 them; otherwise, we set the min_width and min_height members
11994 to the size for a zero x zero frame. */
11996 #ifdef HAVE_X11R4
11997 size_hints.flags |= PBaseSize;
11998 size_hints.base_width = base_width;
11999 size_hints.base_height = base_height;
12000 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12001 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12002 #else
12003 size_hints.min_width = base_width;
12004 size_hints.min_height = base_height;
12005 #endif
12008 /* If we don't need the old flags, we don't need the old hint at all. */
12009 if (flags)
12011 size_hints.flags |= flags;
12012 goto no_read;
12014 #endif /* not USE_X_TOOLKIT */
12017 XSizeHints hints; /* Sometimes I hate X Windows... */
12018 long supplied_return;
12019 int value;
12021 #ifdef HAVE_X11R4
12022 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12023 &supplied_return);
12024 #else
12025 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12026 #endif
12028 #ifdef USE_X_TOOLKIT
12029 size_hints.base_height = hints.base_height;
12030 size_hints.base_width = hints.base_width;
12031 size_hints.min_height = hints.min_height;
12032 size_hints.min_width = hints.min_width;
12033 #endif
12035 if (flags)
12036 size_hints.flags |= flags;
12037 else
12039 if (value == 0)
12040 hints.flags = 0;
12041 if (hints.flags & PSize)
12042 size_hints.flags |= PSize;
12043 if (hints.flags & PPosition)
12044 size_hints.flags |= PPosition;
12045 if (hints.flags & USPosition)
12046 size_hints.flags |= USPosition;
12047 if (hints.flags & USSize)
12048 size_hints.flags |= USSize;
12052 #ifndef USE_X_TOOLKIT
12053 no_read:
12054 #endif
12056 #ifdef PWinGravity
12057 size_hints.win_gravity = f->output_data.x->win_gravity;
12058 size_hints.flags |= PWinGravity;
12060 if (user_position)
12062 size_hints.flags &= ~ PPosition;
12063 size_hints.flags |= USPosition;
12065 #endif /* PWinGravity */
12067 #ifdef HAVE_X11R4
12068 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12069 #else
12070 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12071 #endif
12074 /* Used for IconicState or NormalState */
12076 void
12077 x_wm_set_window_state (f, state)
12078 struct frame *f;
12079 int state;
12081 #ifdef USE_X_TOOLKIT
12082 Arg al[1];
12084 XtSetArg (al[0], XtNinitialState, state);
12085 XtSetValues (f->output_data.x->widget, al, 1);
12086 #else /* not USE_X_TOOLKIT */
12087 Window window = FRAME_X_WINDOW (f);
12089 f->output_data.x->wm_hints.flags |= StateHint;
12090 f->output_data.x->wm_hints.initial_state = state;
12092 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12093 #endif /* not USE_X_TOOLKIT */
12096 void
12097 x_wm_set_icon_pixmap (f, pixmap_id)
12098 struct frame *f;
12099 int pixmap_id;
12101 Pixmap icon_pixmap;
12103 #ifndef USE_X_TOOLKIT
12104 Window window = FRAME_X_WINDOW (f);
12105 #endif
12107 if (pixmap_id > 0)
12109 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12110 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12112 else
12114 /* It seems there is no way to turn off use of an icon pixmap.
12115 The following line does it, only if no icon has yet been created,
12116 for some window managers. But with mwm it crashes.
12117 Some people say it should clear the IconPixmapHint bit in this case,
12118 but that doesn't work, and the X consortium said it isn't the
12119 right thing at all. Since there is no way to win,
12120 best to explicitly give up. */
12121 #if 0
12122 f->output_data.x->wm_hints.icon_pixmap = None;
12123 #else
12124 return;
12125 #endif
12128 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12131 Arg al[1];
12132 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12133 XtSetValues (f->output_data.x->widget, al, 1);
12136 #else /* not USE_X_TOOLKIT */
12138 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12139 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12141 #endif /* not USE_X_TOOLKIT */
12144 void
12145 x_wm_set_icon_position (f, icon_x, icon_y)
12146 struct frame *f;
12147 int icon_x, icon_y;
12149 #ifdef USE_X_TOOLKIT
12150 Window window = XtWindow (f->output_data.x->widget);
12151 #else
12152 Window window = FRAME_X_WINDOW (f);
12153 #endif
12155 f->output_data.x->wm_hints.flags |= IconPositionHint;
12156 f->output_data.x->wm_hints.icon_x = icon_x;
12157 f->output_data.x->wm_hints.icon_y = icon_y;
12159 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12163 /***********************************************************************
12164 Fonts
12165 ***********************************************************************/
12167 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12169 struct font_info *
12170 x_get_font_info (f, font_idx)
12171 FRAME_PTR f;
12172 int font_idx;
12174 return (FRAME_X_FONT_TABLE (f) + font_idx);
12178 /* Return a list of names of available fonts matching PATTERN on frame
12179 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12180 to be listed. Frame F NULL means we have not yet created any
12181 frame on X, and consult the first display in x_display_list.
12182 MAXNAMES sets a limit on how many fonts to match. */
12184 Lisp_Object
12185 x_list_fonts (f, pattern, size, maxnames)
12186 FRAME_PTR f;
12187 Lisp_Object pattern;
12188 int size;
12189 int maxnames;
12191 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12192 Lisp_Object tem, second_best;
12193 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12194 int try_XLoadQueryFont = 0;
12195 int count;
12197 patterns = Fassoc (pattern, Valternate_fontname_alist);
12198 if (NILP (patterns))
12199 patterns = Fcons (pattern, Qnil);
12201 if (maxnames == 1 && !size)
12202 /* We can return any single font matching PATTERN. */
12203 try_XLoadQueryFont = 1;
12205 for (; CONSP (patterns); patterns = XCDR (patterns))
12207 int num_fonts;
12208 char **names;
12210 pattern = XCAR (patterns);
12211 /* See if we cached the result for this particular query.
12212 The cache is an alist of the form:
12213 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12215 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12216 key = Fcons (pattern, make_number (maxnames)),
12217 !NILP (list = Fassoc (key, tem))))
12219 list = Fcdr_safe (list);
12220 /* We have a cashed list. Don't have to get the list again. */
12221 goto label_cached;
12224 /* At first, put PATTERN in the cache. */
12226 BLOCK_INPUT;
12227 count = x_catch_errors (dpy);
12229 if (try_XLoadQueryFont)
12231 XFontStruct *font;
12232 unsigned long value;
12234 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12235 if (x_had_errors_p (dpy))
12237 /* This error is perhaps due to insufficient memory on X
12238 server. Let's just ignore it. */
12239 font = NULL;
12240 x_clear_errors (dpy);
12243 if (font
12244 && XGetFontProperty (font, XA_FONT, &value))
12246 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12247 int len = strlen (name);
12248 char *tmp;
12250 /* If DXPC (a Differential X Protocol Compressor)
12251 Ver.3.7 is running, XGetAtomName will return null
12252 string. We must avoid such a name. */
12253 if (len == 0)
12254 try_XLoadQueryFont = 0;
12255 else
12257 num_fonts = 1;
12258 names = (char **) alloca (sizeof (char *));
12259 /* Some systems only allow alloca assigned to a
12260 simple var. */
12261 tmp = (char *) alloca (len + 1); names[0] = tmp;
12262 bcopy (name, names[0], len + 1);
12263 XFree (name);
12266 else
12267 try_XLoadQueryFont = 0;
12269 if (font)
12270 XFreeFont (dpy, font);
12273 if (!try_XLoadQueryFont)
12275 /* We try at least 10 fonts because XListFonts will return
12276 auto-scaled fonts at the head. */
12277 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12278 &num_fonts);
12279 if (x_had_errors_p (dpy))
12281 /* This error is perhaps due to insufficient memory on X
12282 server. Let's just ignore it. */
12283 names = NULL;
12284 x_clear_errors (dpy);
12288 x_uncatch_errors (dpy, count);
12289 UNBLOCK_INPUT;
12291 if (names)
12293 int i;
12295 /* Make a list of all the fonts we got back.
12296 Store that in the font cache for the display. */
12297 for (i = 0; i < num_fonts; i++)
12299 int width = 0;
12300 char *p = names[i];
12301 int average_width = -1, dashes = 0;
12303 /* Count the number of dashes in NAMES[I]. If there are
12304 14 dashes, and the field value following 12th dash
12305 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12306 is usually too ugly to be used for editing. Let's
12307 ignore it. */
12308 while (*p)
12309 if (*p++ == '-')
12311 dashes++;
12312 if (dashes == 7) /* PIXEL_SIZE field */
12313 width = atoi (p);
12314 else if (dashes == 12) /* AVERAGE_WIDTH field */
12315 average_width = atoi (p);
12317 if (dashes < 14 || average_width != 0)
12319 tem = build_string (names[i]);
12320 if (NILP (Fassoc (tem, list)))
12322 if (STRINGP (Vx_pixel_size_width_font_regexp)
12323 && ((fast_c_string_match_ignore_case
12324 (Vx_pixel_size_width_font_regexp, names[i]))
12325 >= 0))
12326 /* We can set the value of PIXEL_SIZE to the
12327 width of this font. */
12328 list = Fcons (Fcons (tem, make_number (width)), list);
12329 else
12330 /* For the moment, width is not known. */
12331 list = Fcons (Fcons (tem, Qnil), list);
12335 if (!try_XLoadQueryFont)
12336 XFreeFontNames (names);
12339 /* Now store the result in the cache. */
12340 if (f != NULL)
12341 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12342 = Fcons (Fcons (key, list),
12343 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12345 label_cached:
12346 if (NILP (list)) continue; /* Try the remaining alternatives. */
12348 newlist = second_best = Qnil;
12349 /* Make a list of the fonts that have the right width. */
12350 for (; CONSP (list); list = XCDR (list))
12352 int found_size;
12354 tem = XCAR (list);
12356 if (!CONSP (tem) || NILP (XCAR (tem)))
12357 continue;
12358 if (!size)
12360 newlist = Fcons (XCAR (tem), newlist);
12361 continue;
12364 if (!INTEGERP (XCDR (tem)))
12366 /* Since we have not yet known the size of this font, we
12367 must try slow function call XLoadQueryFont. */
12368 XFontStruct *thisinfo;
12370 BLOCK_INPUT;
12371 count = x_catch_errors (dpy);
12372 thisinfo = XLoadQueryFont (dpy,
12373 XSTRING (XCAR (tem))->data);
12374 if (x_had_errors_p (dpy))
12376 /* This error is perhaps due to insufficient memory on X
12377 server. Let's just ignore it. */
12378 thisinfo = NULL;
12379 x_clear_errors (dpy);
12381 x_uncatch_errors (dpy, count);
12382 UNBLOCK_INPUT;
12384 if (thisinfo)
12386 XCDR (tem)
12387 = (thisinfo->min_bounds.width == 0
12388 ? make_number (0)
12389 : make_number (thisinfo->max_bounds.width));
12390 XFreeFont (dpy, thisinfo);
12392 else
12393 /* For unknown reason, the previous call of XListFont had
12394 returned a font which can't be opened. Record the size
12395 as 0 not to try to open it again. */
12396 XCDR (tem) = make_number (0);
12399 found_size = XINT (XCDR (tem));
12400 if (found_size == size)
12401 newlist = Fcons (XCAR (tem), newlist);
12402 else if (found_size > 0)
12404 if (NILP (second_best))
12405 second_best = tem;
12406 else if (found_size < size)
12408 if (XINT (XCDR (second_best)) > size
12409 || XINT (XCDR (second_best)) < found_size)
12410 second_best = tem;
12412 else
12414 if (XINT (XCDR (second_best)) > size
12415 && XINT (XCDR (second_best)) > found_size)
12416 second_best = tem;
12420 if (!NILP (newlist))
12421 break;
12422 else if (!NILP (second_best))
12424 newlist = Fcons (XCAR (second_best), Qnil);
12425 break;
12429 return newlist;
12433 #if GLYPH_DEBUG
12435 /* Check that FONT is valid on frame F. It is if it can be found in F's
12436 font table. */
12438 static void
12439 x_check_font (f, font)
12440 struct frame *f;
12441 XFontStruct *font;
12443 int i;
12444 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12446 xassert (font != NULL);
12448 for (i = 0; i < dpyinfo->n_fonts; i++)
12449 if (dpyinfo->font_table[i].name
12450 && font == dpyinfo->font_table[i].font)
12451 break;
12453 xassert (i < dpyinfo->n_fonts);
12456 #endif /* GLYPH_DEBUG != 0 */
12458 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12459 Note: There are (broken) X fonts out there with invalid XFontStruct
12460 min_bounds contents. For example, handa@etl.go.jp reports that
12461 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12462 have font->min_bounds.width == 0. */
12464 static INLINE void
12465 x_font_min_bounds (font, w, h)
12466 XFontStruct *font;
12467 int *w, *h;
12469 *h = FONT_HEIGHT (font);
12470 *w = font->min_bounds.width;
12472 /* Try to handle the case where FONT->min_bounds has invalid
12473 contents. Since the only font known to have invalid min_bounds
12474 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12475 if (*w <= 0)
12476 *w = font->max_bounds.width;
12480 /* Compute the smallest character width and smallest font height over
12481 all fonts available on frame F. Set the members smallest_char_width
12482 and smallest_font_height in F's x_display_info structure to
12483 the values computed. Value is non-zero if smallest_font_height or
12484 smallest_char_width become smaller than they were before. */
12486 static int
12487 x_compute_min_glyph_bounds (f)
12488 struct frame *f;
12490 int i;
12491 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12492 XFontStruct *font;
12493 int old_width = dpyinfo->smallest_char_width;
12494 int old_height = dpyinfo->smallest_font_height;
12496 dpyinfo->smallest_font_height = 100000;
12497 dpyinfo->smallest_char_width = 100000;
12499 for (i = 0; i < dpyinfo->n_fonts; ++i)
12500 if (dpyinfo->font_table[i].name)
12502 struct font_info *fontp = dpyinfo->font_table + i;
12503 int w, h;
12505 font = (XFontStruct *) fontp->font;
12506 xassert (font != (XFontStruct *) ~0);
12507 x_font_min_bounds (font, &w, &h);
12509 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12510 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12513 xassert (dpyinfo->smallest_char_width > 0
12514 && dpyinfo->smallest_font_height > 0);
12516 return (dpyinfo->n_fonts == 1
12517 || dpyinfo->smallest_char_width < old_width
12518 || dpyinfo->smallest_font_height < old_height);
12522 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12523 pointer to the structure font_info while allocating it dynamically.
12524 If SIZE is 0, load any size of font.
12525 If loading is failed, return NULL. */
12527 struct font_info *
12528 x_load_font (f, fontname, size)
12529 struct frame *f;
12530 register char *fontname;
12531 int size;
12533 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12534 Lisp_Object font_names;
12535 int count;
12537 /* Get a list of all the fonts that match this name. Once we
12538 have a list of matching fonts, we compare them against the fonts
12539 we already have by comparing names. */
12540 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12542 if (!NILP (font_names))
12544 Lisp_Object tail;
12545 int i;
12547 for (i = 0; i < dpyinfo->n_fonts; i++)
12548 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12549 if (dpyinfo->font_table[i].name
12550 && (!strcmp (dpyinfo->font_table[i].name,
12551 XSTRING (XCAR (tail))->data)
12552 || !strcmp (dpyinfo->font_table[i].full_name,
12553 XSTRING (XCAR (tail))->data)))
12554 return (dpyinfo->font_table + i);
12557 /* Load the font and add it to the table. */
12559 char *full_name;
12560 XFontStruct *font;
12561 struct font_info *fontp;
12562 unsigned long value;
12563 int i;
12565 /* If we have found fonts by x_list_font, load one of them. If
12566 not, we still try to load a font by the name given as FONTNAME
12567 because XListFonts (called in x_list_font) of some X server has
12568 a bug of not finding a font even if the font surely exists and
12569 is loadable by XLoadQueryFont. */
12570 if (size > 0 && !NILP (font_names))
12571 fontname = (char *) XSTRING (XCAR (font_names))->data;
12573 BLOCK_INPUT;
12574 count = x_catch_errors (FRAME_X_DISPLAY (f));
12575 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12576 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12578 /* This error is perhaps due to insufficient memory on X
12579 server. Let's just ignore it. */
12580 font = NULL;
12581 x_clear_errors (FRAME_X_DISPLAY (f));
12583 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12584 UNBLOCK_INPUT;
12585 if (!font)
12586 return NULL;
12588 /* Find a free slot in the font table. */
12589 for (i = 0; i < dpyinfo->n_fonts; ++i)
12590 if (dpyinfo->font_table[i].name == NULL)
12591 break;
12593 /* If no free slot found, maybe enlarge the font table. */
12594 if (i == dpyinfo->n_fonts
12595 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12597 int sz;
12598 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12599 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12600 dpyinfo->font_table
12601 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12604 fontp = dpyinfo->font_table + i;
12605 if (i == dpyinfo->n_fonts)
12606 ++dpyinfo->n_fonts;
12608 /* Now fill in the slots of *FONTP. */
12609 BLOCK_INPUT;
12610 fontp->font = font;
12611 fontp->font_idx = i;
12612 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12613 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12615 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12616 full_name = 0;
12617 if (XGetFontProperty (font, XA_FONT, &value))
12619 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12620 char *p = name;
12621 int dashes = 0;
12623 /* Count the number of dashes in the "full name".
12624 If it is too few, this isn't really the font's full name,
12625 so don't use it.
12626 In X11R4, the fonts did not come with their canonical names
12627 stored in them. */
12628 while (*p)
12630 if (*p == '-')
12631 dashes++;
12632 p++;
12635 if (dashes >= 13)
12637 full_name = (char *) xmalloc (p - name + 1);
12638 bcopy (name, full_name, p - name + 1);
12641 XFree (name);
12644 if (full_name != 0)
12645 fontp->full_name = full_name;
12646 else
12647 fontp->full_name = fontp->name;
12649 fontp->size = font->max_bounds.width;
12650 fontp->height = FONT_HEIGHT (font);
12652 /* For some font, ascent and descent in max_bounds field is
12653 larger than the above value. */
12654 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12655 if (max_height > fontp->height)
12656 fontp->height = max_height;
12659 if (NILP (font_names))
12661 /* We come here because of a bug of XListFonts mentioned at
12662 the head of this block. Let's store this information in
12663 the cache for x_list_fonts. */
12664 Lisp_Object lispy_name = build_string (fontname);
12665 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12667 XCDR (dpyinfo->name_list_element)
12668 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12669 Fcons (Fcons (lispy_full_name,
12670 make_number (fontp->size)),
12671 Qnil)),
12672 XCDR (dpyinfo->name_list_element));
12673 if (full_name)
12674 XCDR (dpyinfo->name_list_element)
12675 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12676 Fcons (Fcons (lispy_full_name,
12677 make_number (fontp->size)),
12678 Qnil)),
12679 XCDR (dpyinfo->name_list_element));
12682 /* The slot `encoding' specifies how to map a character
12683 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12684 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12685 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
12686 2:0xA020..0xFF7F). For the moment, we don't know which charset
12687 uses this font. So, we set information in fontp->encoding[1]
12688 which is never used by any charset. If mapping can't be
12689 decided, set FONT_ENCODING_NOT_DECIDED. */
12690 fontp->encoding[1]
12691 = (font->max_byte1 == 0
12692 /* 1-byte font */
12693 ? (font->min_char_or_byte2 < 0x80
12694 ? (font->max_char_or_byte2 < 0x80
12695 ? 0 /* 0x20..0x7F */
12696 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
12697 : 1) /* 0xA0..0xFF */
12698 /* 2-byte font */
12699 : (font->min_byte1 < 0x80
12700 ? (font->max_byte1 < 0x80
12701 ? (font->min_char_or_byte2 < 0x80
12702 ? (font->max_char_or_byte2 < 0x80
12703 ? 0 /* 0x2020..0x7F7F */
12704 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
12705 : 3) /* 0x20A0..0x7FFF */
12706 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
12707 : (font->min_char_or_byte2 < 0x80
12708 ? (font->max_char_or_byte2 < 0x80
12709 ? 2 /* 0xA020..0xFF7F */
12710 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
12711 : 1))); /* 0xA0A0..0xFFFF */
12713 fontp->baseline_offset
12714 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12715 ? (long) value : 0);
12716 fontp->relative_compose
12717 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12718 ? (long) value : 0);
12719 fontp->default_ascent
12720 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12721 ? (long) value : 0);
12723 /* Set global flag fonts_changed_p to non-zero if the font loaded
12724 has a character with a smaller width than any other character
12725 before, or if the font loaded has a smalle>r height than any
12726 other font loaded before. If this happens, it will make a
12727 glyph matrix reallocation necessary. */
12728 fonts_changed_p = x_compute_min_glyph_bounds (f);
12729 UNBLOCK_INPUT;
12730 return fontp;
12735 /* Return a pointer to struct font_info of a font named FONTNAME for
12736 frame F. If no such font is loaded, return NULL. */
12738 struct font_info *
12739 x_query_font (f, fontname)
12740 struct frame *f;
12741 register char *fontname;
12743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12744 int i;
12746 for (i = 0; i < dpyinfo->n_fonts; i++)
12747 if (dpyinfo->font_table[i].name
12748 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12749 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
12750 return (dpyinfo->font_table + i);
12751 return NULL;
12755 /* Find a CCL program for a font specified by FONTP, and set the member
12756 `encoder' of the structure. */
12758 void
12759 x_find_ccl_program (fontp)
12760 struct font_info *fontp;
12762 Lisp_Object list, elt;
12764 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
12766 elt = XCAR (list);
12767 if (CONSP (elt)
12768 && STRINGP (XCAR (elt))
12769 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
12770 >= 0))
12771 break;
12773 if (! NILP (list))
12775 struct ccl_program *ccl
12776 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
12778 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
12779 xfree (ccl);
12780 else
12781 fontp->font_encoder = ccl;
12787 /***********************************************************************
12788 Initialization
12789 ***********************************************************************/
12791 #ifdef USE_X_TOOLKIT
12792 static XrmOptionDescRec emacs_options[] = {
12793 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12794 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12796 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12797 XrmoptionSepArg, NULL},
12798 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12800 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12801 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12802 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12803 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12804 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12805 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12806 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12808 #endif /* USE_X_TOOLKIT */
12810 static int x_initialized;
12812 #ifdef MULTI_KBOARD
12813 /* Test whether two display-name strings agree up to the dot that separates
12814 the screen number from the server number. */
12815 static int
12816 same_x_server (name1, name2)
12817 char *name1, *name2;
12819 int seen_colon = 0;
12820 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12821 int system_name_length = strlen (system_name);
12822 int length_until_period = 0;
12824 while (system_name[length_until_period] != 0
12825 && system_name[length_until_period] != '.')
12826 length_until_period++;
12828 /* Treat `unix' like an empty host name. */
12829 if (! strncmp (name1, "unix:", 5))
12830 name1 += 4;
12831 if (! strncmp (name2, "unix:", 5))
12832 name2 += 4;
12833 /* Treat this host's name like an empty host name. */
12834 if (! strncmp (name1, system_name, system_name_length)
12835 && name1[system_name_length] == ':')
12836 name1 += system_name_length;
12837 if (! strncmp (name2, system_name, system_name_length)
12838 && name2[system_name_length] == ':')
12839 name2 += system_name_length;
12840 /* Treat this host's domainless name like an empty host name. */
12841 if (! strncmp (name1, system_name, length_until_period)
12842 && name1[length_until_period] == ':')
12843 name1 += length_until_period;
12844 if (! strncmp (name2, system_name, length_until_period)
12845 && name2[length_until_period] == ':')
12846 name2 += length_until_period;
12848 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12850 if (*name1 == ':')
12851 seen_colon++;
12852 if (seen_colon && *name1 == '.')
12853 return 1;
12855 return (seen_colon
12856 && (*name1 == '.' || *name1 == '\0')
12857 && (*name2 == '.' || *name2 == '\0'));
12859 #endif
12861 struct x_display_info *
12862 x_term_init (display_name, xrm_option, resource_name)
12863 Lisp_Object display_name;
12864 char *xrm_option;
12865 char *resource_name;
12867 int connection;
12868 Display *dpy;
12869 struct x_display_info *dpyinfo;
12870 XrmDatabase xrdb;
12872 BLOCK_INPUT;
12874 if (!x_initialized)
12876 x_initialize ();
12877 x_initialized = 1;
12880 #ifdef USE_X_TOOLKIT
12881 /* weiner@footloose.sps.mot.com reports that this causes
12882 errors with X11R5:
12883 X protocol error: BadAtom (invalid Atom parameter)
12884 on protocol request 18skiloaf.
12885 So let's not use it until R6. */
12886 #ifdef HAVE_X11XTR6
12887 XtSetLanguageProc (NULL, NULL, NULL);
12888 #endif
12891 int argc = 0;
12892 char *argv[3];
12894 argv[0] = "";
12895 argc = 1;
12896 if (xrm_option)
12898 argv[argc++] = "-xrm";
12899 argv[argc++] = xrm_option;
12901 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12902 resource_name, EMACS_CLASS,
12903 emacs_options, XtNumber (emacs_options),
12904 &argc, argv);
12906 #ifdef HAVE_X11XTR6
12907 /* I think this is to compensate for XtSetLanguageProc. */
12908 fixup_locale ();
12909 #endif
12912 #else /* not USE_X_TOOLKIT */
12913 #ifdef HAVE_X11R5
12914 XSetLocaleModifiers ("");
12915 #endif
12916 dpy = XOpenDisplay (XSTRING (display_name)->data);
12917 #endif /* not USE_X_TOOLKIT */
12919 /* Detect failure. */
12920 if (dpy == 0)
12922 UNBLOCK_INPUT;
12923 return 0;
12926 /* We have definitely succeeded. Record the new connection. */
12928 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12930 #ifdef MULTI_KBOARD
12932 struct x_display_info *share;
12933 Lisp_Object tail;
12935 for (share = x_display_list, tail = x_display_name_list; share;
12936 share = share->next, tail = XCDR (tail))
12937 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
12938 XSTRING (display_name)->data))
12939 break;
12940 if (share)
12941 dpyinfo->kboard = share->kboard;
12942 else
12944 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12945 init_kboard (dpyinfo->kboard);
12946 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12948 char *vendor = ServerVendor (dpy);
12949 UNBLOCK_INPUT;
12950 dpyinfo->kboard->Vsystem_key_alist
12951 = call1 (Qvendor_specific_keysyms,
12952 build_string (vendor ? vendor : ""));
12953 BLOCK_INPUT;
12956 dpyinfo->kboard->next_kboard = all_kboards;
12957 all_kboards = dpyinfo->kboard;
12958 /* Don't let the initial kboard remain current longer than necessary.
12959 That would cause problems if a file loaded on startup tries to
12960 prompt in the mini-buffer. */
12961 if (current_kboard == initial_kboard)
12962 current_kboard = dpyinfo->kboard;
12964 dpyinfo->kboard->reference_count++;
12966 #endif
12968 /* Put this display on the chain. */
12969 dpyinfo->next = x_display_list;
12970 x_display_list = dpyinfo;
12972 /* Put it on x_display_name_list as well, to keep them parallel. */
12973 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12974 x_display_name_list);
12975 dpyinfo->name_list_element = XCAR (x_display_name_list);
12977 dpyinfo->display = dpy;
12979 #if 0
12980 XSetAfterFunction (x_current_display, x_trace_wire);
12981 #endif /* ! 0 */
12983 dpyinfo->x_id_name
12984 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12985 + STRING_BYTES (XSTRING (Vsystem_name))
12986 + 2);
12987 sprintf (dpyinfo->x_id_name, "%s@%s",
12988 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12990 /* Figure out which modifier bits mean what. */
12991 x_find_modifier_meanings (dpyinfo);
12993 /* Get the scroll bar cursor. */
12994 dpyinfo->vertical_scroll_bar_cursor
12995 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12997 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12998 resource_name, EMACS_CLASS);
12999 #ifdef HAVE_XRMSETDATABASE
13000 XrmSetDatabase (dpyinfo->display, xrdb);
13001 #else
13002 dpyinfo->display->db = xrdb;
13003 #endif
13004 /* Put the rdb where we can find it in a way that works on
13005 all versions. */
13006 dpyinfo->xrdb = xrdb;
13008 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13009 DefaultScreen (dpyinfo->display));
13010 select_visual (dpyinfo);
13011 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13012 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13013 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13014 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13015 dpyinfo->grabbed = 0;
13016 dpyinfo->reference_count = 0;
13017 dpyinfo->icon_bitmap_id = -1;
13018 dpyinfo->font_table = NULL;
13019 dpyinfo->n_fonts = 0;
13020 dpyinfo->font_table_size = 0;
13021 dpyinfo->bitmaps = 0;
13022 dpyinfo->bitmaps_size = 0;
13023 dpyinfo->bitmaps_last = 0;
13024 dpyinfo->scratch_cursor_gc = 0;
13025 dpyinfo->mouse_face_mouse_frame = 0;
13026 dpyinfo->mouse_face_deferred_gc = 0;
13027 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13028 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13029 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13030 dpyinfo->mouse_face_window = Qnil;
13031 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13032 dpyinfo->mouse_face_defer = 0;
13033 dpyinfo->x_focus_frame = 0;
13034 dpyinfo->x_focus_event_frame = 0;
13035 dpyinfo->x_highlight_frame = 0;
13036 dpyinfo->image_cache = make_image_cache ();
13038 /* See if a private colormap is requested. */
13039 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13041 if (dpyinfo->visual->class == PseudoColor)
13043 Lisp_Object value;
13044 value = display_x_get_resource (dpyinfo,
13045 build_string ("privateColormap"),
13046 build_string ("PrivateColormap"),
13047 Qnil, Qnil);
13048 if (STRINGP (value)
13049 && (!strcmp (XSTRING (value)->data, "true")
13050 || !strcmp (XSTRING (value)->data, "on")))
13051 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13054 else
13055 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13056 dpyinfo->visual, AllocNone);
13059 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13060 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13061 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13062 dpyinfo->resy = pixels * 25.4 / mm;
13063 pixels = DisplayWidth (dpyinfo->display, screen_number);
13064 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13065 dpyinfo->resx = pixels * 25.4 / mm;
13068 dpyinfo->Xatom_wm_protocols
13069 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13070 dpyinfo->Xatom_wm_take_focus
13071 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13072 dpyinfo->Xatom_wm_save_yourself
13073 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13074 dpyinfo->Xatom_wm_delete_window
13075 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13076 dpyinfo->Xatom_wm_change_state
13077 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13078 dpyinfo->Xatom_wm_configure_denied
13079 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13080 dpyinfo->Xatom_wm_window_moved
13081 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13082 dpyinfo->Xatom_editres
13083 = XInternAtom (dpyinfo->display, "Editres", False);
13084 dpyinfo->Xatom_CLIPBOARD
13085 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13086 dpyinfo->Xatom_TIMESTAMP
13087 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13088 dpyinfo->Xatom_TEXT
13089 = XInternAtom (dpyinfo->display, "TEXT", False);
13090 dpyinfo->Xatom_COMPOUND_TEXT
13091 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13092 dpyinfo->Xatom_DELETE
13093 = XInternAtom (dpyinfo->display, "DELETE", False);
13094 dpyinfo->Xatom_MULTIPLE
13095 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13096 dpyinfo->Xatom_INCR
13097 = XInternAtom (dpyinfo->display, "INCR", False);
13098 dpyinfo->Xatom_EMACS_TMP
13099 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13100 dpyinfo->Xatom_TARGETS
13101 = XInternAtom (dpyinfo->display, "TARGETS", False);
13102 dpyinfo->Xatom_NULL
13103 = XInternAtom (dpyinfo->display, "NULL", False);
13104 dpyinfo->Xatom_ATOM_PAIR
13105 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13106 /* For properties of font. */
13107 dpyinfo->Xatom_PIXEL_SIZE
13108 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13109 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13110 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13111 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13112 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13113 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13114 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13116 /* Ghostscript support. */
13117 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13118 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13120 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13121 False);
13123 dpyinfo->cut_buffers_initialized = 0;
13125 connection = ConnectionNumber (dpyinfo->display);
13126 dpyinfo->connection = connection;
13129 char null_bits[1];
13131 null_bits[0] = 0x00;
13133 dpyinfo->null_pixel
13134 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13135 null_bits, 1, 1, (long) 0, (long) 0,
13140 extern int gray_bitmap_width, gray_bitmap_height;
13141 extern unsigned char *gray_bitmap_bits;
13142 dpyinfo->gray
13143 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13144 gray_bitmap_bits,
13145 gray_bitmap_width, gray_bitmap_height,
13146 (unsigned long) 1, (unsigned long) 0, 1);
13149 #ifdef HAVE_X_I18N
13150 xim_initialize (dpyinfo, resource_name);
13151 #endif
13153 #ifdef subprocesses
13154 /* This is only needed for distinguishing keyboard and process input. */
13155 if (connection != 0)
13156 add_keyboard_wait_descriptor (connection);
13157 #endif
13159 #ifndef F_SETOWN_BUG
13160 #ifdef F_SETOWN
13161 #ifdef F_SETOWN_SOCK_NEG
13162 /* stdin is a socket here */
13163 fcntl (connection, F_SETOWN, -getpid ());
13164 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13165 fcntl (connection, F_SETOWN, getpid ());
13166 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13167 #endif /* ! defined (F_SETOWN) */
13168 #endif /* F_SETOWN_BUG */
13170 #ifdef SIGIO
13171 if (interrupt_input)
13172 init_sigio (connection);
13173 #endif /* ! defined (SIGIO) */
13175 #ifdef USE_LUCID
13176 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13177 /* Make sure that we have a valid font for dialog boxes
13178 so that Xt does not crash. */
13180 Display *dpy = dpyinfo->display;
13181 XrmValue d, fr, to;
13182 Font font;
13183 int count;
13185 d.addr = (XPointer)&dpy;
13186 d.size = sizeof (Display *);
13187 fr.addr = XtDefaultFont;
13188 fr.size = sizeof (XtDefaultFont);
13189 to.size = sizeof (Font *);
13190 to.addr = (XPointer)&font;
13191 count = x_catch_errors (dpy);
13192 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13193 abort ();
13194 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13195 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13196 x_uncatch_errors (dpy, count);
13198 #endif
13199 #endif
13201 /* See if we should run in synchronous mode. This is useful
13202 for debugging X code. */
13204 Lisp_Object value;
13205 value = display_x_get_resource (dpyinfo,
13206 build_string ("synchronous"),
13207 build_string ("Synchronous"),
13208 Qnil, Qnil);
13209 if (STRINGP (value)
13210 && (!strcmp (XSTRING (value)->data, "true")
13211 || !strcmp (XSTRING (value)->data, "on")))
13212 XSynchronize (dpyinfo->display, True);
13215 UNBLOCK_INPUT;
13217 return dpyinfo;
13220 /* Get rid of display DPYINFO, assuming all frames are already gone,
13221 and without sending any more commands to the X server. */
13223 void
13224 x_delete_display (dpyinfo)
13225 struct x_display_info *dpyinfo;
13227 delete_keyboard_wait_descriptor (dpyinfo->connection);
13229 /* Discard this display from x_display_name_list and x_display_list.
13230 We can't use Fdelq because that can quit. */
13231 if (! NILP (x_display_name_list)
13232 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13233 x_display_name_list = XCDR (x_display_name_list);
13234 else
13236 Lisp_Object tail;
13238 tail = x_display_name_list;
13239 while (CONSP (tail) && CONSP (XCDR (tail)))
13241 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13243 XCDR (tail) = XCDR (XCDR (tail));
13244 break;
13246 tail = XCDR (tail);
13250 if (next_noop_dpyinfo == dpyinfo)
13251 next_noop_dpyinfo = dpyinfo->next;
13253 if (x_display_list == dpyinfo)
13254 x_display_list = dpyinfo->next;
13255 else
13257 struct x_display_info *tail;
13259 for (tail = x_display_list; tail; tail = tail->next)
13260 if (tail->next == dpyinfo)
13261 tail->next = tail->next->next;
13264 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13265 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13266 XrmDestroyDatabase (dpyinfo->xrdb);
13267 #endif
13268 #endif
13269 #ifdef MULTI_KBOARD
13270 if (--dpyinfo->kboard->reference_count == 0)
13271 delete_kboard (dpyinfo->kboard);
13272 #endif
13273 #ifdef HAVE_X_I18N
13274 if (dpyinfo->xim)
13275 xim_close_dpy (dpyinfo);
13276 #endif
13278 xfree (dpyinfo->font_table);
13279 xfree (dpyinfo->x_id_name);
13280 xfree (dpyinfo);
13283 /* Set up use of X before we make the first connection. */
13285 static struct redisplay_interface x_redisplay_interface =
13287 x_produce_glyphs,
13288 x_write_glyphs,
13289 x_insert_glyphs,
13290 x_clear_end_of_line,
13291 x_scroll_run,
13292 x_after_update_window_line,
13293 x_update_window_begin,
13294 x_update_window_end,
13295 XTcursor_to,
13296 x_flush,
13297 x_get_glyph_overhangs,
13298 x_fix_overlapping_area
13301 void
13302 x_initialize ()
13304 rif = &x_redisplay_interface;
13306 clear_frame_hook = x_clear_frame;
13307 ins_del_lines_hook = x_ins_del_lines;
13308 change_line_highlight_hook = x_change_line_highlight;
13309 delete_glyphs_hook = x_delete_glyphs;
13310 ring_bell_hook = XTring_bell;
13311 reset_terminal_modes_hook = XTreset_terminal_modes;
13312 set_terminal_modes_hook = XTset_terminal_modes;
13313 update_begin_hook = x_update_begin;
13314 update_end_hook = x_update_end;
13315 set_terminal_window_hook = XTset_terminal_window;
13316 read_socket_hook = XTread_socket;
13317 frame_up_to_date_hook = XTframe_up_to_date;
13318 reassert_line_highlight_hook = XTreassert_line_highlight;
13319 mouse_position_hook = XTmouse_position;
13320 frame_rehighlight_hook = XTframe_rehighlight;
13321 frame_raise_lower_hook = XTframe_raise_lower;
13322 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13323 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13324 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13325 judge_scroll_bars_hook = XTjudge_scroll_bars;
13326 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13328 scroll_region_ok = 1; /* we'll scroll partial frames */
13329 char_ins_del_ok = 0; /* just as fast to write the line */
13330 line_ins_del_ok = 1; /* we'll just blt 'em */
13331 fast_clear_end_of_line = 1; /* X does this well */
13332 memory_below_frame = 0; /* we don't remember what scrolls
13333 off the bottom */
13334 baud_rate = 19200;
13336 x_noop_count = 0;
13337 last_tool_bar_item = -1;
13338 any_help_event_p = 0;
13340 /* Try to use interrupt input; if we can't, then start polling. */
13341 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13343 #ifdef USE_X_TOOLKIT
13344 XtToolkitInitialize ();
13345 Xt_app_con = XtCreateApplicationContext ();
13346 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13348 /* Install an asynchronous timer that processes Xt timeout events
13349 every 0.1s. This is necessary because some widget sets use
13350 timeouts internally, for example the LessTif menu bar, or the
13351 Xaw3d scroll bar. When Xt timouts aren't processed, these
13352 widgets don't behave normally. */
13354 EMACS_TIME interval;
13355 EMACS_SET_SECS_USECS (interval, 0, 100000);
13356 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13358 #endif
13360 #if USE_TOOLKIT_SCROLL_BARS
13361 xaw3d_arrow_scroll = False;
13362 xaw3d_pick_top = True;
13363 #endif
13365 /* Note that there is no real way portable across R3/R4 to get the
13366 original error handler. */
13367 XSetErrorHandler (x_error_handler);
13368 XSetIOErrorHandler (x_io_error_quitter);
13370 /* Disable Window Change signals; they are handled by X events. */
13371 #ifdef SIGWINCH
13372 signal (SIGWINCH, SIG_DFL);
13373 #endif /* ! defined (SIGWINCH) */
13375 signal (SIGPIPE, x_connection_signal);
13379 void
13380 syms_of_xterm ()
13382 staticpro (&x_error_message_string);
13383 x_error_message_string = Qnil;
13385 staticpro (&x_display_name_list);
13386 x_display_name_list = Qnil;
13388 staticpro (&last_mouse_scroll_bar);
13389 last_mouse_scroll_bar = Qnil;
13391 staticpro (&Qvendor_specific_keysyms);
13392 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13394 staticpro (&last_mouse_press_frame);
13395 last_mouse_press_frame = Qnil;
13397 staticpro (&help_echo);
13398 help_echo = Qnil;
13399 staticpro (&previous_help_echo);
13400 previous_help_echo = Qnil;
13402 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13403 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13404 For example, if a block cursor is over a tab, it will be drawn as\n\
13405 wide as that tab on the display.");
13406 x_stretch_cursor_p = 0;
13408 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13409 "If not nil, Emacs uses toolkit scroll bars.");
13410 #if USE_TOOLKIT_SCROLL_BARS
13411 x_toolkit_scroll_bars_p = 1;
13412 #else
13413 x_toolkit_scroll_bars_p = 0;
13414 #endif
13416 staticpro (&last_mouse_motion_frame);
13417 last_mouse_motion_frame = Qnil;
13420 #endif /* not HAVE_X_WINDOWS */