(backup-buffer): Cope if file-modes returns nil.
[emacs.git] / src / xterm.c
blobc5b0a8b00d31c5e91e9fe2309159bce318d5aeb5
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
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 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
57 #include "systty.h"
58 #include "systime.h"
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "process.h"
86 #include "atimer.h"
87 #include "keymap.h"
89 #ifdef USE_X_TOOLKIT
90 #include <X11/Shell.h>
91 #endif
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
100 #ifdef USE_LUCID
101 extern int xlwmenu_window_p P_ ((Widget w, Window window));
102 extern void xlwmenu_redisplay P_ ((Widget));
103 #endif
105 #ifdef USE_X_TOOLKIT
107 extern void free_frame_menubar P_ ((struct frame *));
108 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 #define HACK_EDITRES
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
116 /* Include toolkit specific headers for the scroll bar widget. */
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.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 #define abs(x) ((x) < 0 ? -(x) : (x))
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
158 /* Fringe bitmaps. */
160 enum fringe_bitmap_type
162 NO_FRINGE_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
174 #define zv_width 8
175 #define zv_height 72
176 #define zv_period 3
177 static unsigned char zv_bits[] = {
178 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
179 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
180 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
181 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
182 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
183 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
187 /* An arrow like this: `<-'. */
189 #define left_width 8
190 #define left_height 8
191 static unsigned char left_bits[] = {
192 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
194 /* Right truncation arrow bitmap `->'. */
196 #define right_width 8
197 #define right_height 8
198 static unsigned char right_bits[] = {
199 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
201 /* Marker for continued lines. */
203 #define continued_width 8
204 #define continued_height 8
205 static unsigned char continued_bits[] = {
206 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
208 /* Marker for continuation lines. */
210 #define continuation_width 8
211 #define continuation_height 8
212 static unsigned char continuation_bits[] = {
213 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
215 /* Overlay arrow bitmap. */
217 #if 0
218 /* A bomb. */
219 #define ov_width 8
220 #define ov_height 8
221 static unsigned char ov_bits[] = {
222 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
223 #else
224 /* A triangular arrow. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230 #endif
232 extern Lisp_Object Qhelp_echo;
235 /* Non-nil means Emacs uses toolkit scroll bars. */
237 Lisp_Object Vx_toolkit_scroll_bars;
239 /* If a string, XTread_socket generates an event to display that string.
240 (The display is done in read_char.) */
242 static Lisp_Object help_echo;
243 static Lisp_Object help_echo_window;
244 static Lisp_Object help_echo_object;
245 static int help_echo_pos;
247 /* Temporary variable for XTread_socket. */
249 static Lisp_Object previous_help_echo;
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
254 static int any_help_event_p;
256 /* Non-zero means autoselect window with the mouse cursor. */
258 int mouse_autoselect_window;
260 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
261 static Lisp_Object last_window;
263 /* Non-zero means draw block and hollow cursor as wide as the glyph
264 under it. For example, if a block cursor is over a tab, it will be
265 drawn as wide as that tab on the display. */
267 int x_stretch_cursor_p;
269 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
271 int x_use_underline_position_properties;
273 /* This is a chain of structures for all the X displays currently in
274 use. */
276 struct x_display_info *x_display_list;
278 /* This is a list of cons cells, each of the form (NAME
279 . FONT-LIST-CACHE), one for each element of x_display_list and in
280 the same order. NAME is the name of the frame. FONT-LIST-CACHE
281 records previous values returned by x-list-fonts. */
283 Lisp_Object x_display_name_list;
285 /* Frame being updated by update_frame. This is declared in term.c.
286 This is set by update_begin and looked at by all the XT functions.
287 It is zero while not inside an update. In that case, the XT
288 functions assume that `selected_frame' is the frame to apply to. */
290 extern struct frame *updating_frame;
292 /* This is a frame waiting to be auto-raised, within XTread_socket. */
294 struct frame *pending_autoraise_frame;
296 #ifdef USE_X_TOOLKIT
297 /* The application context for Xt use. */
298 XtAppContext Xt_app_con;
299 static String Xt_default_resources[] = {0};
300 #endif /* USE_X_TOOLKIT */
302 /* Nominal cursor position -- where to draw output.
303 HPOS and VPOS are window relative glyph matrix coordinates.
304 X and Y are window relative pixel coordinates. */
306 struct cursor_pos output_cursor;
308 /* Non-zero means user is interacting with a toolkit scroll bar. */
310 static int toolkit_scroll_bar_interaction;
312 /* Mouse movement.
314 Formerly, we used PointerMotionHintMask (in standard_event_mask)
315 so that we would have to call XQueryPointer after each MotionNotify
316 event to ask for another such event. However, this made mouse tracking
317 slow, and there was a bug that made it eventually stop.
319 Simply asking for MotionNotify all the time seems to work better.
321 In order to avoid asking for motion events and then throwing most
322 of them away or busy-polling the server for mouse positions, we ask
323 the server for pointer motion hints. This means that we get only
324 one event per group of mouse movements. "Groups" are delimited by
325 other kinds of events (focus changes and button clicks, for
326 example), or by XQueryPointer calls; when one of these happens, we
327 get another MotionNotify event the next time the mouse moves. This
328 is at least as efficient as getting motion events when mouse
329 tracking is on, and I suspect only negligibly worse when tracking
330 is off. */
332 /* Where the mouse was last time we reported a mouse event. */
334 FRAME_PTR last_mouse_frame;
335 static XRectangle last_mouse_glyph;
336 static Lisp_Object last_mouse_press_frame;
338 /* The scroll bar in which the last X motion event occurred.
340 If the last X motion event occurred in a scroll bar, we set this so
341 XTmouse_position can know whether to report a scroll bar motion or
342 an ordinary motion.
344 If the last X motion event didn't occur in a scroll bar, we set
345 this to Qnil, to tell XTmouse_position to return an ordinary motion
346 event. */
348 static Lisp_Object last_mouse_scroll_bar;
350 /* This is a hack. We would really prefer that XTmouse_position would
351 return the time associated with the position it returns, but there
352 doesn't seem to be any way to wrest the time-stamp from the server
353 along with the position query. So, we just keep track of the time
354 of the last movement we received, and return that in hopes that
355 it's somewhat accurate. */
357 static Time last_mouse_movement_time;
359 /* Incremented by XTread_socket whenever it really tries to read
360 events. */
362 #ifdef __STDC__
363 static int volatile input_signal_count;
364 #else
365 static int input_signal_count;
366 #endif
368 /* Used locally within XTread_socket. */
370 static int x_noop_count;
372 /* Initial values of argv and argc. */
374 extern char **initial_argv;
375 extern int initial_argc;
377 extern Lisp_Object Vcommand_line_args, Vsystem_name;
379 /* Tells if a window manager is present or not. */
381 extern Lisp_Object Vx_no_window_manager;
383 extern Lisp_Object Qface, Qmouse_face, Qeql;
385 extern int errno;
387 /* A mask of extra modifier bits to put into every keyboard char. */
389 extern EMACS_INT extra_keyboard_modifiers;
391 /* The keysyms to use for the various modifiers. */
393 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
394 Lisp_Object Vx_keysym_table;
395 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
397 static Lisp_Object Qvendor_specific_keysyms;
398 static Lisp_Object Qlatin_1, Qutf_8;
400 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
401 extern Lisp_Object x_icon_type P_ ((struct frame *));
404 /* Enumeration for overriding/changing the face to use for drawing
405 glyphs in x_draw_glyphs. */
407 enum draw_glyphs_face
409 DRAW_NORMAL_TEXT,
410 DRAW_INVERSE_VIDEO,
411 DRAW_CURSOR,
412 DRAW_MOUSE_FACE,
413 DRAW_IMAGE_RAISED,
414 DRAW_IMAGE_SUNKEN
417 static int cursor_in_mouse_face_p P_ ((struct window *));
418 static int clear_mouse_face P_ ((struct x_display_info *));
419 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
420 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
421 static const XColor *x_color_cells P_ ((Display *, int *));
422 static void x_update_window_end P_ ((struct window *, int, int));
423 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
424 void x_delete_display P_ ((struct x_display_info *));
425 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
426 unsigned));
427 static int fast_find_position P_ ((struct window *, int, int *, int *,
428 int *, int *, Lisp_Object));
429 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
430 int *, int *, int *, int *, int));
431 static void set_output_cursor P_ ((struct cursor_pos *));
432 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
433 int *, int *, int *, int));
434 static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
435 int, int));
436 static void note_mouse_highlight P_ ((struct frame *, int, int));
437 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
438 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
439 static void show_mouse_face P_ ((struct x_display_info *,
440 enum draw_glyphs_face));
441 static int x_io_error_quitter P_ ((Display *));
442 int x_catch_errors P_ ((Display *));
443 void x_uncatch_errors P_ ((Display *, int));
444 void x_lower_frame P_ ((struct frame *));
445 void x_scroll_bar_clear P_ ((struct frame *));
446 int x_had_errors_p P_ ((Display *));
447 void x_wm_set_size_hint P_ ((struct frame *, long, int));
448 void x_raise_frame P_ ((struct frame *));
449 void x_set_window_size P_ ((struct frame *, int, int, int));
450 void x_wm_set_window_state P_ ((struct frame *, int));
451 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
452 void x_initialize P_ ((void));
453 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
454 static int x_compute_min_glyph_bounds P_ ((struct frame *));
455 static void x_draw_phys_cursor_glyph P_ ((struct window *,
456 struct glyph_row *,
457 enum draw_glyphs_face));
458 static void x_update_end P_ ((struct frame *));
459 static void XTframe_up_to_date P_ ((struct frame *));
460 static void XTset_terminal_modes P_ ((void));
461 static void XTreset_terminal_modes P_ ((void));
462 static void XTcursor_to P_ ((int, int, int, int));
463 static void x_write_glyphs P_ ((struct glyph *, int));
464 static void x_clear_end_of_line P_ ((int));
465 static void x_clear_frame P_ ((void));
466 static void x_clear_cursor P_ ((struct window *));
467 static void frame_highlight P_ ((struct frame *));
468 static void frame_unhighlight P_ ((struct frame *));
469 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
470 static int x_focus_changed P_ ((int,
471 int,
472 struct x_display_info *,
473 struct frame *,
474 struct input_event *,
475 int));
476 static int x_detect_focus_change P_ ((struct x_display_info *,
477 XEvent *,
478 struct input_event *,
479 int));
480 static void XTframe_rehighlight P_ ((struct frame *));
481 static void x_frame_rehighlight P_ ((struct x_display_info *));
482 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
483 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
484 enum text_cursor_kinds));
485 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
486 XRectangle *));
487 static void expose_frame P_ ((struct frame *, int, int, int, int));
488 static int expose_window_tree P_ ((struct window *, XRectangle *));
489 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
490 struct glyph_row *));
491 static int expose_window P_ ((struct window *, XRectangle *));
492 static void expose_area P_ ((struct window *, struct glyph_row *,
493 XRectangle *, enum glyph_row_area));
494 static int expose_line P_ ((struct window *, struct glyph_row *,
495 XRectangle *));
496 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
497 static void x_update_window_cursor P_ ((struct window *, int));
498 static void x_erase_phys_cursor P_ ((struct window *));
499 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
500 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
501 enum fringe_bitmap_type, int left_p));
503 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
504 GC, int));
505 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
506 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
507 static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
508 int, int, int, int));
509 static void x_flush P_ ((struct frame *f));
510 static void x_update_begin P_ ((struct frame *));
511 static void x_update_window_begin P_ ((struct window *));
512 static void x_draw_vertical_border P_ ((struct window *));
513 static void x_after_update_window_line P_ ((struct glyph_row *));
514 static INLINE void take_vertical_position_into_account P_ ((struct it *));
515 static void x_produce_stretch_glyph P_ ((struct it *));
516 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
517 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
518 enum scroll_bar_part *,
519 Lisp_Object *, Lisp_Object *,
520 unsigned long *));
521 static void x_check_fullscreen P_ ((struct frame *));
522 static void x_check_fullscreen_move P_ ((struct frame *));
524 /* Flush display of frame F, or of all frames if F is null. */
526 static void
527 x_flush (f)
528 struct frame *f;
530 BLOCK_INPUT;
531 if (f == NULL)
533 Lisp_Object rest, frame;
534 FOR_EACH_FRAME (rest, frame)
535 x_flush (XFRAME (frame));
537 else if (FRAME_X_P (f))
538 XFlush (FRAME_X_DISPLAY (f));
539 UNBLOCK_INPUT;
543 /* Remove calls to XFlush by defining XFlush to an empty replacement.
544 Calls to XFlush should be unnecessary because the X output buffer
545 is flushed automatically as needed by calls to XPending,
546 XNextEvent, or XWindowEvent according to the XFlush man page.
547 XTread_socket calls XPending. Removing XFlush improves
548 performance. */
550 #define XFlush(DISPLAY) (void) 0
553 /***********************************************************************
554 Debugging
555 ***********************************************************************/
557 #if 0
559 /* This is a function useful for recording debugging information about
560 the sequence of occurrences in this file. */
562 struct record
564 char *locus;
565 int type;
568 struct record event_record[100];
570 int event_record_index;
572 record_event (locus, type)
573 char *locus;
574 int type;
576 if (event_record_index == sizeof (event_record) / sizeof (struct record))
577 event_record_index = 0;
579 event_record[event_record_index].locus = locus;
580 event_record[event_record_index].type = type;
581 event_record_index++;
584 #endif /* 0 */
588 /* Return the struct x_display_info corresponding to DPY. */
590 struct x_display_info *
591 x_display_info_for_display (dpy)
592 Display *dpy;
594 struct x_display_info *dpyinfo;
596 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
597 if (dpyinfo->display == dpy)
598 return dpyinfo;
600 return 0;
605 /***********************************************************************
606 Starting and ending an update
607 ***********************************************************************/
609 /* Start an update of frame F. This function is installed as a hook
610 for update_begin, i.e. it is called when update_begin is called.
611 This function is called prior to calls to x_update_window_begin for
612 each window being updated. Currently, there is nothing to do here
613 because all interesting stuff is done on a window basis. */
615 static void
616 x_update_begin (f)
617 struct frame *f;
619 /* Nothing to do. */
623 /* Start update of window W. Set the global variable updated_window
624 to the window being updated and set output_cursor to the cursor
625 position of W. */
627 static void
628 x_update_window_begin (w)
629 struct window *w;
631 struct frame *f = XFRAME (WINDOW_FRAME (w));
632 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
634 updated_window = w;
635 set_output_cursor (&w->cursor);
637 BLOCK_INPUT;
639 if (f == display_info->mouse_face_mouse_frame)
641 /* Don't do highlighting for mouse motion during the update. */
642 display_info->mouse_face_defer = 1;
644 /* If F needs to be redrawn, simply forget about any prior mouse
645 highlighting. */
646 if (FRAME_GARBAGED_P (f))
647 display_info->mouse_face_window = Qnil;
649 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
650 their mouse_face_p flag set, which means that they are always
651 unequal to rows in a desired matrix which never have that
652 flag set. So, rows containing mouse-face glyphs are never
653 scrolled, and we don't have to switch the mouse highlight off
654 here to prevent it from being scrolled. */
656 /* Can we tell that this update does not affect the window
657 where the mouse highlight is? If so, no need to turn off.
658 Likewise, don't do anything if the frame is garbaged;
659 in that case, the frame's current matrix that we would use
660 is all wrong, and we will redisplay that line anyway. */
661 if (!NILP (display_info->mouse_face_window)
662 && w == XWINDOW (display_info->mouse_face_window))
664 int i;
666 for (i = 0; i < w->desired_matrix->nrows; ++i)
667 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
668 break;
670 if (i < w->desired_matrix->nrows)
671 clear_mouse_face (display_info);
673 #endif /* 0 */
676 UNBLOCK_INPUT;
680 /* Draw a vertical window border to the right of window W if W doesn't
681 have vertical scroll bars. */
683 static void
684 x_draw_vertical_border (w)
685 struct window *w;
687 struct frame *f = XFRAME (WINDOW_FRAME (w));
689 /* Redraw borders between horizontally adjacent windows. Don't
690 do it for frames with vertical scroll bars because either the
691 right scroll bar of a window, or the left scroll bar of its
692 neighbor will suffice as a border. */
693 if (!WINDOW_RIGHTMOST_P (w)
694 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
696 int x0, x1, y0, y1;
698 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
699 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
700 y1 -= 1;
702 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
703 f->output_data.x->normal_gc, x1, y0, x1, y1);
708 /* End update of window W (which is equal to updated_window).
710 Draw vertical borders between horizontally adjacent windows, and
711 display W's cursor if CURSOR_ON_P is non-zero.
713 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
714 glyphs in mouse-face were overwritten. In that case we have to
715 make sure that the mouse-highlight is properly redrawn.
717 W may be a menu bar pseudo-window in case we don't have X toolkit
718 support. Such windows don't have a cursor, so don't display it
719 here. */
721 static void
722 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
723 struct window *w;
724 int cursor_on_p, mouse_face_overwritten_p;
726 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
728 if (!w->pseudo_window_p)
730 BLOCK_INPUT;
732 if (cursor_on_p)
733 x_display_and_set_cursor (w, 1, output_cursor.hpos,
734 output_cursor.vpos,
735 output_cursor.x, output_cursor.y);
737 x_draw_vertical_border (w);
738 UNBLOCK_INPUT;
741 /* If a row with mouse-face was overwritten, arrange for
742 XTframe_up_to_date to redisplay the mouse highlight. */
743 if (mouse_face_overwritten_p)
745 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
746 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
747 dpyinfo->mouse_face_window = Qnil;
750 updated_window = NULL;
754 /* End update of frame F. This function is installed as a hook in
755 update_end. */
757 static void
758 x_update_end (f)
759 struct frame *f;
761 /* Mouse highlight may be displayed again. */
762 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
764 BLOCK_INPUT;
765 XFlush (FRAME_X_DISPLAY (f));
766 UNBLOCK_INPUT;
770 /* This function is called from various places in xdisp.c whenever a
771 complete update has been performed. The global variable
772 updated_window is not available here. */
774 static void
775 XTframe_up_to_date (f)
776 struct frame *f;
778 if (FRAME_X_P (f))
780 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
782 if (dpyinfo->mouse_face_deferred_gc
783 || f == dpyinfo->mouse_face_mouse_frame)
785 BLOCK_INPUT;
786 if (dpyinfo->mouse_face_mouse_frame)
787 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
788 dpyinfo->mouse_face_mouse_x,
789 dpyinfo->mouse_face_mouse_y);
790 dpyinfo->mouse_face_deferred_gc = 0;
791 UNBLOCK_INPUT;
797 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
798 arrow bitmaps, or clear the fringes if no bitmaps are required
799 before DESIRED_ROW is made current. The window being updated is
800 found in updated_window. This function It is called from
801 update_window_line only if it is known that there are differences
802 between bitmaps to be drawn between current row and DESIRED_ROW. */
804 static void
805 x_after_update_window_line (desired_row)
806 struct glyph_row *desired_row;
808 struct window *w = updated_window;
809 struct frame *f;
810 int width, height;
812 xassert (w);
814 if (!desired_row->mode_line_p && !w->pseudo_window_p)
816 BLOCK_INPUT;
817 x_draw_row_fringe_bitmaps (w, desired_row);
818 UNBLOCK_INPUT;
821 /* When a window has disappeared, make sure that no rest of
822 full-width rows stays visible in the internal border. Could
823 check here if updated_window is the leftmost/rightmost window,
824 but I guess it's not worth doing since vertically split windows
825 are almost never used, internal border is rarely set, and the
826 overhead is very small. */
827 if (windows_or_buffers_changed
828 && desired_row->full_width_p
829 && (f = XFRAME (w->frame),
830 width = FRAME_INTERNAL_BORDER_WIDTH (f),
831 width != 0)
832 && (height = desired_row->visible_height,
833 height > 0))
835 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
837 /* Internal border is drawn below the tool bar. */
838 if (WINDOWP (f->tool_bar_window)
839 && w == XWINDOW (f->tool_bar_window))
840 y -= width;
842 BLOCK_INPUT;
843 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
844 0, y, width, height, False);
845 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
846 f->output_data.x->pixel_width - width,
847 y, width, height, False);
848 UNBLOCK_INPUT;
853 /* Draw the bitmap WHICH in one of the left or right fringes of
854 window W. ROW is the glyph row for which to display the bitmap; it
855 determines the vertical position at which the bitmap has to be
856 drawn. */
858 static void
859 x_draw_fringe_bitmap (w, row, which, left_p)
860 struct window *w;
861 struct glyph_row *row;
862 enum fringe_bitmap_type which;
863 int left_p;
865 struct frame *f = XFRAME (WINDOW_FRAME (w));
866 Display *display = FRAME_X_DISPLAY (f);
867 Window window = FRAME_X_WINDOW (f);
868 int x, y, wd, h, dy;
869 int b1, b2;
870 unsigned char *bits = NULL;
871 Pixmap pixmap;
872 GC gc = f->output_data.x->normal_gc;
873 struct face *face;
874 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
876 /* Must clip because of partially visible lines. */
877 x_clip_to_row (w, row, gc, 1);
879 /* Convert row to frame coordinates. */
880 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
882 switch (which)
884 case NO_FRINGE_BITMAP:
885 wd = 0;
886 h = 0;
887 break;
889 case LEFT_TRUNCATION_BITMAP:
890 wd = left_width;
891 h = left_height;
892 bits = left_bits;
893 break;
895 case OVERLAY_ARROW_BITMAP:
896 wd = ov_width;
897 h = ov_height;
898 bits = ov_bits;
899 break;
901 case RIGHT_TRUNCATION_BITMAP:
902 wd = right_width;
903 h = right_height;
904 bits = right_bits;
905 break;
907 case CONTINUED_LINE_BITMAP:
908 wd = continued_width;
909 h = continued_height;
910 bits = continued_bits;
911 break;
913 case CONTINUATION_LINE_BITMAP:
914 wd = continuation_width;
915 h = continuation_height;
916 bits = continuation_bits;
917 break;
919 case ZV_LINE_BITMAP:
920 wd = zv_width;
921 h = zv_height - (y % zv_period);
922 bits = zv_bits + (y % zv_period);
923 break;
925 default:
926 abort ();
929 /* Clip bitmap if too high. */
930 if (h > row->height)
931 h = row->height;
933 /* Set dy to the offset in the row to start drawing the bitmap. */
934 dy = (row->height - h) / 2;
936 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
937 PREPARE_FACE_FOR_DISPLAY (f, face);
939 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
940 the fringe. */
941 b1 = b2 = -1;
942 if (left_p)
944 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
945 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
946 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
947 - wd
948 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
949 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
951 /* If W has a vertical border to its left, don't draw over it. */
952 int border = ((XFASTINT (w->left) > 0
953 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
954 ? 1 : 0);
955 b1 = (window_box_left (w, -1)
956 - FRAME_X_LEFT_FRINGE_WIDTH (f)
957 + border);
958 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
961 else
963 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
964 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
965 x = (window_box_right (w, -1)
966 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
967 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
968 the fringe. */
969 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
971 b1 = window_box_right (w, -1);
972 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
976 if (b1 >= 0)
978 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
980 /* In case the same realized face is used for fringes and
981 for something displayed in the text (e.g. face `region' on
982 mono-displays, the fill style may have been changed to
983 FillSolid in x_draw_glyph_string_background. */
984 if (face->stipple)
985 XSetFillStyle (display, face->gc, FillOpaqueStippled);
986 else
987 XSetForeground (display, face->gc, face->background);
989 XFillRectangle (display, window, face->gc,
991 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
992 row->y)),
994 row->visible_height);
995 if (!face->stipple)
996 XSetForeground (display, face->gc, face->foreground);
999 if (which != NO_FRINGE_BITMAP)
1001 /* Draw the bitmap. I believe these small pixmaps can be cached
1002 by the server. */
1003 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
1004 face->foreground,
1005 face->background, depth);
1006 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
1007 XFreePixmap (display, pixmap);
1010 XSetClipMask (display, gc, None);
1014 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1015 function with input blocked. */
1017 static void
1018 x_draw_row_fringe_bitmaps (w, row)
1019 struct window *w;
1020 struct glyph_row *row;
1022 struct frame *f = XFRAME (w->frame);
1023 enum fringe_bitmap_type bitmap;
1025 xassert (interrupt_input_blocked);
1027 /* If row is completely invisible, because of vscrolling, we
1028 don't have to draw anything. */
1029 if (row->visible_height <= 0)
1030 return;
1032 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1034 /* Decide which bitmap to draw in the left fringe. */
1035 if (row->overlay_arrow_p)
1036 bitmap = OVERLAY_ARROW_BITMAP;
1037 else if (row->truncated_on_left_p)
1038 bitmap = LEFT_TRUNCATION_BITMAP;
1039 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1040 bitmap = CONTINUATION_LINE_BITMAP;
1041 else if (row->indicate_empty_line_p)
1042 bitmap = ZV_LINE_BITMAP;
1043 else
1044 bitmap = NO_FRINGE_BITMAP;
1046 x_draw_fringe_bitmap (w, row, bitmap, 1);
1049 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1051 /* Decide which bitmap to draw in the right fringe. */
1052 if (row->truncated_on_right_p)
1053 bitmap = RIGHT_TRUNCATION_BITMAP;
1054 else if (row->continued_p)
1055 bitmap = CONTINUED_LINE_BITMAP;
1056 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1057 bitmap = ZV_LINE_BITMAP;
1058 else
1059 bitmap = NO_FRINGE_BITMAP;
1061 x_draw_fringe_bitmap (w, row, bitmap, 0);
1067 /* This is called when starting Emacs and when restarting after
1068 suspend. When starting Emacs, no X window is mapped. And nothing
1069 must be done to Emacs's own window if it is suspended (though that
1070 rarely happens). */
1072 static void
1073 XTset_terminal_modes ()
1077 /* This is called when exiting or suspending Emacs. Exiting will make
1078 the X-windows go away, and suspending requires no action. */
1080 static void
1081 XTreset_terminal_modes ()
1087 /***********************************************************************
1088 Output Cursor
1089 ***********************************************************************/
1091 /* Set the global variable output_cursor to CURSOR. All cursor
1092 positions are relative to updated_window. */
1094 static void
1095 set_output_cursor (cursor)
1096 struct cursor_pos *cursor;
1098 output_cursor.hpos = cursor->hpos;
1099 output_cursor.vpos = cursor->vpos;
1100 output_cursor.x = cursor->x;
1101 output_cursor.y = cursor->y;
1105 /* Set a nominal cursor position.
1107 HPOS and VPOS are column/row positions in a window glyph matrix. X
1108 and Y are window text area relative pixel positions.
1110 If this is done during an update, updated_window will contain the
1111 window that is being updated and the position is the future output
1112 cursor position for that window. If updated_window is null, use
1113 selected_window and display the cursor at the given position. */
1115 static void
1116 XTcursor_to (vpos, hpos, y, x)
1117 int vpos, hpos, y, x;
1119 struct window *w;
1121 /* If updated_window is not set, work on selected_window. */
1122 if (updated_window)
1123 w = updated_window;
1124 else
1125 w = XWINDOW (selected_window);
1127 /* Set the output cursor. */
1128 output_cursor.hpos = hpos;
1129 output_cursor.vpos = vpos;
1130 output_cursor.x = x;
1131 output_cursor.y = y;
1133 /* If not called as part of an update, really display the cursor.
1134 This will also set the cursor position of W. */
1135 if (updated_window == NULL)
1137 BLOCK_INPUT;
1138 x_display_cursor (w, 1, hpos, vpos, x, y);
1139 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1140 UNBLOCK_INPUT;
1146 /***********************************************************************
1147 Display Iterator
1148 ***********************************************************************/
1150 /* Function prototypes of this page. */
1152 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1153 struct glyph *,
1154 XChar2b *,
1155 int *));
1156 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1157 int, XChar2b *, int,
1158 int));
1159 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1160 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1161 static void x_append_glyph P_ ((struct it *));
1162 static void x_append_composite_glyph P_ ((struct it *));
1163 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1164 int, int, double));
1165 static void x_produce_glyphs P_ ((struct it *));
1166 static void x_produce_image_glyph P_ ((struct it *it));
1169 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1170 is not contained in the font. */
1172 static INLINE XCharStruct *
1173 x_per_char_metric (font, char2b)
1174 XFontStruct *font;
1175 XChar2b *char2b;
1177 /* The result metric information. */
1178 XCharStruct *pcm = NULL;
1180 xassert (font && char2b);
1182 if (font->per_char != NULL)
1184 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1186 /* min_char_or_byte2 specifies the linear character index
1187 corresponding to the first element of the per_char array,
1188 max_char_or_byte2 is the index of the last character. A
1189 character with non-zero CHAR2B->byte1 is not in the font.
1190 A character with byte2 less than min_char_or_byte2 or
1191 greater max_char_or_byte2 is not in the font. */
1192 if (char2b->byte1 == 0
1193 && char2b->byte2 >= font->min_char_or_byte2
1194 && char2b->byte2 <= font->max_char_or_byte2)
1195 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1197 else
1199 /* If either min_byte1 or max_byte1 are nonzero, both
1200 min_char_or_byte2 and max_char_or_byte2 are less than
1201 256, and the 2-byte character index values corresponding
1202 to the per_char array element N (counting from 0) are:
1204 byte1 = N/D + min_byte1
1205 byte2 = N\D + min_char_or_byte2
1207 where:
1209 D = max_char_or_byte2 - min_char_or_byte2 + 1
1210 / = integer division
1211 \ = integer modulus */
1212 if (char2b->byte1 >= font->min_byte1
1213 && char2b->byte1 <= font->max_byte1
1214 && char2b->byte2 >= font->min_char_or_byte2
1215 && char2b->byte2 <= font->max_char_or_byte2)
1217 pcm = (font->per_char
1218 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1219 * (char2b->byte1 - font->min_byte1))
1220 + (char2b->byte2 - font->min_char_or_byte2));
1224 else
1226 /* If the per_char pointer is null, all glyphs between the first
1227 and last character indexes inclusive have the same
1228 information, as given by both min_bounds and max_bounds. */
1229 if (char2b->byte2 >= font->min_char_or_byte2
1230 && char2b->byte2 <= font->max_char_or_byte2)
1231 pcm = &font->max_bounds;
1234 return ((pcm == NULL
1235 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1236 ? NULL : pcm);
1240 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1241 the two-byte form of C. Encoding is returned in *CHAR2B. */
1243 static INLINE void
1244 x_encode_char (c, char2b, font_info)
1245 int c;
1246 XChar2b *char2b;
1247 struct font_info *font_info;
1249 int charset = CHAR_CHARSET (c);
1250 XFontStruct *font = font_info->font;
1252 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1253 This may be either a program in a special encoder language or a
1254 fixed encoding. */
1255 if (font_info->font_encoder)
1257 /* It's a program. */
1258 struct ccl_program *ccl = font_info->font_encoder;
1260 if (CHARSET_DIMENSION (charset) == 1)
1262 ccl->reg[0] = charset;
1263 ccl->reg[1] = char2b->byte2;
1264 ccl->reg[2] = -1;
1266 else
1268 ccl->reg[0] = charset;
1269 ccl->reg[1] = char2b->byte1;
1270 ccl->reg[2] = char2b->byte2;
1273 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1275 /* We assume that MSBs are appropriately set/reset by CCL
1276 program. */
1277 if (font->max_byte1 == 0) /* 1-byte font */
1278 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1279 else
1280 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1282 else if (font_info->encoding[charset])
1284 /* Fixed encoding scheme. See fontset.h for the meaning of the
1285 encoding numbers. */
1286 int enc = font_info->encoding[charset];
1288 if ((enc == 1 || enc == 2)
1289 && CHARSET_DIMENSION (charset) == 2)
1290 char2b->byte1 |= 0x80;
1292 if (enc == 1 || enc == 3)
1293 char2b->byte2 |= 0x80;
1298 /* Get face and two-byte form of character C in face FACE_ID on frame
1299 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1300 means we want to display multibyte text. DISPLAY_P non-zero means
1301 make sure that X resources for the face returned are allocated.
1302 Value is a pointer to a realized face that is ready for display if
1303 DISPLAY_P is non-zero. */
1305 static INLINE struct face *
1306 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
1307 struct frame *f;
1308 int c, face_id;
1309 XChar2b *char2b;
1310 int multibyte_p, display_p;
1312 struct face *face = FACE_FROM_ID (f, face_id);
1314 if (!multibyte_p)
1316 /* Unibyte case. We don't have to encode, but we have to make
1317 sure to use a face suitable for unibyte. */
1318 char2b->byte1 = 0;
1319 char2b->byte2 = c;
1320 face_id = FACE_FOR_CHAR (f, face, c);
1321 face = FACE_FROM_ID (f, face_id);
1323 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1325 /* Case of ASCII in a face known to fit ASCII. */
1326 char2b->byte1 = 0;
1327 char2b->byte2 = c;
1329 else
1331 int c1, c2, charset;
1333 /* Split characters into bytes. If c2 is -1 afterwards, C is
1334 really a one-byte character so that byte1 is zero. */
1335 SPLIT_CHAR (c, charset, c1, c2);
1336 if (c2 > 0)
1337 char2b->byte1 = c1, char2b->byte2 = c2;
1338 else
1339 char2b->byte1 = 0, char2b->byte2 = c1;
1341 /* Maybe encode the character in *CHAR2B. */
1342 if (face->font != NULL)
1344 struct font_info *font_info
1345 = FONT_INFO_FROM_ID (f, face->font_info_id);
1346 if (font_info)
1347 x_encode_char (c, char2b, font_info);
1351 /* Make sure X resources of the face are allocated. */
1352 if (display_p)
1354 xassert (face != NULL);
1355 PREPARE_FACE_FOR_DISPLAY (f, face);
1358 return face;
1362 /* Get face and two-byte form of character glyph GLYPH on frame F.
1363 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1364 a pointer to a realized face that is ready for display. */
1366 static INLINE struct face *
1367 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1368 struct frame *f;
1369 struct glyph *glyph;
1370 XChar2b *char2b;
1371 int *two_byte_p;
1373 struct face *face;
1375 xassert (glyph->type == CHAR_GLYPH);
1376 face = FACE_FROM_ID (f, glyph->face_id);
1378 if (two_byte_p)
1379 *two_byte_p = 0;
1381 if (!glyph->multibyte_p)
1383 /* Unibyte case. We don't have to encode, but we have to make
1384 sure to use a face suitable for unibyte. */
1385 char2b->byte1 = 0;
1386 char2b->byte2 = glyph->u.ch;
1388 else if (glyph->u.ch < 128
1389 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1391 /* Case of ASCII in a face known to fit ASCII. */
1392 char2b->byte1 = 0;
1393 char2b->byte2 = glyph->u.ch;
1395 else
1397 int c1, c2, charset;
1399 /* Split characters into bytes. If c2 is -1 afterwards, C is
1400 really a one-byte character so that byte1 is zero. */
1401 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1402 if (c2 > 0)
1403 char2b->byte1 = c1, char2b->byte2 = c2;
1404 else
1405 char2b->byte1 = 0, char2b->byte2 = c1;
1407 /* Maybe encode the character in *CHAR2B. */
1408 if (charset != CHARSET_ASCII)
1410 struct font_info *font_info
1411 = FONT_INFO_FROM_ID (f, face->font_info_id);
1412 if (font_info)
1414 x_encode_char (glyph->u.ch, char2b, font_info);
1415 if (two_byte_p)
1416 *two_byte_p
1417 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1422 /* Make sure X resources of the face are allocated. */
1423 xassert (face != NULL);
1424 PREPARE_FACE_FOR_DISPLAY (f, face);
1425 return face;
1429 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1430 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1432 static INLINE void
1433 x_append_glyph (it)
1434 struct it *it;
1436 struct glyph *glyph;
1437 enum glyph_row_area area = it->area;
1439 xassert (it->glyph_row);
1440 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1442 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1443 if (glyph < it->glyph_row->glyphs[area + 1])
1445 glyph->charpos = CHARPOS (it->position);
1446 glyph->object = it->object;
1447 glyph->pixel_width = it->pixel_width;
1448 glyph->voffset = it->voffset;
1449 glyph->type = CHAR_GLYPH;
1450 glyph->multibyte_p = it->multibyte_p;
1451 glyph->left_box_line_p = it->start_of_box_run_p;
1452 glyph->right_box_line_p = it->end_of_box_run_p;
1453 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1454 || it->phys_descent > it->descent);
1455 glyph->padding_p = 0;
1456 glyph->glyph_not_available_p = it->glyph_not_available_p;
1457 glyph->face_id = it->face_id;
1458 glyph->u.ch = it->char_to_display;
1459 ++it->glyph_row->used[area];
1463 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1464 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1466 static INLINE void
1467 x_append_composite_glyph (it)
1468 struct it *it;
1470 struct glyph *glyph;
1471 enum glyph_row_area area = it->area;
1473 xassert (it->glyph_row);
1475 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1476 if (glyph < it->glyph_row->glyphs[area + 1])
1478 glyph->charpos = CHARPOS (it->position);
1479 glyph->object = it->object;
1480 glyph->pixel_width = it->pixel_width;
1481 glyph->voffset = it->voffset;
1482 glyph->type = COMPOSITE_GLYPH;
1483 glyph->multibyte_p = it->multibyte_p;
1484 glyph->left_box_line_p = it->start_of_box_run_p;
1485 glyph->right_box_line_p = it->end_of_box_run_p;
1486 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1487 || it->phys_descent > it->descent);
1488 glyph->padding_p = 0;
1489 glyph->glyph_not_available_p = 0;
1490 glyph->face_id = it->face_id;
1491 glyph->u.cmp_id = it->cmp_id;
1492 ++it->glyph_row->used[area];
1497 /* Change IT->ascent and IT->height according to the setting of
1498 IT->voffset. */
1500 static INLINE void
1501 take_vertical_position_into_account (it)
1502 struct it *it;
1504 if (it->voffset)
1506 if (it->voffset < 0)
1507 /* Increase the ascent so that we can display the text higher
1508 in the line. */
1509 it->ascent += abs (it->voffset);
1510 else
1511 /* Increase the descent so that we can display the text lower
1512 in the line. */
1513 it->descent += it->voffset;
1518 /* Produce glyphs/get display metrics for the image IT is loaded with.
1519 See the description of struct display_iterator in dispextern.h for
1520 an overview of struct display_iterator. */
1522 static void
1523 x_produce_image_glyph (it)
1524 struct it *it;
1526 struct image *img;
1527 struct face *face;
1529 xassert (it->what == IT_IMAGE);
1531 face = FACE_FROM_ID (it->f, it->face_id);
1532 img = IMAGE_FROM_ID (it->f, it->image_id);
1533 xassert (img);
1535 /* Make sure X resources of the face and image are loaded. */
1536 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1537 prepare_image_for_display (it->f, img);
1539 it->ascent = it->phys_ascent = image_ascent (img, face);
1540 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1541 it->pixel_width = img->width + 2 * img->hmargin;
1543 it->nglyphs = 1;
1545 if (face->box != FACE_NO_BOX)
1547 if (face->box_line_width > 0)
1549 it->ascent += face->box_line_width;
1550 it->descent += face->box_line_width;
1553 if (it->start_of_box_run_p)
1554 it->pixel_width += abs (face->box_line_width);
1555 if (it->end_of_box_run_p)
1556 it->pixel_width += abs (face->box_line_width);
1559 take_vertical_position_into_account (it);
1561 if (it->glyph_row)
1563 struct glyph *glyph;
1564 enum glyph_row_area area = it->area;
1566 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1567 if (glyph < it->glyph_row->glyphs[area + 1])
1569 glyph->charpos = CHARPOS (it->position);
1570 glyph->object = it->object;
1571 glyph->pixel_width = it->pixel_width;
1572 glyph->voffset = it->voffset;
1573 glyph->type = IMAGE_GLYPH;
1574 glyph->multibyte_p = it->multibyte_p;
1575 glyph->left_box_line_p = it->start_of_box_run_p;
1576 glyph->right_box_line_p = it->end_of_box_run_p;
1577 glyph->overlaps_vertically_p = 0;
1578 glyph->padding_p = 0;
1579 glyph->glyph_not_available_p = 0;
1580 glyph->face_id = it->face_id;
1581 glyph->u.img_id = img->id;
1582 ++it->glyph_row->used[area];
1588 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1589 of the glyph, WIDTH and HEIGHT are the width and height of the
1590 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1591 ascent of the glyph (0 <= ASCENT <= 1). */
1593 static void
1594 x_append_stretch_glyph (it, object, width, height, ascent)
1595 struct it *it;
1596 Lisp_Object object;
1597 int width, height;
1598 double ascent;
1600 struct glyph *glyph;
1601 enum glyph_row_area area = it->area;
1603 xassert (ascent >= 0 && ascent <= 1);
1605 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1606 if (glyph < it->glyph_row->glyphs[area + 1])
1608 glyph->charpos = CHARPOS (it->position);
1609 glyph->object = object;
1610 glyph->pixel_width = width;
1611 glyph->voffset = it->voffset;
1612 glyph->type = STRETCH_GLYPH;
1613 glyph->multibyte_p = it->multibyte_p;
1614 glyph->left_box_line_p = it->start_of_box_run_p;
1615 glyph->right_box_line_p = it->end_of_box_run_p;
1616 glyph->overlaps_vertically_p = 0;
1617 glyph->padding_p = 0;
1618 glyph->glyph_not_available_p = 0;
1619 glyph->face_id = it->face_id;
1620 glyph->u.stretch.ascent = height * ascent;
1621 glyph->u.stretch.height = height;
1622 ++it->glyph_row->used[area];
1627 /* Produce a stretch glyph for iterator IT. IT->object is the value
1628 of the glyph property displayed. The value must be a list
1629 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1630 being recognized:
1632 1. `:width WIDTH' specifies that the space should be WIDTH *
1633 canonical char width wide. WIDTH may be an integer or floating
1634 point number.
1636 2. `:relative-width FACTOR' specifies that the width of the stretch
1637 should be computed from the width of the first character having the
1638 `glyph' property, and should be FACTOR times that width.
1640 3. `:align-to HPOS' specifies that the space should be wide enough
1641 to reach HPOS, a value in canonical character units.
1643 Exactly one of the above pairs must be present.
1645 4. `:height HEIGHT' specifies that the height of the stretch produced
1646 should be HEIGHT, measured in canonical character units.
1648 5. `:relative-height FACTOR' specifies that the height of the
1649 stretch should be FACTOR times the height of the characters having
1650 the glyph property.
1652 Either none or exactly one of 4 or 5 must be present.
1654 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1655 of the stretch should be used for the ascent of the stretch.
1656 ASCENT must be in the range 0 <= ASCENT <= 100. */
1658 #define NUMVAL(X) \
1659 ((INTEGERP (X) || FLOATP (X)) \
1660 ? XFLOATINT (X) \
1661 : - 1)
1664 static void
1665 x_produce_stretch_glyph (it)
1666 struct it *it;
1668 /* (space :width WIDTH :height HEIGHT. */
1669 #if GLYPH_DEBUG
1670 extern Lisp_Object Qspace;
1671 #endif
1672 extern Lisp_Object QCwidth, QCheight, QCascent;
1673 extern Lisp_Object QCrelative_width, QCrelative_height;
1674 extern Lisp_Object QCalign_to;
1675 Lisp_Object prop, plist;
1676 double width = 0, height = 0, ascent = 0;
1677 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1678 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1680 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1682 /* List should start with `space'. */
1683 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1684 plist = XCDR (it->object);
1686 /* Compute the width of the stretch. */
1687 if (prop = Fplist_get (plist, QCwidth),
1688 NUMVAL (prop) > 0)
1689 /* Absolute width `:width WIDTH' specified and valid. */
1690 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1691 else if (prop = Fplist_get (plist, QCrelative_width),
1692 NUMVAL (prop) > 0)
1694 /* Relative width `:relative-width FACTOR' specified and valid.
1695 Compute the width of the characters having the `glyph'
1696 property. */
1697 struct it it2;
1698 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1700 it2 = *it;
1701 if (it->multibyte_p)
1703 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1704 - IT_BYTEPOS (*it));
1705 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1707 else
1708 it2.c = *p, it2.len = 1;
1710 it2.glyph_row = NULL;
1711 it2.what = IT_CHARACTER;
1712 x_produce_glyphs (&it2);
1713 width = NUMVAL (prop) * it2.pixel_width;
1715 else if (prop = Fplist_get (plist, QCalign_to),
1716 NUMVAL (prop) > 0)
1717 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1718 else
1719 /* Nothing specified -> width defaults to canonical char width. */
1720 width = CANON_X_UNIT (it->f);
1722 /* Compute height. */
1723 if (prop = Fplist_get (plist, QCheight),
1724 NUMVAL (prop) > 0)
1725 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1726 else if (prop = Fplist_get (plist, QCrelative_height),
1727 NUMVAL (prop) > 0)
1728 height = FONT_HEIGHT (font) * NUMVAL (prop);
1729 else
1730 height = FONT_HEIGHT (font);
1732 /* Compute percentage of height used for ascent. If
1733 `:ascent ASCENT' is present and valid, use that. Otherwise,
1734 derive the ascent from the font in use. */
1735 if (prop = Fplist_get (plist, QCascent),
1736 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1737 ascent = NUMVAL (prop) / 100.0;
1738 else
1739 ascent = (double) font->ascent / FONT_HEIGHT (font);
1741 if (width <= 0)
1742 width = 1;
1743 if (height <= 0)
1744 height = 1;
1746 if (it->glyph_row)
1748 Lisp_Object object = it->stack[it->sp - 1].string;
1749 if (!STRINGP (object))
1750 object = it->w->buffer;
1751 x_append_stretch_glyph (it, object, width, height, ascent);
1754 it->pixel_width = width;
1755 it->ascent = it->phys_ascent = height * ascent;
1756 it->descent = it->phys_descent = height - it->ascent;
1757 it->nglyphs = 1;
1759 if (face->box != FACE_NO_BOX)
1761 if (face->box_line_width > 0)
1763 it->ascent += face->box_line_width;
1764 it->descent += face->box_line_width;
1767 if (it->start_of_box_run_p)
1768 it->pixel_width += abs (face->box_line_width);
1769 if (it->end_of_box_run_p)
1770 it->pixel_width += abs (face->box_line_width);
1773 take_vertical_position_into_account (it);
1776 /* Return proper value to be used as baseline offset of font that has
1777 ASCENT and DESCENT to draw characters by the font at the vertical
1778 center of the line of frame F.
1780 Here, out task is to find the value of BOFF in the following figure;
1782 -------------------------+-----------+-
1783 -+-+---------+-+ | |
1784 | | | | | |
1785 | | | | F_ASCENT F_HEIGHT
1786 | | | ASCENT | |
1787 HEIGHT | | | | |
1788 | | |-|-+------+-----------|------- baseline
1789 | | | | BOFF | |
1790 | |---------|-+-+ | |
1791 | | | DESCENT | |
1792 -+-+---------+-+ F_DESCENT |
1793 -------------------------+-----------+-
1795 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1796 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1797 DESCENT = FONT->descent
1798 HEIGHT = FONT_HEIGHT (FONT)
1799 F_DESCENT = (F->output_data.x->font->descent
1800 - F->output_data.x->baseline_offset)
1801 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1804 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1805 ((FONT)->descent \
1806 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1807 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1808 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1810 /* Produce glyphs/get display metrics for the display element IT is
1811 loaded with. See the description of struct display_iterator in
1812 dispextern.h for an overview of struct display_iterator. */
1814 static void
1815 x_produce_glyphs (it)
1816 struct it *it;
1818 it->glyph_not_available_p = 0;
1820 if (it->what == IT_CHARACTER)
1822 XChar2b char2b;
1823 XFontStruct *font;
1824 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1825 XCharStruct *pcm;
1826 int font_not_found_p;
1827 struct font_info *font_info;
1828 int boff; /* baseline offset */
1829 /* We may change it->multibyte_p upon unibyte<->multibyte
1830 conversion. So, save the current value now and restore it
1831 later.
1833 Note: It seems that we don't have to record multibyte_p in
1834 struct glyph because the character code itself tells if or
1835 not the character is multibyte. Thus, in the future, we must
1836 consider eliminating the field `multibyte_p' in the struct
1837 glyph. */
1838 int saved_multibyte_p = it->multibyte_p;
1840 /* Maybe translate single-byte characters to multibyte, or the
1841 other way. */
1842 it->char_to_display = it->c;
1843 if (!ASCII_BYTE_P (it->c))
1845 if (unibyte_display_via_language_environment
1846 && SINGLE_BYTE_CHAR_P (it->c)
1847 && (it->c >= 0240
1848 || !NILP (Vnonascii_translation_table)))
1850 it->char_to_display = unibyte_char_to_multibyte (it->c);
1851 it->multibyte_p = 1;
1852 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1853 face = FACE_FROM_ID (it->f, it->face_id);
1855 else if (!SINGLE_BYTE_CHAR_P (it->c)
1856 && !it->multibyte_p)
1858 it->multibyte_p = 1;
1859 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1860 face = FACE_FROM_ID (it->f, it->face_id);
1864 /* Get font to use. Encode IT->char_to_display. */
1865 x_get_char_face_and_encoding (it->f, it->char_to_display,
1866 it->face_id, &char2b,
1867 it->multibyte_p, 0);
1868 font = face->font;
1870 /* When no suitable font found, use the default font. */
1871 font_not_found_p = font == NULL;
1872 if (font_not_found_p)
1874 font = FRAME_FONT (it->f);
1875 boff = it->f->output_data.x->baseline_offset;
1876 font_info = NULL;
1878 else
1880 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1881 boff = font_info->baseline_offset;
1882 if (font_info->vertical_centering)
1883 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1886 if (it->char_to_display >= ' '
1887 && (!it->multibyte_p || it->char_to_display < 128))
1889 /* Either unibyte or ASCII. */
1890 int stretched_p;
1892 it->nglyphs = 1;
1894 pcm = x_per_char_metric (font, &char2b);
1895 it->ascent = font->ascent + boff;
1896 it->descent = font->descent - boff;
1898 if (pcm)
1900 it->phys_ascent = pcm->ascent + boff;
1901 it->phys_descent = pcm->descent - boff;
1902 it->pixel_width = pcm->width;
1904 else
1906 it->glyph_not_available_p = 1;
1907 it->phys_ascent = font->ascent + boff;
1908 it->phys_descent = font->descent - boff;
1909 it->pixel_width = FONT_WIDTH (font);
1912 /* If this is a space inside a region of text with
1913 `space-width' property, change its width. */
1914 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1915 if (stretched_p)
1916 it->pixel_width *= XFLOATINT (it->space_width);
1918 /* If face has a box, add the box thickness to the character
1919 height. If character has a box line to the left and/or
1920 right, add the box line width to the character's width. */
1921 if (face->box != FACE_NO_BOX)
1923 int thick = face->box_line_width;
1925 if (thick > 0)
1927 it->ascent += thick;
1928 it->descent += thick;
1930 else
1931 thick = -thick;
1933 if (it->start_of_box_run_p)
1934 it->pixel_width += thick;
1935 if (it->end_of_box_run_p)
1936 it->pixel_width += thick;
1939 /* If face has an overline, add the height of the overline
1940 (1 pixel) and a 1 pixel margin to the character height. */
1941 if (face->overline_p)
1942 it->ascent += 2;
1944 take_vertical_position_into_account (it);
1946 /* If we have to actually produce glyphs, do it. */
1947 if (it->glyph_row)
1949 if (stretched_p)
1951 /* Translate a space with a `space-width' property
1952 into a stretch glyph. */
1953 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1954 x_append_stretch_glyph (it, it->object, it->pixel_width,
1955 it->ascent + it->descent, ascent);
1957 else
1958 x_append_glyph (it);
1960 /* If characters with lbearing or rbearing are displayed
1961 in this line, record that fact in a flag of the
1962 glyph row. This is used to optimize X output code. */
1963 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1964 it->glyph_row->contains_overlapping_glyphs_p = 1;
1967 else if (it->char_to_display == '\n')
1969 /* A newline has no width but we need the height of the line. */
1970 it->pixel_width = 0;
1971 it->nglyphs = 0;
1972 it->ascent = it->phys_ascent = font->ascent + boff;
1973 it->descent = it->phys_descent = font->descent - boff;
1975 if (face->box != FACE_NO_BOX
1976 && face->box_line_width > 0)
1978 it->ascent += face->box_line_width;
1979 it->descent += face->box_line_width;
1982 else if (it->char_to_display == '\t')
1984 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1985 int x = it->current_x + it->continuation_lines_width;
1986 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1988 /* If the distance from the current position to the next tab
1989 stop is less than a canonical character width, use the
1990 tab stop after that. */
1991 if (next_tab_x - x < CANON_X_UNIT (it->f))
1992 next_tab_x += tab_width;
1994 it->pixel_width = next_tab_x - x;
1995 it->nglyphs = 1;
1996 it->ascent = it->phys_ascent = font->ascent + boff;
1997 it->descent = it->phys_descent = font->descent - boff;
1999 if (it->glyph_row)
2001 double ascent = (double) it->ascent / (it->ascent + it->descent);
2002 x_append_stretch_glyph (it, it->object, it->pixel_width,
2003 it->ascent + it->descent, ascent);
2006 else
2008 /* A multi-byte character. Assume that the display width of the
2009 character is the width of the character multiplied by the
2010 width of the font. */
2012 /* If we found a font, this font should give us the right
2013 metrics. If we didn't find a font, use the frame's
2014 default font and calculate the width of the character
2015 from the charset width; this is what old redisplay code
2016 did. */
2017 pcm = x_per_char_metric (font, &char2b);
2018 if (font_not_found_p || !pcm)
2020 int charset = CHAR_CHARSET (it->char_to_display);
2022 it->glyph_not_available_p = 1;
2023 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2024 * CHARSET_WIDTH (charset));
2025 it->phys_ascent = font->ascent + boff;
2026 it->phys_descent = font->descent - boff;
2028 else
2030 it->pixel_width = pcm->width;
2031 it->phys_ascent = pcm->ascent + boff;
2032 it->phys_descent = pcm->descent - boff;
2033 if (it->glyph_row
2034 && (pcm->lbearing < 0
2035 || pcm->rbearing > pcm->width))
2036 it->glyph_row->contains_overlapping_glyphs_p = 1;
2038 it->nglyphs = 1;
2039 it->ascent = font->ascent + boff;
2040 it->descent = font->descent - boff;
2041 if (face->box != FACE_NO_BOX)
2043 int thick = face->box_line_width;
2045 if (thick > 0)
2047 it->ascent += thick;
2048 it->descent += thick;
2050 else
2051 thick = - thick;
2053 if (it->start_of_box_run_p)
2054 it->pixel_width += thick;
2055 if (it->end_of_box_run_p)
2056 it->pixel_width += thick;
2059 /* If face has an overline, add the height of the overline
2060 (1 pixel) and a 1 pixel margin to the character height. */
2061 if (face->overline_p)
2062 it->ascent += 2;
2064 take_vertical_position_into_account (it);
2066 if (it->glyph_row)
2067 x_append_glyph (it);
2069 it->multibyte_p = saved_multibyte_p;
2071 else if (it->what == IT_COMPOSITION)
2073 /* Note: A composition is represented as one glyph in the
2074 glyph matrix. There are no padding glyphs. */
2075 XChar2b char2b;
2076 XFontStruct *font;
2077 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2078 XCharStruct *pcm;
2079 int font_not_found_p;
2080 struct font_info *font_info;
2081 int boff; /* baseline offset */
2082 struct composition *cmp = composition_table[it->cmp_id];
2084 /* Maybe translate single-byte characters to multibyte. */
2085 it->char_to_display = it->c;
2086 if (unibyte_display_via_language_environment
2087 && SINGLE_BYTE_CHAR_P (it->c)
2088 && (it->c >= 0240
2089 || (it->c >= 0200
2090 && !NILP (Vnonascii_translation_table))))
2092 it->char_to_display = unibyte_char_to_multibyte (it->c);
2095 /* Get face and font to use. Encode IT->char_to_display. */
2096 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2097 face = FACE_FROM_ID (it->f, it->face_id);
2098 x_get_char_face_and_encoding (it->f, it->char_to_display,
2099 it->face_id, &char2b, it->multibyte_p, 0);
2100 font = face->font;
2102 /* When no suitable font found, use the default font. */
2103 font_not_found_p = font == NULL;
2104 if (font_not_found_p)
2106 font = FRAME_FONT (it->f);
2107 boff = it->f->output_data.x->baseline_offset;
2108 font_info = NULL;
2110 else
2112 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2113 boff = font_info->baseline_offset;
2114 if (font_info->vertical_centering)
2115 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2118 /* There are no padding glyphs, so there is only one glyph to
2119 produce for the composition. Important is that pixel_width,
2120 ascent and descent are the values of what is drawn by
2121 draw_glyphs (i.e. the values of the overall glyphs composed). */
2122 it->nglyphs = 1;
2124 /* If we have not yet calculated pixel size data of glyphs of
2125 the composition for the current face font, calculate them
2126 now. Theoretically, we have to check all fonts for the
2127 glyphs, but that requires much time and memory space. So,
2128 here we check only the font of the first glyph. This leads
2129 to incorrect display very rarely, and C-l (recenter) can
2130 correct the display anyway. */
2131 if (cmp->font != (void *) font)
2133 /* Ascent and descent of the font of the first character of
2134 this composition (adjusted by baseline offset). Ascent
2135 and descent of overall glyphs should not be less than
2136 them respectively. */
2137 int font_ascent = font->ascent + boff;
2138 int font_descent = font->descent - boff;
2139 /* Bounding box of the overall glyphs. */
2140 int leftmost, rightmost, lowest, highest;
2141 int i, width, ascent, descent;
2143 cmp->font = (void *) font;
2145 /* Initialize the bounding box. */
2146 if (font_info
2147 && (pcm = x_per_char_metric (font, &char2b)))
2149 width = pcm->width;
2150 ascent = pcm->ascent;
2151 descent = pcm->descent;
2153 else
2155 width = FONT_WIDTH (font);
2156 ascent = font->ascent;
2157 descent = font->descent;
2160 rightmost = width;
2161 lowest = - descent + boff;
2162 highest = ascent + boff;
2163 leftmost = 0;
2165 if (font_info
2166 && font_info->default_ascent
2167 && CHAR_TABLE_P (Vuse_default_ascent)
2168 && !NILP (Faref (Vuse_default_ascent,
2169 make_number (it->char_to_display))))
2170 highest = font_info->default_ascent + boff;
2172 /* Draw the first glyph at the normal position. It may be
2173 shifted to right later if some other glyphs are drawn at
2174 the left. */
2175 cmp->offsets[0] = 0;
2176 cmp->offsets[1] = boff;
2178 /* Set cmp->offsets for the remaining glyphs. */
2179 for (i = 1; i < cmp->glyph_len; i++)
2181 int left, right, btm, top;
2182 int ch = COMPOSITION_GLYPH (cmp, i);
2183 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2185 face = FACE_FROM_ID (it->f, face_id);
2186 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2187 it->multibyte_p, 0);
2188 font = face->font;
2189 if (font == NULL)
2191 font = FRAME_FONT (it->f);
2192 boff = it->f->output_data.x->baseline_offset;
2193 font_info = NULL;
2195 else
2197 font_info
2198 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2199 boff = font_info->baseline_offset;
2200 if (font_info->vertical_centering)
2201 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2204 if (font_info
2205 && (pcm = x_per_char_metric (font, &char2b)))
2207 width = pcm->width;
2208 ascent = pcm->ascent;
2209 descent = pcm->descent;
2211 else
2213 width = FONT_WIDTH (font);
2214 ascent = 1;
2215 descent = 0;
2218 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2220 /* Relative composition with or without
2221 alternate chars. */
2222 left = (leftmost + rightmost - width) / 2;
2223 btm = - descent + boff;
2224 if (font_info && font_info->relative_compose
2225 && (! CHAR_TABLE_P (Vignore_relative_composition)
2226 || NILP (Faref (Vignore_relative_composition,
2227 make_number (ch)))))
2230 if (- descent >= font_info->relative_compose)
2231 /* One extra pixel between two glyphs. */
2232 btm = highest + 1;
2233 else if (ascent <= 0)
2234 /* One extra pixel between two glyphs. */
2235 btm = lowest - 1 - ascent - descent;
2238 else
2240 /* A composition rule is specified by an integer
2241 value that encodes global and new reference
2242 points (GREF and NREF). GREF and NREF are
2243 specified by numbers as below:
2245 0---1---2 -- ascent
2249 9--10--11 -- center
2251 ---3---4---5--- baseline
2253 6---7---8 -- descent
2255 int rule = COMPOSITION_RULE (cmp, i);
2256 int gref, nref, grefx, grefy, nrefx, nrefy;
2258 COMPOSITION_DECODE_RULE (rule, gref, nref);
2259 grefx = gref % 3, nrefx = nref % 3;
2260 grefy = gref / 3, nrefy = nref / 3;
2262 left = (leftmost
2263 + grefx * (rightmost - leftmost) / 2
2264 - nrefx * width / 2);
2265 btm = ((grefy == 0 ? highest
2266 : grefy == 1 ? 0
2267 : grefy == 2 ? lowest
2268 : (highest + lowest) / 2)
2269 - (nrefy == 0 ? ascent + descent
2270 : nrefy == 1 ? descent - boff
2271 : nrefy == 2 ? 0
2272 : (ascent + descent) / 2));
2275 cmp->offsets[i * 2] = left;
2276 cmp->offsets[i * 2 + 1] = btm + descent;
2278 /* Update the bounding box of the overall glyphs. */
2279 right = left + width;
2280 top = btm + descent + ascent;
2281 if (left < leftmost)
2282 leftmost = left;
2283 if (right > rightmost)
2284 rightmost = right;
2285 if (top > highest)
2286 highest = top;
2287 if (btm < lowest)
2288 lowest = btm;
2291 /* If there are glyphs whose x-offsets are negative,
2292 shift all glyphs to the right and make all x-offsets
2293 non-negative. */
2294 if (leftmost < 0)
2296 for (i = 0; i < cmp->glyph_len; i++)
2297 cmp->offsets[i * 2] -= leftmost;
2298 rightmost -= leftmost;
2301 cmp->pixel_width = rightmost;
2302 cmp->ascent = highest;
2303 cmp->descent = - lowest;
2304 if (cmp->ascent < font_ascent)
2305 cmp->ascent = font_ascent;
2306 if (cmp->descent < font_descent)
2307 cmp->descent = font_descent;
2310 it->pixel_width = cmp->pixel_width;
2311 it->ascent = it->phys_ascent = cmp->ascent;
2312 it->descent = it->phys_descent = cmp->descent;
2314 if (face->box != FACE_NO_BOX)
2316 int thick = face->box_line_width;
2318 if (thick > 0)
2320 it->ascent += thick;
2321 it->descent += thick;
2323 else
2324 thick = - thick;
2326 if (it->start_of_box_run_p)
2327 it->pixel_width += thick;
2328 if (it->end_of_box_run_p)
2329 it->pixel_width += thick;
2332 /* If face has an overline, add the height of the overline
2333 (1 pixel) and a 1 pixel margin to the character height. */
2334 if (face->overline_p)
2335 it->ascent += 2;
2337 take_vertical_position_into_account (it);
2339 if (it->glyph_row)
2340 x_append_composite_glyph (it);
2342 else if (it->what == IT_IMAGE)
2343 x_produce_image_glyph (it);
2344 else if (it->what == IT_STRETCH)
2345 x_produce_stretch_glyph (it);
2347 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2348 because this isn't true for images with `:ascent 100'. */
2349 xassert (it->ascent >= 0 && it->descent >= 0);
2350 if (it->area == TEXT_AREA)
2351 it->current_x += it->pixel_width;
2353 it->descent += it->extra_line_spacing;
2355 it->max_ascent = max (it->max_ascent, it->ascent);
2356 it->max_descent = max (it->max_descent, it->descent);
2357 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2358 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2362 /* Estimate the pixel height of the mode or top line on frame F.
2363 FACE_ID specifies what line's height to estimate. */
2366 x_estimate_mode_line_height (f, face_id)
2367 struct frame *f;
2368 enum face_id face_id;
2370 int height = FONT_HEIGHT (FRAME_FONT (f));
2372 /* This function is called so early when Emacs starts that the face
2373 cache and mode line face are not yet initialized. */
2374 if (FRAME_FACE_CACHE (f))
2376 struct face *face = FACE_FROM_ID (f, face_id);
2377 if (face)
2379 if (face->font)
2380 height = FONT_HEIGHT (face->font);
2381 if (face->box_line_width > 0)
2382 height += 2 * face->box_line_width;
2386 return height;
2390 /***********************************************************************
2391 Glyph display
2392 ***********************************************************************/
2394 /* A sequence of glyphs to be drawn in the same face.
2396 This data structure is not really completely X specific, so it
2397 could possibly, at least partially, be useful for other systems. It
2398 is currently not part of the external redisplay interface because
2399 it's not clear what other systems will need. */
2401 struct glyph_string
2403 /* X-origin of the string. */
2404 int x;
2406 /* Y-origin and y-position of the base line of this string. */
2407 int y, ybase;
2409 /* The width of the string, not including a face extension. */
2410 int width;
2412 /* The width of the string, including a face extension. */
2413 int background_width;
2415 /* The height of this string. This is the height of the line this
2416 string is drawn in, and can be different from the height of the
2417 font the string is drawn in. */
2418 int height;
2420 /* Number of pixels this string overwrites in front of its x-origin.
2421 This number is zero if the string has an lbearing >= 0; it is
2422 -lbearing, if the string has an lbearing < 0. */
2423 int left_overhang;
2425 /* Number of pixels this string overwrites past its right-most
2426 nominal x-position, i.e. x + width. Zero if the string's
2427 rbearing is <= its nominal width, rbearing - width otherwise. */
2428 int right_overhang;
2430 /* The frame on which the glyph string is drawn. */
2431 struct frame *f;
2433 /* The window on which the glyph string is drawn. */
2434 struct window *w;
2436 /* X display and window for convenience. */
2437 Display *display;
2438 Window window;
2440 /* The glyph row for which this string was built. It determines the
2441 y-origin and height of the string. */
2442 struct glyph_row *row;
2444 /* The area within row. */
2445 enum glyph_row_area area;
2447 /* Characters to be drawn, and number of characters. */
2448 XChar2b *char2b;
2449 int nchars;
2451 /* A face-override for drawing cursors, mouse face and similar. */
2452 enum draw_glyphs_face hl;
2454 /* Face in which this string is to be drawn. */
2455 struct face *face;
2457 /* Font in which this string is to be drawn. */
2458 XFontStruct *font;
2460 /* Font info for this string. */
2461 struct font_info *font_info;
2463 /* Non-null means this string describes (part of) a composition.
2464 All characters from char2b are drawn composed. */
2465 struct composition *cmp;
2467 /* Index of this glyph string's first character in the glyph
2468 definition of CMP. If this is zero, this glyph string describes
2469 the first character of a composition. */
2470 int gidx;
2472 /* 1 means this glyph strings face has to be drawn to the right end
2473 of the window's drawing area. */
2474 unsigned extends_to_end_of_line_p : 1;
2476 /* 1 means the background of this string has been drawn. */
2477 unsigned background_filled_p : 1;
2479 /* 1 means glyph string must be drawn with 16-bit functions. */
2480 unsigned two_byte_p : 1;
2482 /* 1 means that the original font determined for drawing this glyph
2483 string could not be loaded. The member `font' has been set to
2484 the frame's default font in this case. */
2485 unsigned font_not_found_p : 1;
2487 /* 1 means that the face in which this glyph string is drawn has a
2488 stipple pattern. */
2489 unsigned stippled_p : 1;
2491 /* 1 means only the foreground of this glyph string must be drawn,
2492 and we should use the physical height of the line this glyph
2493 string appears in as clip rect. */
2494 unsigned for_overlaps_p : 1;
2496 /* The GC to use for drawing this glyph string. */
2497 GC gc;
2499 /* A pointer to the first glyph in the string. This glyph
2500 corresponds to char2b[0]. Needed to draw rectangles if
2501 font_not_found_p is 1. */
2502 struct glyph *first_glyph;
2504 /* Image, if any. */
2505 struct image *img;
2507 struct glyph_string *next, *prev;
2511 #if GLYPH_DEBUG
2513 static void
2514 x_dump_glyph_string (s)
2515 struct glyph_string *s;
2517 fprintf (stderr, "glyph string\n");
2518 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2519 s->x, s->y, s->width, s->height);
2520 fprintf (stderr, " ybase = %d\n", s->ybase);
2521 fprintf (stderr, " hl = %d\n", s->hl);
2522 fprintf (stderr, " left overhang = %d, right = %d\n",
2523 s->left_overhang, s->right_overhang);
2524 fprintf (stderr, " nchars = %d\n", s->nchars);
2525 fprintf (stderr, " extends to end of line = %d\n",
2526 s->extends_to_end_of_line_p);
2527 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2528 fprintf (stderr, " bg width = %d\n", s->background_width);
2531 #endif /* GLYPH_DEBUG */
2535 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2536 struct glyph_string **,
2537 struct glyph_string *,
2538 struct glyph_string *));
2539 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2540 struct glyph_string **,
2541 struct glyph_string *,
2542 struct glyph_string *));
2543 static void x_append_glyph_string P_ ((struct glyph_string **,
2544 struct glyph_string **,
2545 struct glyph_string *));
2546 static int x_left_overwritten P_ ((struct glyph_string *));
2547 static int x_left_overwriting P_ ((struct glyph_string *));
2548 static int x_right_overwritten P_ ((struct glyph_string *));
2549 static int x_right_overwriting P_ ((struct glyph_string *));
2550 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2551 int));
2552 static void x_init_glyph_string P_ ((struct glyph_string *,
2553 XChar2b *, struct window *,
2554 struct glyph_row *,
2555 enum glyph_row_area, int,
2556 enum draw_glyphs_face));
2557 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2558 enum glyph_row_area, int, int,
2559 enum draw_glyphs_face, int));
2560 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2561 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2562 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2563 int));
2564 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2565 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2566 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2567 static void x_draw_glyph_string P_ ((struct glyph_string *));
2568 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2569 static void x_set_cursor_gc P_ ((struct glyph_string *));
2570 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2571 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2572 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2573 int *, int *));
2574 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2575 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2576 unsigned long *, double, int));
2577 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2578 double, int, unsigned long));
2579 static void x_setup_relief_colors P_ ((struct glyph_string *));
2580 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2581 static void x_draw_image_relief P_ ((struct glyph_string *));
2582 static void x_draw_image_foreground P_ ((struct glyph_string *));
2583 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2584 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2585 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2586 int, int, int));
2587 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2588 int, int, int, int, XRectangle *));
2589 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2590 int, int, int, XRectangle *));
2591 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2592 enum glyph_row_area));
2593 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2594 struct glyph_row *,
2595 enum glyph_row_area, int, int));
2597 #if GLYPH_DEBUG
2598 static void x_check_font P_ ((struct frame *, XFontStruct *));
2599 #endif
2602 /* Append the list of glyph strings with head H and tail T to the list
2603 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2605 static INLINE void
2606 x_append_glyph_string_lists (head, tail, h, t)
2607 struct glyph_string **head, **tail;
2608 struct glyph_string *h, *t;
2610 if (h)
2612 if (*head)
2613 (*tail)->next = h;
2614 else
2615 *head = h;
2616 h->prev = *tail;
2617 *tail = t;
2622 /* Prepend the list of glyph strings with head H and tail T to the
2623 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2624 result. */
2626 static INLINE void
2627 x_prepend_glyph_string_lists (head, tail, h, t)
2628 struct glyph_string **head, **tail;
2629 struct glyph_string *h, *t;
2631 if (h)
2633 if (*head)
2634 (*head)->prev = t;
2635 else
2636 *tail = t;
2637 t->next = *head;
2638 *head = h;
2643 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2644 Set *HEAD and *TAIL to the resulting list. */
2646 static INLINE void
2647 x_append_glyph_string (head, tail, s)
2648 struct glyph_string **head, **tail;
2649 struct glyph_string *s;
2651 s->next = s->prev = NULL;
2652 x_append_glyph_string_lists (head, tail, s, s);
2656 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2657 face. */
2659 static void
2660 x_set_cursor_gc (s)
2661 struct glyph_string *s;
2663 if (s->font == FRAME_FONT (s->f)
2664 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2665 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2666 && !s->cmp)
2667 s->gc = s->f->output_data.x->cursor_gc;
2668 else
2670 /* Cursor on non-default face: must merge. */
2671 XGCValues xgcv;
2672 unsigned long mask;
2674 xgcv.background = s->f->output_data.x->cursor_pixel;
2675 xgcv.foreground = s->face->background;
2677 /* If the glyph would be invisible, try a different foreground. */
2678 if (xgcv.foreground == xgcv.background)
2679 xgcv.foreground = s->face->foreground;
2680 if (xgcv.foreground == xgcv.background)
2681 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2682 if (xgcv.foreground == xgcv.background)
2683 xgcv.foreground = s->face->foreground;
2685 /* Make sure the cursor is distinct from text in this face. */
2686 if (xgcv.background == s->face->background
2687 && xgcv.foreground == s->face->foreground)
2689 xgcv.background = s->face->foreground;
2690 xgcv.foreground = s->face->background;
2693 IF_DEBUG (x_check_font (s->f, s->font));
2694 xgcv.font = s->font->fid;
2695 xgcv.graphics_exposures = False;
2696 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2698 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2699 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2700 mask, &xgcv);
2701 else
2702 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2703 = XCreateGC (s->display, s->window, mask, &xgcv);
2705 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2710 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2712 static void
2713 x_set_mouse_face_gc (s)
2714 struct glyph_string *s;
2716 int face_id;
2717 struct face *face;
2719 /* What face has to be used last for the mouse face? */
2720 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2721 face = FACE_FROM_ID (s->f, face_id);
2722 if (face == NULL)
2723 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2725 if (s->first_glyph->type == CHAR_GLYPH)
2726 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2727 else
2728 face_id = FACE_FOR_CHAR (s->f, face, 0);
2729 s->face = FACE_FROM_ID (s->f, face_id);
2730 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2732 /* If font in this face is same as S->font, use it. */
2733 if (s->font == s->face->font)
2734 s->gc = s->face->gc;
2735 else
2737 /* Otherwise construct scratch_cursor_gc with values from FACE
2738 but font FONT. */
2739 XGCValues xgcv;
2740 unsigned long mask;
2742 xgcv.background = s->face->background;
2743 xgcv.foreground = s->face->foreground;
2744 IF_DEBUG (x_check_font (s->f, s->font));
2745 xgcv.font = s->font->fid;
2746 xgcv.graphics_exposures = False;
2747 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2749 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2750 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2751 mask, &xgcv);
2752 else
2753 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2754 = XCreateGC (s->display, s->window, mask, &xgcv);
2756 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2759 xassert (s->gc != 0);
2763 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2764 Faces to use in the mode line have already been computed when the
2765 matrix was built, so there isn't much to do, here. */
2767 static INLINE void
2768 x_set_mode_line_face_gc (s)
2769 struct glyph_string *s;
2771 s->gc = s->face->gc;
2775 /* Set S->gc of glyph string S for drawing that glyph string. Set
2776 S->stippled_p to a non-zero value if the face of S has a stipple
2777 pattern. */
2779 static INLINE void
2780 x_set_glyph_string_gc (s)
2781 struct glyph_string *s;
2783 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2785 if (s->hl == DRAW_NORMAL_TEXT)
2787 s->gc = s->face->gc;
2788 s->stippled_p = s->face->stipple != 0;
2790 else if (s->hl == DRAW_INVERSE_VIDEO)
2792 x_set_mode_line_face_gc (s);
2793 s->stippled_p = s->face->stipple != 0;
2795 else if (s->hl == DRAW_CURSOR)
2797 x_set_cursor_gc (s);
2798 s->stippled_p = 0;
2800 else if (s->hl == DRAW_MOUSE_FACE)
2802 x_set_mouse_face_gc (s);
2803 s->stippled_p = s->face->stipple != 0;
2805 else if (s->hl == DRAW_IMAGE_RAISED
2806 || s->hl == DRAW_IMAGE_SUNKEN)
2808 s->gc = s->face->gc;
2809 s->stippled_p = s->face->stipple != 0;
2811 else
2813 s->gc = s->face->gc;
2814 s->stippled_p = s->face->stipple != 0;
2817 /* GC must have been set. */
2818 xassert (s->gc != 0);
2822 /* Return in *R the clipping rectangle for glyph string S. */
2824 static void
2825 x_get_glyph_string_clip_rect (s, r)
2826 struct glyph_string *s;
2827 XRectangle *r;
2829 if (s->row->full_width_p)
2831 /* Draw full-width. X coordinates are relative to S->w->left. */
2832 int canon_x = CANON_X_UNIT (s->f);
2834 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2835 r->width = XFASTINT (s->w->width) * canon_x;
2837 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2839 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2840 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2841 r->x -= width;
2844 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2846 /* Unless displaying a mode or menu bar line, which are always
2847 fully visible, clip to the visible part of the row. */
2848 if (s->w->pseudo_window_p)
2849 r->height = s->row->visible_height;
2850 else
2851 r->height = s->height;
2853 else
2855 /* This is a text line that may be partially visible. */
2856 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2857 r->width = window_box_width (s->w, s->area);
2858 r->height = s->row->visible_height;
2861 /* If S draws overlapping rows, it's sufficient to use the top and
2862 bottom of the window for clipping because this glyph string
2863 intentionally draws over other lines. */
2864 if (s->for_overlaps_p)
2866 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2867 r->height = window_text_bottom_y (s->w) - r->y;
2869 else
2871 /* Don't use S->y for clipping because it doesn't take partially
2872 visible lines into account. For example, it can be negative for
2873 partially visible lines at the top of a window. */
2874 if (!s->row->full_width_p
2875 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2876 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2877 else
2878 r->y = max (0, s->row->y);
2880 /* If drawing a tool-bar window, draw it over the internal border
2881 at the top of the window. */
2882 if (s->w == XWINDOW (s->f->tool_bar_window))
2883 r->y -= s->f->output_data.x->internal_border_width;
2886 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2890 /* Set clipping for output of glyph string S. S may be part of a mode
2891 line or menu if we don't have X toolkit support. */
2893 static INLINE void
2894 x_set_glyph_string_clipping (s)
2895 struct glyph_string *s;
2897 XRectangle r;
2898 x_get_glyph_string_clip_rect (s, &r);
2899 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2903 /* Compute left and right overhang of glyph string S. If S is a glyph
2904 string for a composition, assume overhangs don't exist. */
2906 static INLINE void
2907 x_compute_glyph_string_overhangs (s)
2908 struct glyph_string *s;
2910 if (s->cmp == NULL
2911 && s->first_glyph->type == CHAR_GLYPH)
2913 XCharStruct cs;
2914 int direction, font_ascent, font_descent;
2915 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2916 &font_ascent, &font_descent, &cs);
2917 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2918 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2923 /* Compute overhangs and x-positions for glyph string S and its
2924 predecessors, or successors. X is the starting x-position for S.
2925 BACKWARD_P non-zero means process predecessors. */
2927 static void
2928 x_compute_overhangs_and_x (s, x, backward_p)
2929 struct glyph_string *s;
2930 int x;
2931 int backward_p;
2933 if (backward_p)
2935 while (s)
2937 x_compute_glyph_string_overhangs (s);
2938 x -= s->width;
2939 s->x = x;
2940 s = s->prev;
2943 else
2945 while (s)
2947 x_compute_glyph_string_overhangs (s);
2948 s->x = x;
2949 x += s->width;
2950 s = s->next;
2956 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2957 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2958 assumed to be zero. */
2960 static void
2961 x_get_glyph_overhangs (glyph, f, left, right)
2962 struct glyph *glyph;
2963 struct frame *f;
2964 int *left, *right;
2966 *left = *right = 0;
2968 if (glyph->type == CHAR_GLYPH)
2970 XFontStruct *font;
2971 struct face *face;
2972 struct font_info *font_info;
2973 XChar2b char2b;
2974 XCharStruct *pcm;
2976 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2977 font = face->font;
2978 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2979 if (font
2980 && (pcm = x_per_char_metric (font, &char2b)))
2982 if (pcm->rbearing > pcm->width)
2983 *right = pcm->rbearing - pcm->width;
2984 if (pcm->lbearing < 0)
2985 *left = -pcm->lbearing;
2991 /* Return the index of the first glyph preceding glyph string S that
2992 is overwritten by S because of S's left overhang. Value is -1
2993 if no glyphs are overwritten. */
2995 static int
2996 x_left_overwritten (s)
2997 struct glyph_string *s;
2999 int k;
3001 if (s->left_overhang)
3003 int x = 0, i;
3004 struct glyph *glyphs = s->row->glyphs[s->area];
3005 int first = s->first_glyph - glyphs;
3007 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3008 x -= glyphs[i].pixel_width;
3010 k = i + 1;
3012 else
3013 k = -1;
3015 return k;
3019 /* Return the index of the first glyph preceding glyph string S that
3020 is overwriting S because of its right overhang. Value is -1 if no
3021 glyph in front of S overwrites S. */
3023 static int
3024 x_left_overwriting (s)
3025 struct glyph_string *s;
3027 int i, k, x;
3028 struct glyph *glyphs = s->row->glyphs[s->area];
3029 int first = s->first_glyph - glyphs;
3031 k = -1;
3032 x = 0;
3033 for (i = first - 1; i >= 0; --i)
3035 int left, right;
3036 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3037 if (x + right > 0)
3038 k = i;
3039 x -= glyphs[i].pixel_width;
3042 return k;
3046 /* Return the index of the last glyph following glyph string S that is
3047 not overwritten by S because of S's right overhang. Value is -1 if
3048 no such glyph is found. */
3050 static int
3051 x_right_overwritten (s)
3052 struct glyph_string *s;
3054 int k = -1;
3056 if (s->right_overhang)
3058 int x = 0, i;
3059 struct glyph *glyphs = s->row->glyphs[s->area];
3060 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3061 int end = s->row->used[s->area];
3063 for (i = first; i < end && s->right_overhang > x; ++i)
3064 x += glyphs[i].pixel_width;
3066 k = i;
3069 return k;
3073 /* Return the index of the last glyph following glyph string S that
3074 overwrites S because of its left overhang. Value is negative
3075 if no such glyph is found. */
3077 static int
3078 x_right_overwriting (s)
3079 struct glyph_string *s;
3081 int i, k, x;
3082 int end = s->row->used[s->area];
3083 struct glyph *glyphs = s->row->glyphs[s->area];
3084 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3086 k = -1;
3087 x = 0;
3088 for (i = first; i < end; ++i)
3090 int left, right;
3091 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3092 if (x - left < 0)
3093 k = i;
3094 x += glyphs[i].pixel_width;
3097 return k;
3101 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3103 static INLINE void
3104 x_clear_glyph_string_rect (s, x, y, w, h)
3105 struct glyph_string *s;
3106 int x, y, w, h;
3108 XGCValues xgcv;
3109 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3110 XSetForeground (s->display, s->gc, xgcv.background);
3111 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3112 XSetForeground (s->display, s->gc, xgcv.foreground);
3116 /* Draw the background of glyph_string S. If S->background_filled_p
3117 is non-zero don't draw it. FORCE_P non-zero means draw the
3118 background even if it wouldn't be drawn normally. This is used
3119 when a string preceding S draws into the background of S, or S
3120 contains the first component of a composition. */
3122 static void
3123 x_draw_glyph_string_background (s, force_p)
3124 struct glyph_string *s;
3125 int force_p;
3127 /* Nothing to do if background has already been drawn or if it
3128 shouldn't be drawn in the first place. */
3129 if (!s->background_filled_p)
3131 int box_line_width = max (s->face->box_line_width, 0);
3133 if (s->stippled_p)
3135 /* Fill background with a stipple pattern. */
3136 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3137 XFillRectangle (s->display, s->window, s->gc, s->x,
3138 s->y + box_line_width,
3139 s->background_width,
3140 s->height - 2 * box_line_width);
3141 XSetFillStyle (s->display, s->gc, FillSolid);
3142 s->background_filled_p = 1;
3144 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3145 || s->font_not_found_p
3146 || s->extends_to_end_of_line_p
3147 || force_p)
3149 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3150 s->background_width,
3151 s->height - 2 * box_line_width);
3152 s->background_filled_p = 1;
3158 /* Draw the foreground of glyph string S. */
3160 static void
3161 x_draw_glyph_string_foreground (s)
3162 struct glyph_string *s;
3164 int i, x;
3166 /* If first glyph of S has a left box line, start drawing the text
3167 of S to the right of that box line. */
3168 if (s->face->box != FACE_NO_BOX
3169 && s->first_glyph->left_box_line_p)
3170 x = s->x + abs (s->face->box_line_width);
3171 else
3172 x = s->x;
3174 /* Draw characters of S as rectangles if S's font could not be
3175 loaded. */
3176 if (s->font_not_found_p)
3178 for (i = 0; i < s->nchars; ++i)
3180 struct glyph *g = s->first_glyph + i;
3181 XDrawRectangle (s->display, s->window,
3182 s->gc, x, s->y, g->pixel_width - 1,
3183 s->height - 1);
3184 x += g->pixel_width;
3187 else
3189 char *char1b = (char *) s->char2b;
3190 int boff = s->font_info->baseline_offset;
3192 if (s->font_info->vertical_centering)
3193 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3195 /* If we can use 8-bit functions, condense S->char2b. */
3196 if (!s->two_byte_p)
3197 for (i = 0; i < s->nchars; ++i)
3198 char1b[i] = s->char2b[i].byte2;
3200 /* Draw text with XDrawString if background has already been
3201 filled. Otherwise, use XDrawImageString. (Note that
3202 XDrawImageString is usually faster than XDrawString.) Always
3203 use XDrawImageString when drawing the cursor so that there is
3204 no chance that characters under a box cursor are invisible. */
3205 if (s->for_overlaps_p
3206 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3208 /* Draw characters with 16-bit or 8-bit functions. */
3209 if (s->two_byte_p)
3210 XDrawString16 (s->display, s->window, s->gc, x,
3211 s->ybase - boff, s->char2b, s->nchars);
3212 else
3213 XDrawString (s->display, s->window, s->gc, x,
3214 s->ybase - boff, char1b, s->nchars);
3216 else
3218 if (s->two_byte_p)
3219 XDrawImageString16 (s->display, s->window, s->gc, x,
3220 s->ybase - boff, s->char2b, s->nchars);
3221 else
3222 XDrawImageString (s->display, s->window, s->gc, x,
3223 s->ybase - boff, char1b, s->nchars);
3226 if (s->face->overstrike)
3228 /* For overstriking (to simulate bold-face), draw the
3229 characters again shifted to the right by one pixel. */
3230 if (s->two_byte_p)
3231 XDrawString16 (s->display, s->window, s->gc, x + 1,
3232 s->ybase - boff, s->char2b, s->nchars);
3233 else
3234 XDrawString (s->display, s->window, s->gc, x + 1,
3235 s->ybase - boff, char1b, s->nchars);
3240 /* Draw the foreground of composite glyph string S. */
3242 static void
3243 x_draw_composite_glyph_string_foreground (s)
3244 struct glyph_string *s;
3246 int i, x;
3248 /* If first glyph of S has a left box line, start drawing the text
3249 of S to the right of that box line. */
3250 if (s->face->box != FACE_NO_BOX
3251 && s->first_glyph->left_box_line_p)
3252 x = s->x + abs (s->face->box_line_width);
3253 else
3254 x = s->x;
3256 /* S is a glyph string for a composition. S->gidx is the index of
3257 the first character drawn for glyphs of this composition.
3258 S->gidx == 0 means we are drawing the very first character of
3259 this composition. */
3261 /* Draw a rectangle for the composition if the font for the very
3262 first character of the composition could not be loaded. */
3263 if (s->font_not_found_p)
3265 if (s->gidx == 0)
3266 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3267 s->width - 1, s->height - 1);
3269 else
3271 for (i = 0; i < s->nchars; i++, ++s->gidx)
3273 XDrawString16 (s->display, s->window, s->gc,
3274 x + s->cmp->offsets[s->gidx * 2],
3275 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3276 s->char2b + i, 1);
3277 if (s->face->overstrike)
3278 XDrawString16 (s->display, s->window, s->gc,
3279 x + s->cmp->offsets[s->gidx * 2] + 1,
3280 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3281 s->char2b + i, 1);
3287 #ifdef USE_X_TOOLKIT
3289 static struct frame *x_frame_of_widget P_ ((Widget));
3290 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3291 XrmValue *, XrmValue *, XtPointer *));
3292 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3293 XrmValue *, Cardinal *));
3296 /* Return the frame on which widget WIDGET is used.. Abort if frame
3297 cannot be determined. */
3299 static struct frame *
3300 x_frame_of_widget (widget)
3301 Widget widget;
3303 struct x_display_info *dpyinfo;
3304 Lisp_Object tail;
3305 struct frame *f;
3307 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3309 /* Find the top-level shell of the widget. Note that this function
3310 can be called when the widget is not yet realized, so XtWindow
3311 (widget) == 0. That's the reason we can't simply use
3312 x_any_window_to_frame. */
3313 while (!XtIsTopLevelShell (widget))
3314 widget = XtParent (widget);
3316 /* Look for a frame with that top-level widget. Allocate the color
3317 on that frame to get the right gamma correction value. */
3318 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3319 if (GC_FRAMEP (XCAR (tail))
3320 && (f = XFRAME (XCAR (tail)),
3321 (f->output_data.nothing != 1
3322 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3323 && f->output_data.x->widget == widget)
3324 return f;
3326 abort ();
3330 /* Allocate the color COLOR->pixel on the screen and display of
3331 widget WIDGET in colormap CMAP. If an exact match cannot be
3332 allocated, try the nearest color available. Value is non-zero
3333 if successful. This is called from lwlib. */
3336 x_alloc_nearest_color_for_widget (widget, cmap, color)
3337 Widget widget;
3338 Colormap cmap;
3339 XColor *color;
3341 struct frame *f = x_frame_of_widget (widget);
3342 return x_alloc_nearest_color (f, cmap, color);
3346 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3347 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3348 If this produces the same color as PIXEL, try a color where all RGB
3349 values have DELTA added. Return the allocated color in *PIXEL.
3350 DISPLAY is the X display, CMAP is the colormap to operate on.
3351 Value is non-zero if successful. */
3354 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3355 Widget widget;
3356 Display *display;
3357 Colormap cmap;
3358 unsigned long *pixel;
3359 double factor;
3360 int delta;
3362 struct frame *f = x_frame_of_widget (widget);
3363 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3367 /* Structure specifying which arguments should be passed by Xt to
3368 cvt_string_to_pixel. We want the widget's screen and colormap. */
3370 static XtConvertArgRec cvt_string_to_pixel_args[] =
3372 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3373 sizeof (Screen *)},
3374 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3375 sizeof (Colormap)}
3379 /* The address of this variable is returned by
3380 cvt_string_to_pixel. */
3382 static Pixel cvt_string_to_pixel_value;
3385 /* Convert a color name to a pixel color.
3387 DPY is the display we are working on.
3389 ARGS is an array of *NARGS XrmValue structures holding additional
3390 information about the widget for which the conversion takes place.
3391 The contents of this array are determined by the specification
3392 in cvt_string_to_pixel_args.
3394 FROM is a pointer to an XrmValue which points to the color name to
3395 convert. TO is an XrmValue in which to return the pixel color.
3397 CLOSURE_RET is a pointer to user-data, in which we record if
3398 we allocated the color or not.
3400 Value is True if successful, False otherwise. */
3402 static Boolean
3403 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3404 Display *dpy;
3405 XrmValue *args;
3406 Cardinal *nargs;
3407 XrmValue *from, *to;
3408 XtPointer *closure_ret;
3410 Screen *screen;
3411 Colormap cmap;
3412 Pixel pixel;
3413 String color_name;
3414 XColor color;
3416 if (*nargs != 2)
3418 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3419 "wrongParameters", "cvt_string_to_pixel",
3420 "XtToolkitError",
3421 "Screen and colormap args required", NULL, NULL);
3422 return False;
3425 screen = *(Screen **) args[0].addr;
3426 cmap = *(Colormap *) args[1].addr;
3427 color_name = (String) from->addr;
3429 if (strcmp (color_name, XtDefaultBackground) == 0)
3431 *closure_ret = (XtPointer) False;
3432 pixel = WhitePixelOfScreen (screen);
3434 else if (strcmp (color_name, XtDefaultForeground) == 0)
3436 *closure_ret = (XtPointer) False;
3437 pixel = BlackPixelOfScreen (screen);
3439 else if (XParseColor (dpy, cmap, color_name, &color)
3440 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3442 pixel = color.pixel;
3443 *closure_ret = (XtPointer) True;
3445 else
3447 String params[1];
3448 Cardinal nparams = 1;
3450 params[0] = color_name;
3451 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3452 "badValue", "cvt_string_to_pixel",
3453 "XtToolkitError", "Invalid color `%s'",
3454 params, &nparams);
3455 return False;
3458 if (to->addr != NULL)
3460 if (to->size < sizeof (Pixel))
3462 to->size = sizeof (Pixel);
3463 return False;
3466 *(Pixel *) to->addr = pixel;
3468 else
3470 cvt_string_to_pixel_value = pixel;
3471 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3474 to->size = sizeof (Pixel);
3475 return True;
3479 /* Free a pixel color which was previously allocated via
3480 cvt_string_to_pixel. This is registered as the destructor
3481 for this type of resource via XtSetTypeConverter.
3483 APP is the application context in which we work.
3485 TO is a pointer to an XrmValue holding the color to free.
3486 CLOSURE is the value we stored in CLOSURE_RET for this color
3487 in cvt_string_to_pixel.
3489 ARGS and NARGS are like for cvt_string_to_pixel. */
3491 static void
3492 cvt_pixel_dtor (app, to, closure, args, nargs)
3493 XtAppContext app;
3494 XrmValuePtr to;
3495 XtPointer closure;
3496 XrmValuePtr args;
3497 Cardinal *nargs;
3499 if (*nargs != 2)
3501 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3502 "XtToolkitError",
3503 "Screen and colormap arguments required",
3504 NULL, NULL);
3506 else if (closure != NULL)
3508 /* We did allocate the pixel, so free it. */
3509 Screen *screen = *(Screen **) args[0].addr;
3510 Colormap cmap = *(Colormap *) args[1].addr;
3511 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3512 (Pixel *) to->addr, 1);
3517 #endif /* USE_X_TOOLKIT */
3520 /* Value is an array of XColor structures for the contents of the
3521 color map of display DPY. Set *NCELLS to the size of the array.
3522 Note that this probably shouldn't be called for large color maps,
3523 say a 24-bit TrueColor map. */
3525 static const XColor *
3526 x_color_cells (dpy, ncells)
3527 Display *dpy;
3528 int *ncells;
3530 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3532 if (dpyinfo->color_cells == NULL)
3534 Screen *screen = dpyinfo->screen;
3535 int i;
3537 dpyinfo->ncolor_cells
3538 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3539 dpyinfo->color_cells
3540 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3541 * sizeof *dpyinfo->color_cells);
3543 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3544 dpyinfo->color_cells[i].pixel = i;
3546 XQueryColors (dpy, dpyinfo->cmap,
3547 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3550 *ncells = dpyinfo->ncolor_cells;
3551 return dpyinfo->color_cells;
3555 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3556 colors in COLORS. Use cached information, if available. */
3558 void
3559 x_query_colors (f, colors, ncolors)
3560 struct frame *f;
3561 XColor *colors;
3562 int ncolors;
3564 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3566 if (dpyinfo->color_cells)
3568 int i;
3569 for (i = 0; i < ncolors; ++i)
3571 unsigned long pixel = colors[i].pixel;
3572 xassert (pixel < dpyinfo->ncolor_cells);
3573 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3574 colors[i] = dpyinfo->color_cells[pixel];
3577 else
3578 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3582 /* On frame F, translate pixel color to RGB values for the color in
3583 COLOR. Use cached information, if available. */
3585 void
3586 x_query_color (f, color)
3587 struct frame *f;
3588 XColor *color;
3590 x_query_colors (f, color, 1);
3594 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3595 exact match can't be allocated, try the nearest color available.
3596 Value is non-zero if successful. Set *COLOR to the color
3597 allocated. */
3599 static int
3600 x_alloc_nearest_color_1 (dpy, cmap, color)
3601 Display *dpy;
3602 Colormap cmap;
3603 XColor *color;
3605 int rc;
3607 rc = XAllocColor (dpy, cmap, color);
3608 if (rc == 0)
3610 /* If we got to this point, the colormap is full, so we're going
3611 to try to get the next closest color. The algorithm used is
3612 a least-squares matching, which is what X uses for closest
3613 color matching with StaticColor visuals. */
3614 int nearest, i;
3615 unsigned long nearest_delta = ~0;
3616 int ncells;
3617 const XColor *cells = x_color_cells (dpy, &ncells);
3619 for (nearest = i = 0; i < ncells; ++i)
3621 long dred = (color->red >> 8) - (cells[i].red >> 8);
3622 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3623 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3624 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3626 if (delta < nearest_delta)
3628 nearest = i;
3629 nearest_delta = delta;
3633 color->red = cells[nearest].red;
3634 color->green = cells[nearest].green;
3635 color->blue = cells[nearest].blue;
3636 rc = XAllocColor (dpy, cmap, color);
3638 else
3640 /* If allocation succeeded, and the allocated pixel color is not
3641 equal to a cached pixel color recorded earlier, there was a
3642 change in the colormap, so clear the color cache. */
3643 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3644 XColor *cached_color;
3646 if (dpyinfo->color_cells
3647 && (cached_color = &dpyinfo->color_cells[color->pixel],
3648 (cached_color->red != color->red
3649 || cached_color->blue != color->blue
3650 || cached_color->green != color->green)))
3652 xfree (dpyinfo->color_cells);
3653 dpyinfo->color_cells = NULL;
3654 dpyinfo->ncolor_cells = 0;
3658 #ifdef DEBUG_X_COLORS
3659 if (rc)
3660 register_color (color->pixel);
3661 #endif /* DEBUG_X_COLORS */
3663 return rc;
3667 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3668 exact match can't be allocated, try the nearest color available.
3669 Value is non-zero if successful. Set *COLOR to the color
3670 allocated. */
3673 x_alloc_nearest_color (f, cmap, color)
3674 struct frame *f;
3675 Colormap cmap;
3676 XColor *color;
3678 gamma_correct (f, color);
3679 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3683 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3684 It's necessary to do this instead of just using PIXEL directly to
3685 get color reference counts right. */
3687 unsigned long
3688 x_copy_color (f, pixel)
3689 struct frame *f;
3690 unsigned long pixel;
3692 XColor color;
3694 color.pixel = pixel;
3695 BLOCK_INPUT;
3696 x_query_color (f, &color);
3697 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3698 UNBLOCK_INPUT;
3699 #ifdef DEBUG_X_COLORS
3700 register_color (pixel);
3701 #endif
3702 return color.pixel;
3706 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3707 It's necessary to do this instead of just using PIXEL directly to
3708 get color reference counts right. */
3710 unsigned long
3711 x_copy_dpy_color (dpy, cmap, pixel)
3712 Display *dpy;
3713 Colormap cmap;
3714 unsigned long pixel;
3716 XColor color;
3718 color.pixel = pixel;
3719 BLOCK_INPUT;
3720 XQueryColor (dpy, cmap, &color);
3721 XAllocColor (dpy, cmap, &color);
3722 UNBLOCK_INPUT;
3723 #ifdef DEBUG_X_COLORS
3724 register_color (pixel);
3725 #endif
3726 return color.pixel;
3730 /* Brightness beyond which a color won't have its highlight brightness
3731 boosted.
3733 Nominally, highlight colors for `3d' faces are calculated by
3734 brightening an object's color by a constant scale factor, but this
3735 doesn't yield good results for dark colors, so for colors who's
3736 brightness is less than this value (on a scale of 0-65535) have an
3737 use an additional additive factor.
3739 The value here is set so that the default menu-bar/mode-line color
3740 (grey75) will not have its highlights changed at all. */
3741 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3744 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3745 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3746 If this produces the same color as PIXEL, try a color where all RGB
3747 values have DELTA added. Return the allocated color in *PIXEL.
3748 DISPLAY is the X display, CMAP is the colormap to operate on.
3749 Value is non-zero if successful. */
3751 static int
3752 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3753 struct frame *f;
3754 Display *display;
3755 Colormap cmap;
3756 unsigned long *pixel;
3757 double factor;
3758 int delta;
3760 XColor color, new;
3761 long bright;
3762 int success_p;
3764 /* Get RGB color values. */
3765 color.pixel = *pixel;
3766 x_query_color (f, &color);
3768 /* Change RGB values by specified FACTOR. Avoid overflow! */
3769 xassert (factor >= 0);
3770 new.red = min (0xffff, factor * color.red);
3771 new.green = min (0xffff, factor * color.green);
3772 new.blue = min (0xffff, factor * color.blue);
3774 /* Calculate brightness of COLOR. */
3775 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3777 /* We only boost colors that are darker than
3778 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3779 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3780 /* Make an additive adjustment to NEW, because it's dark enough so
3781 that scaling by FACTOR alone isn't enough. */
3783 /* How far below the limit this color is (0 - 1, 1 being darker). */
3784 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3785 /* The additive adjustment. */
3786 int min_delta = delta * dimness * factor / 2;
3788 if (factor < 1)
3790 new.red = max (0, new.red - min_delta);
3791 new.green = max (0, new.green - min_delta);
3792 new.blue = max (0, new.blue - min_delta);
3794 else
3796 new.red = min (0xffff, min_delta + new.red);
3797 new.green = min (0xffff, min_delta + new.green);
3798 new.blue = min (0xffff, min_delta + new.blue);
3802 /* Try to allocate the color. */
3803 success_p = x_alloc_nearest_color (f, cmap, &new);
3804 if (success_p)
3806 if (new.pixel == *pixel)
3808 /* If we end up with the same color as before, try adding
3809 delta to the RGB values. */
3810 x_free_colors (f, &new.pixel, 1);
3812 new.red = min (0xffff, delta + color.red);
3813 new.green = min (0xffff, delta + color.green);
3814 new.blue = min (0xffff, delta + color.blue);
3815 success_p = x_alloc_nearest_color (f, cmap, &new);
3817 else
3818 success_p = 1;
3819 *pixel = new.pixel;
3822 return success_p;
3826 /* Set up the foreground color for drawing relief lines of glyph
3827 string S. RELIEF is a pointer to a struct relief containing the GC
3828 with which lines will be drawn. Use a color that is FACTOR or
3829 DELTA lighter or darker than the relief's background which is found
3830 in S->f->output_data.x->relief_background. If such a color cannot
3831 be allocated, use DEFAULT_PIXEL, instead. */
3833 static void
3834 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3835 struct frame *f;
3836 struct relief *relief;
3837 double factor;
3838 int delta;
3839 unsigned long default_pixel;
3841 XGCValues xgcv;
3842 struct x_output *di = f->output_data.x;
3843 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3844 unsigned long pixel;
3845 unsigned long background = di->relief_background;
3846 Colormap cmap = FRAME_X_COLORMAP (f);
3847 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3848 Display *dpy = FRAME_X_DISPLAY (f);
3850 xgcv.graphics_exposures = False;
3851 xgcv.line_width = 1;
3853 /* Free previously allocated color. The color cell will be reused
3854 when it has been freed as many times as it was allocated, so this
3855 doesn't affect faces using the same colors. */
3856 if (relief->gc
3857 && relief->allocated_p)
3859 x_free_colors (f, &relief->pixel, 1);
3860 relief->allocated_p = 0;
3863 /* Allocate new color. */
3864 xgcv.foreground = default_pixel;
3865 pixel = background;
3866 if (dpyinfo->n_planes != 1
3867 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3869 relief->allocated_p = 1;
3870 xgcv.foreground = relief->pixel = pixel;
3873 if (relief->gc == 0)
3875 xgcv.stipple = dpyinfo->gray;
3876 mask |= GCStipple;
3877 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3879 else
3880 XChangeGC (dpy, relief->gc, mask, &xgcv);
3884 /* Set up colors for the relief lines around glyph string S. */
3886 static void
3887 x_setup_relief_colors (s)
3888 struct glyph_string *s;
3890 struct x_output *di = s->f->output_data.x;
3891 unsigned long color;
3893 if (s->face->use_box_color_for_shadows_p)
3894 color = s->face->box_color;
3895 else if (s->first_glyph->type == IMAGE_GLYPH
3896 && s->img->pixmap
3897 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3898 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3899 else
3901 XGCValues xgcv;
3903 /* Get the background color of the face. */
3904 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3905 color = xgcv.background;
3908 if (di->white_relief.gc == 0
3909 || color != di->relief_background)
3911 di->relief_background = color;
3912 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3913 WHITE_PIX_DEFAULT (s->f));
3914 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3915 BLACK_PIX_DEFAULT (s->f));
3920 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3921 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3922 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3923 relief. LEFT_P non-zero means draw a relief on the left side of
3924 the rectangle. RIGHT_P non-zero means draw a relief on the right
3925 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3926 when drawing. */
3928 static void
3929 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3930 raised_p, left_p, right_p, clip_rect)
3931 struct frame *f;
3932 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
3933 XRectangle *clip_rect;
3935 Display *dpy = FRAME_X_DISPLAY (f);
3936 Window window = FRAME_X_WINDOW (f);
3937 int i;
3938 GC gc;
3940 if (raised_p)
3941 gc = f->output_data.x->white_relief.gc;
3942 else
3943 gc = f->output_data.x->black_relief.gc;
3944 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3946 /* Top. */
3947 for (i = 0; i < width; ++i)
3948 XDrawLine (dpy, window, gc,
3949 left_x + i * left_p, top_y + i,
3950 right_x + 1 - i * right_p, top_y + i);
3952 /* Left. */
3953 if (left_p)
3954 for (i = 0; i < width; ++i)
3955 XDrawLine (dpy, window, gc,
3956 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3958 XSetClipMask (dpy, gc, None);
3959 if (raised_p)
3960 gc = f->output_data.x->black_relief.gc;
3961 else
3962 gc = f->output_data.x->white_relief.gc;
3963 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3965 /* Bottom. */
3966 for (i = 0; i < width; ++i)
3967 XDrawLine (dpy, window, gc,
3968 left_x + i * left_p, bottom_y - i,
3969 right_x + 1 - i * right_p, bottom_y - i);
3971 /* Right. */
3972 if (right_p)
3973 for (i = 0; i < width; ++i)
3974 XDrawLine (dpy, window, gc,
3975 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3977 XSetClipMask (dpy, gc, None);
3981 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3982 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3983 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3984 left side of the rectangle. RIGHT_P non-zero means draw a line
3985 on the right side of the rectangle. CLIP_RECT is the clipping
3986 rectangle to use when drawing. */
3988 static void
3989 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3990 left_p, right_p, clip_rect)
3991 struct glyph_string *s;
3992 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3993 XRectangle *clip_rect;
3995 XGCValues xgcv;
3997 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3998 XSetForeground (s->display, s->gc, s->face->box_color);
3999 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
4001 /* Top. */
4002 XFillRectangle (s->display, s->window, s->gc,
4003 left_x, top_y, right_x - left_x + 1, width);
4005 /* Left. */
4006 if (left_p)
4007 XFillRectangle (s->display, s->window, s->gc,
4008 left_x, top_y, width, bottom_y - top_y + 1);
4010 /* Bottom. */
4011 XFillRectangle (s->display, s->window, s->gc,
4012 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
4014 /* Right. */
4015 if (right_p)
4016 XFillRectangle (s->display, s->window, s->gc,
4017 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
4019 XSetForeground (s->display, s->gc, xgcv.foreground);
4020 XSetClipMask (s->display, s->gc, None);
4024 /* Draw a box around glyph string S. */
4026 static void
4027 x_draw_glyph_string_box (s)
4028 struct glyph_string *s;
4030 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4031 int left_p, right_p;
4032 struct glyph *last_glyph;
4033 XRectangle clip_rect;
4035 last_x = window_box_right (s->w, s->area);
4036 if (s->row->full_width_p
4037 && !s->w->pseudo_window_p)
4039 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4040 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4041 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4044 /* The glyph that may have a right box line. */
4045 last_glyph = (s->cmp || s->img
4046 ? s->first_glyph
4047 : s->first_glyph + s->nchars - 1);
4049 width = abs (s->face->box_line_width);
4050 raised_p = s->face->box == FACE_RAISED_BOX;
4051 left_x = s->x;
4052 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
4053 ? last_x - 1
4054 : min (last_x, s->x + s->background_width) - 1);
4055 top_y = s->y;
4056 bottom_y = top_y + s->height - 1;
4058 left_p = (s->first_glyph->left_box_line_p
4059 || (s->hl == DRAW_MOUSE_FACE
4060 && (s->prev == NULL
4061 || s->prev->hl != s->hl)));
4062 right_p = (last_glyph->right_box_line_p
4063 || (s->hl == DRAW_MOUSE_FACE
4064 && (s->next == NULL
4065 || s->next->hl != s->hl)));
4067 x_get_glyph_string_clip_rect (s, &clip_rect);
4069 if (s->face->box == FACE_SIMPLE_BOX)
4070 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4071 left_p, right_p, &clip_rect);
4072 else
4074 x_setup_relief_colors (s);
4075 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4076 width, raised_p, left_p, right_p, &clip_rect);
4081 /* Draw foreground of image glyph string S. */
4083 static void
4084 x_draw_image_foreground (s)
4085 struct glyph_string *s;
4087 int x;
4088 int y = s->ybase - image_ascent (s->img, s->face);
4090 /* If first glyph of S has a left box line, start drawing it to the
4091 right of that line. */
4092 if (s->face->box != FACE_NO_BOX
4093 && s->first_glyph->left_box_line_p)
4094 x = s->x + abs (s->face->box_line_width);
4095 else
4096 x = s->x;
4098 /* If there is a margin around the image, adjust x- and y-position
4099 by that margin. */
4100 x += s->img->hmargin;
4101 y += s->img->vmargin;
4103 if (s->img->pixmap)
4105 if (s->img->mask)
4107 /* We can't set both a clip mask and use XSetClipRectangles
4108 because the latter also sets a clip mask. We also can't
4109 trust on the shape extension to be available
4110 (XShapeCombineRegion). So, compute the rectangle to draw
4111 manually. */
4112 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4113 | GCFunction);
4114 XGCValues xgcv;
4115 XRectangle clip_rect, image_rect, r;
4117 xgcv.clip_mask = s->img->mask;
4118 xgcv.clip_x_origin = x;
4119 xgcv.clip_y_origin = y;
4120 xgcv.function = GXcopy;
4121 XChangeGC (s->display, s->gc, mask, &xgcv);
4123 x_get_glyph_string_clip_rect (s, &clip_rect);
4124 image_rect.x = x;
4125 image_rect.y = y;
4126 image_rect.width = s->img->width;
4127 image_rect.height = s->img->height;
4128 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4129 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4130 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4132 else
4134 XRectangle clip_rect, image_rect, r;
4136 x_get_glyph_string_clip_rect (s, &clip_rect);
4137 image_rect.x = x;
4138 image_rect.y = y;
4139 image_rect.width = s->img->width;
4140 image_rect.height = s->img->height;
4141 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4142 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4143 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4145 /* When the image has a mask, we can expect that at
4146 least part of a mouse highlight or a block cursor will
4147 be visible. If the image doesn't have a mask, make
4148 a block cursor visible by drawing a rectangle around
4149 the image. I believe it's looking better if we do
4150 nothing here for mouse-face. */
4151 if (s->hl == DRAW_CURSOR)
4153 int r = s->img->relief;
4154 if (r < 0) r = -r;
4155 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4156 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4160 else
4161 /* Draw a rectangle if image could not be loaded. */
4162 XDrawRectangle (s->display, s->window, s->gc, x, y,
4163 s->img->width - 1, s->img->height - 1);
4167 /* Draw a relief around the image glyph string S. */
4169 static void
4170 x_draw_image_relief (s)
4171 struct glyph_string *s;
4173 int x0, y0, x1, y1, thick, raised_p;
4174 XRectangle r;
4175 int x;
4176 int y = s->ybase - image_ascent (s->img, s->face);
4178 /* If first glyph of S has a left box line, start drawing it to the
4179 right of that line. */
4180 if (s->face->box != FACE_NO_BOX
4181 && s->first_glyph->left_box_line_p)
4182 x = s->x + abs (s->face->box_line_width);
4183 else
4184 x = s->x;
4186 /* If there is a margin around the image, adjust x- and y-position
4187 by that margin. */
4188 x += s->img->hmargin;
4189 y += s->img->vmargin;
4191 if (s->hl == DRAW_IMAGE_SUNKEN
4192 || s->hl == DRAW_IMAGE_RAISED)
4194 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4195 raised_p = s->hl == DRAW_IMAGE_RAISED;
4197 else
4199 thick = abs (s->img->relief);
4200 raised_p = s->img->relief > 0;
4203 x0 = x - thick;
4204 y0 = y - thick;
4205 x1 = x + s->img->width + thick - 1;
4206 y1 = y + s->img->height + thick - 1;
4208 x_setup_relief_colors (s);
4209 x_get_glyph_string_clip_rect (s, &r);
4210 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4214 /* Draw the foreground of image glyph string S to PIXMAP. */
4216 static void
4217 x_draw_image_foreground_1 (s, pixmap)
4218 struct glyph_string *s;
4219 Pixmap pixmap;
4221 int x;
4222 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4224 /* If first glyph of S has a left box line, start drawing it to the
4225 right of that line. */
4226 if (s->face->box != FACE_NO_BOX
4227 && s->first_glyph->left_box_line_p)
4228 x = abs (s->face->box_line_width);
4229 else
4230 x = 0;
4232 /* If there is a margin around the image, adjust x- and y-position
4233 by that margin. */
4234 x += s->img->hmargin;
4235 y += s->img->vmargin;
4237 if (s->img->pixmap)
4239 if (s->img->mask)
4241 /* We can't set both a clip mask and use XSetClipRectangles
4242 because the latter also sets a clip mask. We also can't
4243 trust on the shape extension to be available
4244 (XShapeCombineRegion). So, compute the rectangle to draw
4245 manually. */
4246 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4247 | GCFunction);
4248 XGCValues xgcv;
4250 xgcv.clip_mask = s->img->mask;
4251 xgcv.clip_x_origin = x;
4252 xgcv.clip_y_origin = y;
4253 xgcv.function = GXcopy;
4254 XChangeGC (s->display, s->gc, mask, &xgcv);
4256 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4257 0, 0, s->img->width, s->img->height, x, y);
4258 XSetClipMask (s->display, s->gc, None);
4260 else
4262 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4263 0, 0, s->img->width, s->img->height, x, y);
4265 /* When the image has a mask, we can expect that at
4266 least part of a mouse highlight or a block cursor will
4267 be visible. If the image doesn't have a mask, make
4268 a block cursor visible by drawing a rectangle around
4269 the image. I believe it's looking better if we do
4270 nothing here for mouse-face. */
4271 if (s->hl == DRAW_CURSOR)
4273 int r = s->img->relief;
4274 if (r < 0) r = -r;
4275 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4276 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4280 else
4281 /* Draw a rectangle if image could not be loaded. */
4282 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4283 s->img->width - 1, s->img->height - 1);
4287 /* Draw part of the background of glyph string S. X, Y, W, and H
4288 give the rectangle to draw. */
4290 static void
4291 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4292 struct glyph_string *s;
4293 int x, y, w, h;
4295 if (s->stippled_p)
4297 /* Fill background with a stipple pattern. */
4298 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4299 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4300 XSetFillStyle (s->display, s->gc, FillSolid);
4302 else
4303 x_clear_glyph_string_rect (s, x, y, w, h);
4307 /* Draw image glyph string S.
4309 s->y
4310 s->x +-------------------------
4311 | s->face->box
4313 | +-------------------------
4314 | | s->img->margin
4316 | | +-------------------
4317 | | | the image
4321 static void
4322 x_draw_image_glyph_string (s)
4323 struct glyph_string *s;
4325 int x, y;
4326 int box_line_hwidth = abs (s->face->box_line_width);
4327 int box_line_vwidth = max (s->face->box_line_width, 0);
4328 int height;
4329 Pixmap pixmap = None;
4331 height = s->height - 2 * box_line_vwidth;
4333 /* Fill background with face under the image. Do it only if row is
4334 taller than image or if image has a clip mask to reduce
4335 flickering. */
4336 s->stippled_p = s->face->stipple != 0;
4337 if (height > s->img->height
4338 || s->img->hmargin
4339 || s->img->vmargin
4340 || s->img->mask
4341 || s->img->pixmap == 0
4342 || s->width != s->background_width)
4344 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4345 x = s->x + box_line_hwidth;
4346 else
4347 x = s->x;
4349 y = s->y + box_line_vwidth;
4351 if (s->img->mask)
4353 /* Create a pixmap as large as the glyph string. Fill it
4354 with the background color. Copy the image to it, using
4355 its mask. Copy the temporary pixmap to the display. */
4356 Screen *screen = FRAME_X_SCREEN (s->f);
4357 int depth = DefaultDepthOfScreen (screen);
4359 /* Create a pixmap as large as the glyph string. */
4360 pixmap = XCreatePixmap (s->display, s->window,
4361 s->background_width,
4362 s->height, depth);
4364 /* Don't clip in the following because we're working on the
4365 pixmap. */
4366 XSetClipMask (s->display, s->gc, None);
4368 /* Fill the pixmap with the background color/stipple. */
4369 if (s->stippled_p)
4371 /* Fill background with a stipple pattern. */
4372 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4373 XFillRectangle (s->display, pixmap, s->gc,
4374 0, 0, s->background_width, s->height);
4375 XSetFillStyle (s->display, s->gc, FillSolid);
4377 else
4379 XGCValues xgcv;
4380 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4381 &xgcv);
4382 XSetForeground (s->display, s->gc, xgcv.background);
4383 XFillRectangle (s->display, pixmap, s->gc,
4384 0, 0, s->background_width, s->height);
4385 XSetForeground (s->display, s->gc, xgcv.foreground);
4388 else
4389 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4391 s->background_filled_p = 1;
4394 /* Draw the foreground. */
4395 if (pixmap != None)
4397 x_draw_image_foreground_1 (s, pixmap);
4398 x_set_glyph_string_clipping (s);
4399 XCopyArea (s->display, pixmap, s->window, s->gc,
4400 0, 0, s->background_width, s->height, s->x, s->y);
4401 XFreePixmap (s->display, pixmap);
4403 else
4404 x_draw_image_foreground (s);
4406 /* If we must draw a relief around the image, do it. */
4407 if (s->img->relief
4408 || s->hl == DRAW_IMAGE_RAISED
4409 || s->hl == DRAW_IMAGE_SUNKEN)
4410 x_draw_image_relief (s);
4414 /* Draw stretch glyph string S. */
4416 static void
4417 x_draw_stretch_glyph_string (s)
4418 struct glyph_string *s;
4420 xassert (s->first_glyph->type == STRETCH_GLYPH);
4421 s->stippled_p = s->face->stipple != 0;
4423 if (s->hl == DRAW_CURSOR
4424 && !x_stretch_cursor_p)
4426 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4427 as wide as the stretch glyph. */
4428 int width = min (CANON_X_UNIT (s->f), s->background_width);
4430 /* Draw cursor. */
4431 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4433 /* Clear rest using the GC of the original non-cursor face. */
4434 if (width < s->background_width)
4436 int x = s->x + width, y = s->y;
4437 int w = s->background_width - width, h = s->height;
4438 XRectangle r;
4439 GC gc;
4441 if (s->row->mouse_face_p
4442 && cursor_in_mouse_face_p (s->w))
4444 x_set_mouse_face_gc (s);
4445 gc = s->gc;
4447 else
4448 gc = s->face->gc;
4450 x_get_glyph_string_clip_rect (s, &r);
4451 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4453 if (s->face->stipple)
4455 /* Fill background with a stipple pattern. */
4456 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4457 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4458 XSetFillStyle (s->display, gc, FillSolid);
4460 else
4462 XGCValues xgcv;
4463 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4464 XSetForeground (s->display, gc, xgcv.background);
4465 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4466 XSetForeground (s->display, gc, xgcv.foreground);
4470 else if (!s->background_filled_p)
4471 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4472 s->height);
4474 s->background_filled_p = 1;
4478 /* Draw glyph string S. */
4480 static void
4481 x_draw_glyph_string (s)
4482 struct glyph_string *s;
4484 int relief_drawn_p = 0;
4486 /* If S draws into the background of its successor, draw the
4487 background of the successor first so that S can draw into it.
4488 This makes S->next use XDrawString instead of XDrawImageString. */
4489 if (s->next && s->right_overhang && !s->for_overlaps_p)
4491 xassert (s->next->img == NULL);
4492 x_set_glyph_string_gc (s->next);
4493 x_set_glyph_string_clipping (s->next);
4494 x_draw_glyph_string_background (s->next, 1);
4497 /* Set up S->gc, set clipping and draw S. */
4498 x_set_glyph_string_gc (s);
4500 /* Draw relief (if any) in advance for char/composition so that the
4501 glyph string can be drawn over it. */
4502 if (!s->for_overlaps_p
4503 && s->face->box != FACE_NO_BOX
4504 && (s->first_glyph->type == CHAR_GLYPH
4505 || s->first_glyph->type == COMPOSITE_GLYPH))
4508 x_set_glyph_string_clipping (s);
4509 x_draw_glyph_string_background (s, 1);
4510 x_draw_glyph_string_box (s);
4511 x_set_glyph_string_clipping (s);
4512 relief_drawn_p = 1;
4514 else
4515 x_set_glyph_string_clipping (s);
4517 switch (s->first_glyph->type)
4519 case IMAGE_GLYPH:
4520 x_draw_image_glyph_string (s);
4521 break;
4523 case STRETCH_GLYPH:
4524 x_draw_stretch_glyph_string (s);
4525 break;
4527 case CHAR_GLYPH:
4528 if (s->for_overlaps_p)
4529 s->background_filled_p = 1;
4530 else
4531 x_draw_glyph_string_background (s, 0);
4532 x_draw_glyph_string_foreground (s);
4533 break;
4535 case COMPOSITE_GLYPH:
4536 if (s->for_overlaps_p || s->gidx > 0)
4537 s->background_filled_p = 1;
4538 else
4539 x_draw_glyph_string_background (s, 1);
4540 x_draw_composite_glyph_string_foreground (s);
4541 break;
4543 default:
4544 abort ();
4547 if (!s->for_overlaps_p)
4549 /* Draw underline. */
4550 if (s->face->underline_p)
4552 unsigned long tem, h;
4553 int y;
4555 /* Get the underline thickness. Default is 1 pixel. */
4556 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4557 h = 1;
4559 /* Get the underline position. This is the recommended
4560 vertical offset in pixels from the baseline to the top of
4561 the underline. This is a signed value according to the
4562 specs, and its default is
4564 ROUND ((maximum descent) / 2), with
4565 ROUND(x) = floor (x + 0.5) */
4567 if (x_use_underline_position_properties
4568 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4569 y = s->ybase + (long) tem;
4570 else if (s->face->font)
4571 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4572 else
4573 y = s->y + s->height - h;
4575 if (s->face->underline_defaulted_p)
4576 XFillRectangle (s->display, s->window, s->gc,
4577 s->x, y, s->width, h);
4578 else
4580 XGCValues xgcv;
4581 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4582 XSetForeground (s->display, s->gc, s->face->underline_color);
4583 XFillRectangle (s->display, s->window, s->gc,
4584 s->x, y, s->width, h);
4585 XSetForeground (s->display, s->gc, xgcv.foreground);
4589 /* Draw overline. */
4590 if (s->face->overline_p)
4592 unsigned long dy = 0, h = 1;
4594 if (s->face->overline_color_defaulted_p)
4595 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4596 s->width, h);
4597 else
4599 XGCValues xgcv;
4600 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4601 XSetForeground (s->display, s->gc, s->face->overline_color);
4602 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4603 s->width, h);
4604 XSetForeground (s->display, s->gc, xgcv.foreground);
4608 /* Draw strike-through. */
4609 if (s->face->strike_through_p)
4611 unsigned long h = 1;
4612 unsigned long dy = (s->height - h) / 2;
4614 if (s->face->strike_through_color_defaulted_p)
4615 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4616 s->width, h);
4617 else
4619 XGCValues xgcv;
4620 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4621 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4622 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4623 s->width, h);
4624 XSetForeground (s->display, s->gc, xgcv.foreground);
4628 /* Draw relief if not yet drawn. */
4629 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4630 x_draw_glyph_string_box (s);
4633 /* Reset clipping. */
4634 XSetClipMask (s->display, s->gc, None);
4638 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4639 struct face **, int));
4642 /* Fill glyph string S with composition components specified by S->cmp.
4644 FACES is an array of faces for all components of this composition.
4645 S->gidx is the index of the first component for S.
4646 OVERLAPS_P non-zero means S should draw the foreground only, and
4647 use its physical height for clipping.
4649 Value is the index of a component not in S. */
4651 static int
4652 x_fill_composite_glyph_string (s, faces, overlaps_p)
4653 struct glyph_string *s;
4654 struct face **faces;
4655 int overlaps_p;
4657 int i;
4659 xassert (s);
4661 s->for_overlaps_p = overlaps_p;
4663 s->face = faces[s->gidx];
4664 s->font = s->face->font;
4665 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4667 /* For all glyphs of this composition, starting at the offset
4668 S->gidx, until we reach the end of the definition or encounter a
4669 glyph that requires the different face, add it to S. */
4670 ++s->nchars;
4671 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4672 ++s->nchars;
4674 /* All glyph strings for the same composition has the same width,
4675 i.e. the width set for the first component of the composition. */
4677 s->width = s->first_glyph->pixel_width;
4679 /* If the specified font could not be loaded, use the frame's
4680 default font, but record the fact that we couldn't load it in
4681 the glyph string so that we can draw rectangles for the
4682 characters of the glyph string. */
4683 if (s->font == NULL)
4685 s->font_not_found_p = 1;
4686 s->font = FRAME_FONT (s->f);
4689 /* Adjust base line for subscript/superscript text. */
4690 s->ybase += s->first_glyph->voffset;
4692 xassert (s->face && s->face->gc);
4694 /* This glyph string must always be drawn with 16-bit functions. */
4695 s->two_byte_p = 1;
4697 return s->gidx + s->nchars;
4701 /* Fill glyph string S from a sequence of character glyphs.
4703 FACE_ID is the face id of the string. START is the index of the
4704 first glyph to consider, END is the index of the last + 1.
4705 OVERLAPS_P non-zero means S should draw the foreground only, and
4706 use its physical height for clipping.
4708 Value is the index of the first glyph not in S. */
4710 static int
4711 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4712 struct glyph_string *s;
4713 int face_id;
4714 int start, end, overlaps_p;
4716 struct glyph *glyph, *last;
4717 int voffset;
4718 int glyph_not_available_p;
4720 xassert (s->f == XFRAME (s->w->frame));
4721 xassert (s->nchars == 0);
4722 xassert (start >= 0 && end > start);
4724 s->for_overlaps_p = overlaps_p,
4725 glyph = s->row->glyphs[s->area] + start;
4726 last = s->row->glyphs[s->area] + end;
4727 voffset = glyph->voffset;
4729 glyph_not_available_p = glyph->glyph_not_available_p;
4731 while (glyph < last
4732 && glyph->type == CHAR_GLYPH
4733 && glyph->voffset == voffset
4734 /* Same face id implies same font, nowadays. */
4735 && glyph->face_id == face_id
4736 && glyph->glyph_not_available_p == glyph_not_available_p)
4738 int two_byte_p;
4740 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4741 s->char2b + s->nchars,
4742 &two_byte_p);
4743 s->two_byte_p = two_byte_p;
4744 ++s->nchars;
4745 xassert (s->nchars <= end - start);
4746 s->width += glyph->pixel_width;
4747 ++glyph;
4750 s->font = s->face->font;
4751 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4753 /* If the specified font could not be loaded, use the frame's font,
4754 but record the fact that we couldn't load it in
4755 S->font_not_found_p so that we can draw rectangles for the
4756 characters of the glyph string. */
4757 if (s->font == NULL || glyph_not_available_p)
4759 s->font_not_found_p = 1;
4760 s->font = FRAME_FONT (s->f);
4763 /* Adjust base line for subscript/superscript text. */
4764 s->ybase += voffset;
4766 xassert (s->face && s->face->gc);
4767 return glyph - s->row->glyphs[s->area];
4771 /* Fill glyph string S from image glyph S->first_glyph. */
4773 static void
4774 x_fill_image_glyph_string (s)
4775 struct glyph_string *s;
4777 xassert (s->first_glyph->type == IMAGE_GLYPH);
4778 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4779 xassert (s->img);
4780 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4781 s->font = s->face->font;
4782 s->width = s->first_glyph->pixel_width;
4784 /* Adjust base line for subscript/superscript text. */
4785 s->ybase += s->first_glyph->voffset;
4789 /* Fill glyph string S from a sequence of stretch glyphs.
4791 ROW is the glyph row in which the glyphs are found, AREA is the
4792 area within the row. START is the index of the first glyph to
4793 consider, END is the index of the last + 1.
4795 Value is the index of the first glyph not in S. */
4797 static int
4798 x_fill_stretch_glyph_string (s, row, area, start, end)
4799 struct glyph_string *s;
4800 struct glyph_row *row;
4801 enum glyph_row_area area;
4802 int start, end;
4804 struct glyph *glyph, *last;
4805 int voffset, face_id;
4807 xassert (s->first_glyph->type == STRETCH_GLYPH);
4809 glyph = s->row->glyphs[s->area] + start;
4810 last = s->row->glyphs[s->area] + end;
4811 face_id = glyph->face_id;
4812 s->face = FACE_FROM_ID (s->f, face_id);
4813 s->font = s->face->font;
4814 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4815 s->width = glyph->pixel_width;
4816 voffset = glyph->voffset;
4818 for (++glyph;
4819 (glyph < last
4820 && glyph->type == STRETCH_GLYPH
4821 && glyph->voffset == voffset
4822 && glyph->face_id == face_id);
4823 ++glyph)
4824 s->width += glyph->pixel_width;
4826 /* Adjust base line for subscript/superscript text. */
4827 s->ybase += voffset;
4829 /* The case that face->gc == 0 is handled when drawing the glyph
4830 string by calling PREPARE_FACE_FOR_DISPLAY. */
4831 xassert (s->face);
4832 return glyph - s->row->glyphs[s->area];
4836 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4837 of XChar2b structures for S; it can't be allocated in
4838 x_init_glyph_string because it must be allocated via `alloca'. W
4839 is the window on which S is drawn. ROW and AREA are the glyph row
4840 and area within the row from which S is constructed. START is the
4841 index of the first glyph structure covered by S. HL is a
4842 face-override for drawing S. */
4844 static void
4845 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4846 struct glyph_string *s;
4847 XChar2b *char2b;
4848 struct window *w;
4849 struct glyph_row *row;
4850 enum glyph_row_area area;
4851 int start;
4852 enum draw_glyphs_face hl;
4854 bzero (s, sizeof *s);
4855 s->w = w;
4856 s->f = XFRAME (w->frame);
4857 s->display = FRAME_X_DISPLAY (s->f);
4858 s->window = FRAME_X_WINDOW (s->f);
4859 s->char2b = char2b;
4860 s->hl = hl;
4861 s->row = row;
4862 s->area = area;
4863 s->first_glyph = row->glyphs[area] + start;
4864 s->height = row->height;
4865 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4867 /* Display the internal border below the tool-bar window. */
4868 if (s->w == XWINDOW (s->f->tool_bar_window))
4869 s->y -= s->f->output_data.x->internal_border_width;
4871 s->ybase = s->y + row->ascent;
4875 /* Set background width of glyph string S. START is the index of the
4876 first glyph following S. LAST_X is the right-most x-position + 1
4877 in the drawing area. */
4879 static INLINE void
4880 x_set_glyph_string_background_width (s, start, last_x)
4881 struct glyph_string *s;
4882 int start;
4883 int last_x;
4885 /* If the face of this glyph string has to be drawn to the end of
4886 the drawing area, set S->extends_to_end_of_line_p. */
4887 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4889 if (start == s->row->used[s->area]
4890 && s->area == TEXT_AREA
4891 && ((s->hl == DRAW_NORMAL_TEXT
4892 && (s->row->fill_line_p
4893 || s->face->background != default_face->background
4894 || s->face->stipple != default_face->stipple
4895 || s->row->mouse_face_p))
4896 || s->hl == DRAW_MOUSE_FACE
4897 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4898 && s->row->fill_line_p)))
4899 s->extends_to_end_of_line_p = 1;
4901 /* If S extends its face to the end of the line, set its
4902 background_width to the distance to the right edge of the drawing
4903 area. */
4904 if (s->extends_to_end_of_line_p)
4905 s->background_width = last_x - s->x + 1;
4906 else
4907 s->background_width = s->width;
4911 /* Add a glyph string for a stretch glyph to the list of strings
4912 between HEAD and TAIL. START is the index of the stretch glyph in
4913 row area AREA of glyph row ROW. END is the index of the last glyph
4914 in that glyph row area. X is the current output position assigned
4915 to the new glyph string constructed. HL overrides that face of the
4916 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4917 is the right-most x-position of the drawing area. */
4919 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4920 and below -- keep them on one line. */
4921 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4922 do \
4924 s = (struct glyph_string *) alloca (sizeof *s); \
4925 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4926 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4927 x_append_glyph_string (&HEAD, &TAIL, s); \
4928 s->x = (X); \
4930 while (0)
4933 /* Add a glyph string for an image glyph to the list of strings
4934 between HEAD and TAIL. START is the index of the image glyph in
4935 row area AREA of glyph row ROW. END is the index of the last glyph
4936 in that glyph row area. X is the current output position assigned
4937 to the new glyph string constructed. HL overrides that face of the
4938 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4939 is the right-most x-position of the drawing area. */
4941 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4942 do \
4944 s = (struct glyph_string *) alloca (sizeof *s); \
4945 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4946 x_fill_image_glyph_string (s); \
4947 x_append_glyph_string (&HEAD, &TAIL, s); \
4948 ++START; \
4949 s->x = (X); \
4951 while (0)
4954 /* Add a glyph string for a sequence of character glyphs to the list
4955 of strings between HEAD and TAIL. START is the index of the first
4956 glyph in row area AREA of glyph row ROW that is part of the new
4957 glyph string. END is the index of the last glyph in that glyph row
4958 area. X is the current output position assigned to the new glyph
4959 string constructed. HL overrides that face of the glyph; e.g. it
4960 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4961 right-most x-position of the drawing area. */
4963 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4964 do \
4966 int c, face_id; \
4967 XChar2b *char2b; \
4969 c = (ROW)->glyphs[AREA][START].u.ch; \
4970 face_id = (ROW)->glyphs[AREA][START].face_id; \
4972 s = (struct glyph_string *) alloca (sizeof *s); \
4973 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4974 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4975 x_append_glyph_string (&HEAD, &TAIL, s); \
4976 s->x = (X); \
4977 START = x_fill_glyph_string (s, face_id, START, END, \
4978 OVERLAPS_P); \
4980 while (0)
4983 /* Add a glyph string for a composite sequence to the list of strings
4984 between HEAD and TAIL. START is the index of the first glyph in
4985 row area AREA of glyph row ROW that is part of the new glyph
4986 string. END is the index of the last glyph in that glyph row area.
4987 X is the current output position assigned to the new glyph string
4988 constructed. HL overrides that face of the glyph; e.g. it is
4989 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4990 x-position of the drawing area. */
4992 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4993 do { \
4994 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4995 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4996 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4997 struct composition *cmp = composition_table[cmp_id]; \
4998 int glyph_len = cmp->glyph_len; \
4999 XChar2b *char2b; \
5000 struct face **faces; \
5001 struct glyph_string *first_s = NULL; \
5002 int n; \
5004 base_face = base_face->ascii_face; \
5005 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5006 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5007 /* At first, fill in `char2b' and `faces'. */ \
5008 for (n = 0; n < glyph_len; n++) \
5010 int c = COMPOSITION_GLYPH (cmp, n); \
5011 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5012 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5013 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5014 this_face_id, char2b + n, 1, 1); \
5017 /* Make glyph_strings for each glyph sequence that is drawable by \
5018 the same face, and append them to HEAD/TAIL. */ \
5019 for (n = 0; n < cmp->glyph_len;) \
5021 s = (struct glyph_string *) alloca (sizeof *s); \
5022 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5023 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5024 s->cmp = cmp; \
5025 s->gidx = n; \
5026 s->x = (X); \
5028 if (n == 0) \
5029 first_s = s; \
5031 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5034 ++START; \
5035 s = first_s; \
5036 } while (0)
5039 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5040 of AREA of glyph row ROW on window W between indices START and END.
5041 HL overrides the face for drawing glyph strings, e.g. it is
5042 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5043 x-positions of the drawing area.
5045 This is an ugly monster macro construct because we must use alloca
5046 to allocate glyph strings (because x_draw_glyphs can be called
5047 asynchronously). */
5049 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5050 do \
5052 HEAD = TAIL = NULL; \
5053 while (START < END) \
5055 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5056 switch (first_glyph->type) \
5058 case CHAR_GLYPH: \
5059 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5060 TAIL, HL, X, LAST_X, \
5061 OVERLAPS_P); \
5062 break; \
5064 case COMPOSITE_GLYPH: \
5065 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5066 HEAD, TAIL, HL, X, LAST_X,\
5067 OVERLAPS_P); \
5068 break; \
5070 case STRETCH_GLYPH: \
5071 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5072 HEAD, TAIL, HL, X, LAST_X); \
5073 break; \
5075 case IMAGE_GLYPH: \
5076 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5077 TAIL, HL, X, LAST_X); \
5078 break; \
5080 default: \
5081 abort (); \
5084 x_set_glyph_string_background_width (s, START, LAST_X); \
5085 (X) += s->width; \
5088 while (0)
5091 /* Draw glyphs between START and END in AREA of ROW on window W,
5092 starting at x-position X. X is relative to AREA in W. HL is a
5093 face-override with the following meaning:
5095 DRAW_NORMAL_TEXT draw normally
5096 DRAW_CURSOR draw in cursor face
5097 DRAW_MOUSE_FACE draw in mouse face.
5098 DRAW_INVERSE_VIDEO draw in mode line face
5099 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5100 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5102 If OVERLAPS_P is non-zero, draw only the foreground of characters
5103 and clip to the physical height of ROW.
5105 Value is the x-position reached, relative to AREA of W. */
5107 static int
5108 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5109 struct window *w;
5110 int x;
5111 struct glyph_row *row;
5112 enum glyph_row_area area;
5113 int start, end;
5114 enum draw_glyphs_face hl;
5115 int overlaps_p;
5117 struct glyph_string *head, *tail;
5118 struct glyph_string *s;
5119 int last_x, area_width;
5120 int x_reached;
5121 int i, j;
5123 /* Let's rather be paranoid than getting a SEGV. */
5124 end = min (end, row->used[area]);
5125 start = max (0, start);
5126 start = min (end, start);
5128 /* Translate X to frame coordinates. Set last_x to the right
5129 end of the drawing area. */
5130 if (row->full_width_p)
5132 /* X is relative to the left edge of W, without scroll bars
5133 or fringes. */
5134 struct frame *f = XFRAME (w->frame);
5135 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5137 x += window_left_x;
5138 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5139 last_x = window_left_x + area_width;
5141 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5143 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5144 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5145 last_x += width;
5146 else
5147 x -= width;
5150 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5151 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5153 else
5155 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5156 area_width = window_box_width (w, area);
5157 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5160 /* Build a doubly-linked list of glyph_string structures between
5161 head and tail from what we have to draw. Note that the macro
5162 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5163 the reason we use a separate variable `i'. */
5164 i = start;
5165 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5166 overlaps_p);
5167 if (tail)
5168 x_reached = tail->x + tail->background_width;
5169 else
5170 x_reached = x;
5172 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5173 the row, redraw some glyphs in front or following the glyph
5174 strings built above. */
5175 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5177 int dummy_x = 0;
5178 struct glyph_string *h, *t;
5180 /* Compute overhangs for all glyph strings. */
5181 for (s = head; s; s = s->next)
5182 x_compute_glyph_string_overhangs (s);
5184 /* Prepend glyph strings for glyphs in front of the first glyph
5185 string that are overwritten because of the first glyph
5186 string's left overhang. The background of all strings
5187 prepended must be drawn because the first glyph string
5188 draws over it. */
5189 i = x_left_overwritten (head);
5190 if (i >= 0)
5192 j = i;
5193 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5194 DRAW_NORMAL_TEXT, dummy_x, last_x,
5195 overlaps_p);
5196 start = i;
5197 x_compute_overhangs_and_x (t, head->x, 1);
5198 x_prepend_glyph_string_lists (&head, &tail, h, t);
5201 /* Prepend glyph strings for glyphs in front of the first glyph
5202 string that overwrite that glyph string because of their
5203 right overhang. For these strings, only the foreground must
5204 be drawn, because it draws over the glyph string at `head'.
5205 The background must not be drawn because this would overwrite
5206 right overhangs of preceding glyphs for which no glyph
5207 strings exist. */
5208 i = x_left_overwriting (head);
5209 if (i >= 0)
5211 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5212 DRAW_NORMAL_TEXT, dummy_x, last_x,
5213 overlaps_p);
5214 for (s = h; s; s = s->next)
5215 s->background_filled_p = 1;
5216 x_compute_overhangs_and_x (t, head->x, 1);
5217 x_prepend_glyph_string_lists (&head, &tail, h, t);
5220 /* Append glyphs strings for glyphs following the last glyph
5221 string tail that are overwritten by tail. The background of
5222 these strings has to be drawn because tail's foreground draws
5223 over it. */
5224 i = x_right_overwritten (tail);
5225 if (i >= 0)
5227 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5228 DRAW_NORMAL_TEXT, x, last_x,
5229 overlaps_p);
5230 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5231 x_append_glyph_string_lists (&head, &tail, h, t);
5234 /* Append glyph strings for glyphs following the last glyph
5235 string tail that overwrite tail. The foreground of such
5236 glyphs has to be drawn because it writes into the background
5237 of tail. The background must not be drawn because it could
5238 paint over the foreground of following glyphs. */
5239 i = x_right_overwriting (tail);
5240 if (i >= 0)
5242 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5243 DRAW_NORMAL_TEXT, x, last_x,
5244 overlaps_p);
5245 for (s = h; s; s = s->next)
5246 s->background_filled_p = 1;
5247 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5248 x_append_glyph_string_lists (&head, &tail, h, t);
5252 /* Draw all strings. */
5253 for (s = head; s; s = s->next)
5254 x_draw_glyph_string (s);
5256 if (area == TEXT_AREA
5257 && !row->full_width_p
5258 /* When drawing overlapping rows, only the glyph strings'
5259 foreground is drawn, which doesn't erase a cursor
5260 completely. */
5261 && !overlaps_p)
5263 int x0 = head ? head->x : x;
5264 int x1 = tail ? tail->x + tail->background_width : x;
5266 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5267 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5269 if (XFASTINT (w->left_margin_width) != 0)
5271 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5272 x0 -= left_area_width;
5273 x1 -= left_area_width;
5276 notice_overwritten_cursor (w, area, x0, x1,
5277 row->y, MATRIX_ROW_BOTTOM_Y (row));
5280 /* Value is the x-position up to which drawn, relative to AREA of W.
5281 This doesn't include parts drawn because of overhangs. */
5282 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5283 if (!row->full_width_p)
5285 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5286 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5287 if (area > TEXT_AREA)
5288 x_reached -= window_box_width (w, TEXT_AREA);
5291 return x_reached;
5295 /* Fix the display of area AREA of overlapping row ROW in window W. */
5297 static void
5298 x_fix_overlapping_area (w, row, area)
5299 struct window *w;
5300 struct glyph_row *row;
5301 enum glyph_row_area area;
5303 int i, x;
5305 BLOCK_INPUT;
5307 if (area == LEFT_MARGIN_AREA)
5308 x = 0;
5309 else if (area == TEXT_AREA)
5310 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5311 else
5312 x = (window_box_width (w, LEFT_MARGIN_AREA)
5313 + window_box_width (w, TEXT_AREA));
5315 for (i = 0; i < row->used[area];)
5317 if (row->glyphs[area][i].overlaps_vertically_p)
5319 int start = i, start_x = x;
5323 x += row->glyphs[area][i].pixel_width;
5324 ++i;
5326 while (i < row->used[area]
5327 && row->glyphs[area][i].overlaps_vertically_p);
5329 x_draw_glyphs (w, start_x, row, area, start, i,
5330 DRAW_NORMAL_TEXT, 1);
5332 else
5334 x += row->glyphs[area][i].pixel_width;
5335 ++i;
5339 UNBLOCK_INPUT;
5343 /* Output LEN glyphs starting at START at the nominal cursor position.
5344 Advance the nominal cursor over the text. The global variable
5345 updated_window contains the window being updated, updated_row is
5346 the glyph row being updated, and updated_area is the area of that
5347 row being updated. */
5349 static void
5350 x_write_glyphs (start, len)
5351 struct glyph *start;
5352 int len;
5354 int x, hpos;
5356 xassert (updated_window && updated_row);
5357 BLOCK_INPUT;
5359 /* Write glyphs. */
5361 hpos = start - updated_row->glyphs[updated_area];
5362 x = x_draw_glyphs (updated_window, output_cursor.x,
5363 updated_row, updated_area,
5364 hpos, hpos + len,
5365 DRAW_NORMAL_TEXT, 0);
5367 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
5368 if (updated_area == TEXT_AREA
5369 && updated_window->phys_cursor_on_p
5370 && updated_window->phys_cursor.vpos == output_cursor.vpos
5371 && updated_window->phys_cursor.hpos >= hpos
5372 && updated_window->phys_cursor.hpos < hpos + len)
5373 updated_window->phys_cursor_on_p = 0;
5375 UNBLOCK_INPUT;
5377 /* Advance the output cursor. */
5378 output_cursor.hpos += len;
5379 output_cursor.x = x;
5383 /* Insert LEN glyphs from START at the nominal cursor position. */
5385 static void
5386 x_insert_glyphs (start, len)
5387 struct glyph *start;
5388 register int len;
5390 struct frame *f;
5391 struct window *w;
5392 int line_height, shift_by_width, shifted_region_width;
5393 struct glyph_row *row;
5394 struct glyph *glyph;
5395 int frame_x, frame_y, hpos;
5397 xassert (updated_window && updated_row);
5398 BLOCK_INPUT;
5399 w = updated_window;
5400 f = XFRAME (WINDOW_FRAME (w));
5402 /* Get the height of the line we are in. */
5403 row = updated_row;
5404 line_height = row->height;
5406 /* Get the width of the glyphs to insert. */
5407 shift_by_width = 0;
5408 for (glyph = start; glyph < start + len; ++glyph)
5409 shift_by_width += glyph->pixel_width;
5411 /* Get the width of the region to shift right. */
5412 shifted_region_width = (window_box_width (w, updated_area)
5413 - output_cursor.x
5414 - shift_by_width);
5416 /* Shift right. */
5417 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5418 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5419 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5420 f->output_data.x->normal_gc,
5421 frame_x, frame_y,
5422 shifted_region_width, line_height,
5423 frame_x + shift_by_width, frame_y);
5425 /* Write the glyphs. */
5426 hpos = start - row->glyphs[updated_area];
5427 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5428 DRAW_NORMAL_TEXT, 0);
5430 /* Advance the output cursor. */
5431 output_cursor.hpos += len;
5432 output_cursor.x += shift_by_width;
5433 UNBLOCK_INPUT;
5437 /* Delete N glyphs at the nominal cursor position. Not implemented
5438 for X frames. */
5440 static void
5441 x_delete_glyphs (n)
5442 register int n;
5444 abort ();
5448 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5449 If they are <= 0, this is probably an error. */
5451 void
5452 x_clear_area (dpy, window, x, y, width, height, exposures)
5453 Display *dpy;
5454 Window window;
5455 int x, y;
5456 int width, height;
5457 int exposures;
5459 xassert (width > 0 && height > 0);
5460 XClearArea (dpy, window, x, y, width, height, exposures);
5464 /* Erase the current text line from the nominal cursor position
5465 (inclusive) to pixel column TO_X (exclusive). The idea is that
5466 everything from TO_X onward is already erased.
5468 TO_X is a pixel position relative to updated_area of
5469 updated_window. TO_X == -1 means clear to the end of this area. */
5471 static void
5472 x_clear_end_of_line (to_x)
5473 int to_x;
5475 struct frame *f;
5476 struct window *w = updated_window;
5477 int max_x, min_y, max_y;
5478 int from_x, from_y, to_y;
5480 xassert (updated_window && updated_row);
5481 f = XFRAME (w->frame);
5483 if (updated_row->full_width_p)
5485 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5486 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5487 && !w->pseudo_window_p)
5488 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5490 else
5491 max_x = window_box_width (w, updated_area);
5492 max_y = window_text_bottom_y (w);
5494 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5495 of window. For TO_X > 0, truncate to end of drawing area. */
5496 if (to_x == 0)
5497 return;
5498 else if (to_x < 0)
5499 to_x = max_x;
5500 else
5501 to_x = min (to_x, max_x);
5503 to_y = min (max_y, output_cursor.y + updated_row->height);
5505 /* Notice if the cursor will be cleared by this operation. */
5506 if (!updated_row->full_width_p)
5507 notice_overwritten_cursor (w, updated_area,
5508 output_cursor.x, -1,
5509 updated_row->y,
5510 MATRIX_ROW_BOTTOM_Y (updated_row));
5512 from_x = output_cursor.x;
5514 /* Translate to frame coordinates. */
5515 if (updated_row->full_width_p)
5517 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5518 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5520 else
5522 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5523 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5526 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5527 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5528 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5530 /* Prevent inadvertently clearing to end of the X window. */
5531 if (to_x > from_x && to_y > from_y)
5533 BLOCK_INPUT;
5534 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5535 from_x, from_y, to_x - from_x, to_y - from_y,
5536 False);
5537 UNBLOCK_INPUT;
5542 /* Clear entire frame. If updating_frame is non-null, clear that
5543 frame. Otherwise clear the selected frame. */
5545 static void
5546 x_clear_frame ()
5548 struct frame *f;
5550 if (updating_frame)
5551 f = updating_frame;
5552 else
5553 f = SELECTED_FRAME ();
5555 /* Clearing the frame will erase any cursor, so mark them all as no
5556 longer visible. */
5557 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5558 output_cursor.hpos = output_cursor.vpos = 0;
5559 output_cursor.x = -1;
5561 /* We don't set the output cursor here because there will always
5562 follow an explicit cursor_to. */
5563 BLOCK_INPUT;
5564 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5566 /* We have to clear the scroll bars, too. If we have changed
5567 colors or something like that, then they should be notified. */
5568 x_scroll_bar_clear (f);
5570 XFlush (FRAME_X_DISPLAY (f));
5571 UNBLOCK_INPUT;
5576 /* Invert the middle quarter of the frame for .15 sec. */
5578 /* We use the select system call to do the waiting, so we have to make
5579 sure it's available. If it isn't, we just won't do visual bells. */
5581 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5584 /* Subtract the `struct timeval' values X and Y, storing the result in
5585 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5587 static int
5588 timeval_subtract (result, x, y)
5589 struct timeval *result, x, y;
5591 /* Perform the carry for the later subtraction by updating y. This
5592 is safer because on some systems the tv_sec member is unsigned. */
5593 if (x.tv_usec < y.tv_usec)
5595 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5596 y.tv_usec -= 1000000 * nsec;
5597 y.tv_sec += nsec;
5600 if (x.tv_usec - y.tv_usec > 1000000)
5602 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5603 y.tv_usec += 1000000 * nsec;
5604 y.tv_sec -= nsec;
5607 /* Compute the time remaining to wait. tv_usec is certainly
5608 positive. */
5609 result->tv_sec = x.tv_sec - y.tv_sec;
5610 result->tv_usec = x.tv_usec - y.tv_usec;
5612 /* Return indication of whether the result should be considered
5613 negative. */
5614 return x.tv_sec < y.tv_sec;
5617 void
5618 XTflash (f)
5619 struct frame *f;
5621 BLOCK_INPUT;
5624 GC gc;
5626 /* Create a GC that will use the GXxor function to flip foreground
5627 pixels into background pixels. */
5629 XGCValues values;
5631 values.function = GXxor;
5632 values.foreground = (f->output_data.x->foreground_pixel
5633 ^ f->output_data.x->background_pixel);
5635 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5636 GCFunction | GCForeground, &values);
5640 /* Get the height not including a menu bar widget. */
5641 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5642 /* Height of each line to flash. */
5643 int flash_height = FRAME_LINE_HEIGHT (f);
5644 /* These will be the left and right margins of the rectangles. */
5645 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5646 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5648 int width;
5650 /* Don't flash the area between a scroll bar and the frame
5651 edge it is next to. */
5652 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5654 case vertical_scroll_bar_left:
5655 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5656 break;
5658 case vertical_scroll_bar_right:
5659 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5660 break;
5662 default:
5663 break;
5666 width = flash_right - flash_left;
5668 /* If window is tall, flash top and bottom line. */
5669 if (height > 3 * FRAME_LINE_HEIGHT (f))
5671 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5672 flash_left,
5673 (FRAME_INTERNAL_BORDER_WIDTH (f)
5674 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5675 width, flash_height);
5676 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5677 flash_left,
5678 (height - flash_height
5679 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5680 width, flash_height);
5682 else
5683 /* If it is short, flash it all. */
5684 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5685 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5686 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5688 x_flush (f);
5691 struct timeval wakeup;
5693 EMACS_GET_TIME (wakeup);
5695 /* Compute time to wait until, propagating carry from usecs. */
5696 wakeup.tv_usec += 150000;
5697 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5698 wakeup.tv_usec %= 1000000;
5700 /* Keep waiting until past the time wakeup or any input gets
5701 available. */
5702 while (! detect_input_pending ())
5704 struct timeval current;
5705 struct timeval timeout;
5707 EMACS_GET_TIME (current);
5709 /* Break if result would be negative. */
5710 if (timeval_subtract (&current, wakeup, current))
5711 break;
5713 /* How long `select' should wait. */
5714 timeout.tv_sec = 0;
5715 timeout.tv_usec = 10000;
5717 /* Try to wait that long--but we might wake up sooner. */
5718 select (0, NULL, NULL, NULL, &timeout);
5722 /* If window is tall, flash top and bottom line. */
5723 if (height > 3 * FRAME_LINE_HEIGHT (f))
5725 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5726 flash_left,
5727 (FRAME_INTERNAL_BORDER_WIDTH (f)
5728 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5729 width, flash_height);
5730 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5731 flash_left,
5732 (height - flash_height
5733 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5734 width, flash_height);
5736 else
5737 /* If it is short, flash it all. */
5738 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5739 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5740 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5742 XFreeGC (FRAME_X_DISPLAY (f), gc);
5743 x_flush (f);
5747 UNBLOCK_INPUT;
5750 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5753 /* Make audible bell. */
5755 void
5756 XTring_bell ()
5758 struct frame *f = SELECTED_FRAME ();
5760 if (FRAME_X_DISPLAY (f))
5762 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5763 if (visible_bell)
5764 XTflash (f);
5765 else
5766 #endif
5768 BLOCK_INPUT;
5769 XBell (FRAME_X_DISPLAY (f), 0);
5770 XFlush (FRAME_X_DISPLAY (f));
5771 UNBLOCK_INPUT;
5777 /* Specify how many text lines, from the top of the window,
5778 should be affected by insert-lines and delete-lines operations.
5779 This, and those operations, are used only within an update
5780 that is bounded by calls to x_update_begin and x_update_end. */
5782 static void
5783 XTset_terminal_window (n)
5784 register int n;
5786 /* This function intentionally left blank. */
5791 /***********************************************************************
5792 Line Dance
5793 ***********************************************************************/
5795 /* Perform an insert-lines or delete-lines operation, inserting N
5796 lines or deleting -N lines at vertical position VPOS. */
5798 static void
5799 x_ins_del_lines (vpos, n)
5800 int vpos, n;
5802 abort ();
5806 /* Scroll part of the display as described by RUN. */
5808 static void
5809 x_scroll_run (w, run)
5810 struct window *w;
5811 struct run *run;
5813 struct frame *f = XFRAME (w->frame);
5814 int x, y, width, height, from_y, to_y, bottom_y;
5816 /* Get frame-relative bounding box of the text display area of W,
5817 without mode lines. Include in this box the left and right
5818 fringe of W. */
5819 window_box (w, -1, &x, &y, &width, &height);
5820 width += FRAME_X_FRINGE_WIDTH (f);
5821 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5823 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5824 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5825 bottom_y = y + height;
5827 if (to_y < from_y)
5829 /* Scrolling up. Make sure we don't copy part of the mode
5830 line at the bottom. */
5831 if (from_y + run->height > bottom_y)
5832 height = bottom_y - from_y;
5833 else
5834 height = run->height;
5836 else
5838 /* Scolling down. Make sure we don't copy over the mode line.
5839 at the bottom. */
5840 if (to_y + run->height > bottom_y)
5841 height = bottom_y - to_y;
5842 else
5843 height = run->height;
5846 BLOCK_INPUT;
5848 /* Cursor off. Will be switched on again in x_update_window_end. */
5849 updated_window = w;
5850 x_clear_cursor (w);
5852 XCopyArea (FRAME_X_DISPLAY (f),
5853 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5854 f->output_data.x->normal_gc,
5855 x, from_y,
5856 width, height,
5857 x, to_y);
5859 UNBLOCK_INPUT;
5864 /***********************************************************************
5865 Exposure Events
5866 ***********************************************************************/
5868 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5869 corner of the exposed rectangle. W and H are width and height of
5870 the exposed area. All are pixel values. W or H zero means redraw
5871 the entire frame. */
5873 static void
5874 expose_frame (f, x, y, w, h)
5875 struct frame *f;
5876 int x, y, w, h;
5878 XRectangle r;
5879 int mouse_face_overwritten_p = 0;
5881 TRACE ((stderr, "expose_frame "));
5883 /* No need to redraw if frame will be redrawn soon. */
5884 if (FRAME_GARBAGED_P (f))
5886 TRACE ((stderr, " garbaged\n"));
5887 return;
5890 /* If basic faces haven't been realized yet, there is no point in
5891 trying to redraw anything. This can happen when we get an expose
5892 event while Emacs is starting, e.g. by moving another window. */
5893 if (FRAME_FACE_CACHE (f) == NULL
5894 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5896 TRACE ((stderr, " no faces\n"));
5897 return;
5900 if (w == 0 || h == 0)
5902 r.x = r.y = 0;
5903 r.width = CANON_X_UNIT (f) * f->width;
5904 r.height = CANON_Y_UNIT (f) * f->height;
5906 else
5908 r.x = x;
5909 r.y = y;
5910 r.width = w;
5911 r.height = h;
5914 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5915 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5917 if (WINDOWP (f->tool_bar_window))
5918 mouse_face_overwritten_p
5919 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5921 #ifndef USE_X_TOOLKIT
5922 if (WINDOWP (f->menu_bar_window))
5923 mouse_face_overwritten_p
5924 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5925 #endif /* not USE_X_TOOLKIT */
5927 /* Some window managers support a focus-follows-mouse style with
5928 delayed raising of frames. Imagine a partially obscured frame,
5929 and moving the mouse into partially obscured mouse-face on that
5930 frame. The visible part of the mouse-face will be highlighted,
5931 then the WM raises the obscured frame. With at least one WM, KDE
5932 2.1, Emacs is not getting any event for the raising of the frame
5933 (even tried with SubstructureRedirectMask), only Expose events.
5934 These expose events will draw text normally, i.e. not
5935 highlighted. Which means we must redo the highlight here.
5936 Subsume it under ``we love X''. --gerd 2001-08-15 */
5937 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5939 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5940 if (f == dpyinfo->mouse_face_mouse_frame)
5942 int x = dpyinfo->mouse_face_mouse_x;
5943 int y = dpyinfo->mouse_face_mouse_y;
5944 clear_mouse_face (dpyinfo);
5945 note_mouse_highlight (f, x, y);
5951 /* Redraw (parts) of all windows in the window tree rooted at W that
5952 intersect R. R contains frame pixel coordinates. Value is
5953 non-zero if the exposure overwrites mouse-face. */
5955 static int
5956 expose_window_tree (w, r)
5957 struct window *w;
5958 XRectangle *r;
5960 struct frame *f = XFRAME (w->frame);
5961 int mouse_face_overwritten_p = 0;
5963 while (w && !FRAME_GARBAGED_P (f))
5965 if (!NILP (w->hchild))
5966 mouse_face_overwritten_p
5967 |= expose_window_tree (XWINDOW (w->hchild), r);
5968 else if (!NILP (w->vchild))
5969 mouse_face_overwritten_p
5970 |= expose_window_tree (XWINDOW (w->vchild), r);
5971 else
5972 mouse_face_overwritten_p |= expose_window (w, r);
5974 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5977 return mouse_face_overwritten_p;
5981 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5982 which intersects rectangle R. R is in window-relative coordinates. */
5984 static void
5985 expose_area (w, row, r, area)
5986 struct window *w;
5987 struct glyph_row *row;
5988 XRectangle *r;
5989 enum glyph_row_area area;
5991 struct glyph *first = row->glyphs[area];
5992 struct glyph *end = row->glyphs[area] + row->used[area];
5993 struct glyph *last;
5994 int first_x, start_x, x;
5996 if (area == TEXT_AREA && row->fill_line_p)
5997 /* If row extends face to end of line write the whole line. */
5998 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5999 DRAW_NORMAL_TEXT, 0);
6000 else
6002 /* Set START_X to the window-relative start position for drawing glyphs of
6003 AREA. The first glyph of the text area can be partially visible.
6004 The first glyphs of other areas cannot. */
6005 if (area == LEFT_MARGIN_AREA)
6006 start_x = 0;
6007 else if (area == TEXT_AREA)
6008 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6009 else
6010 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6011 + window_box_width (w, TEXT_AREA));
6012 x = start_x;
6014 /* Find the first glyph that must be redrawn. */
6015 while (first < end
6016 && x + first->pixel_width < r->x)
6018 x += first->pixel_width;
6019 ++first;
6022 /* Find the last one. */
6023 last = first;
6024 first_x = x;
6025 while (last < end
6026 && x < r->x + r->width)
6028 x += last->pixel_width;
6029 ++last;
6032 /* Repaint. */
6033 if (last > first)
6034 x_draw_glyphs (w, first_x - start_x, row, area,
6035 first - row->glyphs[area],
6036 last - row->glyphs[area],
6037 DRAW_NORMAL_TEXT, 0);
6042 /* Redraw the parts of the glyph row ROW on window W intersecting
6043 rectangle R. R is in window-relative coordinates. Value is
6044 non-zero if mouse-face was overwritten. */
6046 static int
6047 expose_line (w, row, r)
6048 struct window *w;
6049 struct glyph_row *row;
6050 XRectangle *r;
6052 xassert (row->enabled_p);
6054 if (row->mode_line_p || w->pseudo_window_p)
6055 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6056 DRAW_NORMAL_TEXT, 0);
6057 else
6059 if (row->used[LEFT_MARGIN_AREA])
6060 expose_area (w, row, r, LEFT_MARGIN_AREA);
6061 if (row->used[TEXT_AREA])
6062 expose_area (w, row, r, TEXT_AREA);
6063 if (row->used[RIGHT_MARGIN_AREA])
6064 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6065 x_draw_row_fringe_bitmaps (w, row);
6068 return row->mouse_face_p;
6072 /* Return non-zero if W's cursor intersects rectangle R. */
6074 static int
6075 x_phys_cursor_in_rect_p (w, r)
6076 struct window *w;
6077 XRectangle *r;
6079 XRectangle cr, result;
6080 struct glyph *cursor_glyph;
6082 cursor_glyph = get_phys_cursor_glyph (w);
6083 if (cursor_glyph)
6085 cr.x = w->phys_cursor.x;
6086 cr.y = w->phys_cursor.y;
6087 cr.width = cursor_glyph->pixel_width;
6088 cr.height = w->phys_cursor_height;
6089 return x_intersect_rectangles (&cr, r, &result);
6091 else
6092 return 0;
6096 /* Redraw those parts of glyphs rows during expose event handling that
6097 overlap other rows. Redrawing of an exposed line writes over parts
6098 of lines overlapping that exposed line; this function fixes that.
6100 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6101 row in W's current matrix that is exposed and overlaps other rows.
6102 LAST_OVERLAPPING_ROW is the last such row. */
6104 static void
6105 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6106 struct window *w;
6107 struct glyph_row *first_overlapping_row;
6108 struct glyph_row *last_overlapping_row;
6110 struct glyph_row *row;
6112 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6113 if (row->overlapping_p)
6115 xassert (row->enabled_p && !row->mode_line_p);
6117 if (row->used[LEFT_MARGIN_AREA])
6118 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6120 if (row->used[TEXT_AREA])
6121 x_fix_overlapping_area (w, row, TEXT_AREA);
6123 if (row->used[RIGHT_MARGIN_AREA])
6124 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6129 /* Redraw the part of window W intersection rectangle FR. Pixel
6130 coordinates in FR are frame-relative. Call this function with
6131 input blocked. Value is non-zero if the exposure overwrites
6132 mouse-face. */
6134 static int
6135 expose_window (w, fr)
6136 struct window *w;
6137 XRectangle *fr;
6139 struct frame *f = XFRAME (w->frame);
6140 XRectangle wr, r;
6141 int mouse_face_overwritten_p = 0;
6143 /* If window is not yet fully initialized, do nothing. This can
6144 happen when toolkit scroll bars are used and a window is split.
6145 Reconfiguring the scroll bar will generate an expose for a newly
6146 created window. */
6147 if (w->current_matrix == NULL)
6148 return 0;
6150 /* When we're currently updating the window, display and current
6151 matrix usually don't agree. Arrange for a thorough display
6152 later. */
6153 if (w == updated_window)
6155 SET_FRAME_GARBAGED (f);
6156 return 0;
6159 /* Frame-relative pixel rectangle of W. */
6160 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6161 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6162 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6163 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6165 if (x_intersect_rectangles (fr, &wr, &r))
6167 int yb = window_text_bottom_y (w);
6168 struct glyph_row *row;
6169 int cursor_cleared_p;
6170 struct glyph_row *first_overlapping_row, *last_overlapping_row;
6172 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6173 r.x, r.y, r.width, r.height));
6175 /* Convert to window coordinates. */
6176 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6177 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6179 /* Turn off the cursor. */
6180 if (!w->pseudo_window_p
6181 && x_phys_cursor_in_rect_p (w, &r))
6183 x_clear_cursor (w);
6184 cursor_cleared_p = 1;
6186 else
6187 cursor_cleared_p = 0;
6189 /* Update lines intersecting rectangle R. */
6190 first_overlapping_row = last_overlapping_row = NULL;
6191 for (row = w->current_matrix->rows;
6192 row->enabled_p;
6193 ++row)
6195 int y0 = row->y;
6196 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6198 if ((y0 >= r.y && y0 < r.y + r.height)
6199 || (y1 > r.y && y1 < r.y + r.height)
6200 || (r.y >= y0 && r.y < y1)
6201 || (r.y + r.height > y0 && r.y + r.height < y1))
6203 if (row->overlapping_p)
6205 if (first_overlapping_row == NULL)
6206 first_overlapping_row = row;
6207 last_overlapping_row = row;
6210 if (expose_line (w, row, &r))
6211 mouse_face_overwritten_p = 1;
6214 if (y1 >= yb)
6215 break;
6218 /* Display the mode line if there is one. */
6219 if (WINDOW_WANTS_MODELINE_P (w)
6220 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6221 row->enabled_p)
6222 && row->y < r.y + r.height)
6224 if (expose_line (w, row, &r))
6225 mouse_face_overwritten_p = 1;
6228 if (!w->pseudo_window_p)
6230 /* Fix the display of overlapping rows. */
6231 if (first_overlapping_row)
6232 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
6234 /* Draw border between windows. */
6235 x_draw_vertical_border (w);
6237 /* Turn the cursor on again. */
6238 if (cursor_cleared_p)
6239 x_update_window_cursor (w, 1);
6243 return mouse_face_overwritten_p;
6247 /* Determine the intersection of two rectangles R1 and R2. Return
6248 the intersection in *RESULT. Value is non-zero if RESULT is not
6249 empty. */
6251 static int
6252 x_intersect_rectangles (r1, r2, result)
6253 XRectangle *r1, *r2, *result;
6255 XRectangle *left, *right;
6256 XRectangle *upper, *lower;
6257 int intersection_p = 0;
6259 /* Rearrange so that R1 is the left-most rectangle. */
6260 if (r1->x < r2->x)
6261 left = r1, right = r2;
6262 else
6263 left = r2, right = r1;
6265 /* X0 of the intersection is right.x0, if this is inside R1,
6266 otherwise there is no intersection. */
6267 if (right->x <= left->x + left->width)
6269 result->x = right->x;
6271 /* The right end of the intersection is the minimum of the
6272 the right ends of left and right. */
6273 result->width = (min (left->x + left->width, right->x + right->width)
6274 - result->x);
6276 /* Same game for Y. */
6277 if (r1->y < r2->y)
6278 upper = r1, lower = r2;
6279 else
6280 upper = r2, lower = r1;
6282 /* The upper end of the intersection is lower.y0, if this is inside
6283 of upper. Otherwise, there is no intersection. */
6284 if (lower->y <= upper->y + upper->height)
6286 result->y = lower->y;
6288 /* The lower end of the intersection is the minimum of the lower
6289 ends of upper and lower. */
6290 result->height = (min (lower->y + lower->height,
6291 upper->y + upper->height)
6292 - result->y);
6293 intersection_p = 1;
6297 return intersection_p;
6304 static void
6305 frame_highlight (f)
6306 struct frame *f;
6308 /* We used to only do this if Vx_no_window_manager was non-nil, but
6309 the ICCCM (section 4.1.6) says that the window's border pixmap
6310 and border pixel are window attributes which are "private to the
6311 client", so we can always change it to whatever we want. */
6312 BLOCK_INPUT;
6313 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6314 f->output_data.x->border_pixel);
6315 UNBLOCK_INPUT;
6316 x_update_cursor (f, 1);
6319 static void
6320 frame_unhighlight (f)
6321 struct frame *f;
6323 /* We used to only do this if Vx_no_window_manager was non-nil, but
6324 the ICCCM (section 4.1.6) says that the window's border pixmap
6325 and border pixel are window attributes which are "private to the
6326 client", so we can always change it to whatever we want. */
6327 BLOCK_INPUT;
6328 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6329 f->output_data.x->border_tile);
6330 UNBLOCK_INPUT;
6331 x_update_cursor (f, 1);
6334 /* The focus has changed. Update the frames as necessary to reflect
6335 the new situation. Note that we can't change the selected frame
6336 here, because the Lisp code we are interrupting might become confused.
6337 Each event gets marked with the frame in which it occurred, so the
6338 Lisp code can tell when the switch took place by examining the events. */
6340 static void
6341 x_new_focus_frame (dpyinfo, frame)
6342 struct x_display_info *dpyinfo;
6343 struct frame *frame;
6345 struct frame *old_focus = dpyinfo->x_focus_frame;
6347 if (frame != dpyinfo->x_focus_frame)
6349 /* Set this before calling other routines, so that they see
6350 the correct value of x_focus_frame. */
6351 dpyinfo->x_focus_frame = frame;
6353 if (old_focus && old_focus->auto_lower)
6354 x_lower_frame (old_focus);
6356 #if 0
6357 selected_frame = frame;
6358 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6359 selected_frame);
6360 Fselect_window (selected_frame->selected_window);
6361 choose_minibuf_frame ();
6362 #endif /* ! 0 */
6364 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6365 pending_autoraise_frame = dpyinfo->x_focus_frame;
6366 else
6367 pending_autoraise_frame = 0;
6370 x_frame_rehighlight (dpyinfo);
6373 /* Handle FocusIn and FocusOut state changes for FRAME.
6374 If FRAME has focus and there exists more than one frame, puts
6375 a FOCUS_IN_EVENT into BUFP.
6376 Returns number of events inserted into BUFP. */
6378 static int
6379 x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
6380 int type;
6381 int state;
6382 struct x_display_info *dpyinfo;
6383 struct frame *frame;
6384 struct input_event *bufp;
6385 int numchars;
6387 int nr_events = 0;
6389 if (type == FocusIn)
6391 if (dpyinfo->x_focus_event_frame != frame)
6393 x_new_focus_frame (dpyinfo, frame);
6394 dpyinfo->x_focus_event_frame = frame;
6396 /* Don't stop displaying the initial startup message
6397 for a switch-frame event we don't need. */
6398 if (numchars > 0
6399 && GC_NILP (Vterminal_frame)
6400 && GC_CONSP (Vframe_list)
6401 && !GC_NILP (XCDR (Vframe_list)))
6403 bufp->kind = FOCUS_IN_EVENT;
6404 XSETFRAME (bufp->frame_or_window, frame);
6405 bufp->arg = Qnil;
6406 ++bufp;
6407 numchars--;
6408 ++nr_events;
6412 frame->output_data.x->focus_state |= state;
6414 #ifdef HAVE_X_I18N
6415 if (FRAME_XIC (frame))
6416 XSetICFocus (FRAME_XIC (frame));
6417 #endif
6419 else if (type == FocusOut)
6421 frame->output_data.x->focus_state &= ~state;
6423 if (dpyinfo->x_focus_event_frame == frame)
6425 dpyinfo->x_focus_event_frame = 0;
6426 x_new_focus_frame (dpyinfo, 0);
6429 #ifdef HAVE_X_I18N
6430 if (FRAME_XIC (frame))
6431 XUnsetICFocus (FRAME_XIC (frame));
6432 #endif
6435 return nr_events;
6438 /* The focus may have changed. Figure out if it is a real focus change,
6439 by checking both FocusIn/Out and Enter/LeaveNotify events.
6441 Returns number of events inserted into BUFP. */
6443 static int
6444 x_detect_focus_change (dpyinfo, event, bufp, numchars)
6445 struct x_display_info *dpyinfo;
6446 XEvent *event;
6447 struct input_event *bufp;
6448 int numchars;
6450 struct frame *frame;
6451 int nr_events = 0;
6453 frame = x_top_window_to_frame (dpyinfo, event->xany.window);
6454 if (! frame) return nr_events;
6456 switch (event->type)
6458 case EnterNotify:
6459 case LeaveNotify:
6460 if (event->xcrossing.detail != NotifyInferior
6461 && event->xcrossing.focus
6462 && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
6463 nr_events = x_focus_changed ((event->type == EnterNotify
6464 ? FocusIn : FocusOut),
6465 FOCUS_IMPLICIT,
6466 dpyinfo,
6467 frame,
6468 bufp,
6469 numchars);
6470 break;
6472 case FocusIn:
6473 case FocusOut:
6474 nr_events = x_focus_changed (event->type,
6475 (event->xfocus.detail == NotifyPointer
6476 ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
6477 dpyinfo,
6478 frame,
6479 bufp,
6480 numchars);
6481 break;
6484 return nr_events;
6488 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6490 void
6491 x_mouse_leave (dpyinfo)
6492 struct x_display_info *dpyinfo;
6494 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6497 /* The focus has changed, or we have redirected a frame's focus to
6498 another frame (this happens when a frame uses a surrogate
6499 mini-buffer frame). Shift the highlight as appropriate.
6501 The FRAME argument doesn't necessarily have anything to do with which
6502 frame is being highlighted or un-highlighted; we only use it to find
6503 the appropriate X display info. */
6505 static void
6506 XTframe_rehighlight (frame)
6507 struct frame *frame;
6509 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6512 static void
6513 x_frame_rehighlight (dpyinfo)
6514 struct x_display_info *dpyinfo;
6516 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6518 if (dpyinfo->x_focus_frame)
6520 dpyinfo->x_highlight_frame
6521 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6522 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6523 : dpyinfo->x_focus_frame);
6524 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6526 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6527 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6530 else
6531 dpyinfo->x_highlight_frame = 0;
6533 if (dpyinfo->x_highlight_frame != old_highlight)
6535 if (old_highlight)
6536 frame_unhighlight (old_highlight);
6537 if (dpyinfo->x_highlight_frame)
6538 frame_highlight (dpyinfo->x_highlight_frame);
6544 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6546 /* Initialize mode_switch_bit and modifier_meaning. */
6547 static void
6548 x_find_modifier_meanings (dpyinfo)
6549 struct x_display_info *dpyinfo;
6551 int min_code, max_code;
6552 KeySym *syms;
6553 int syms_per_code;
6554 XModifierKeymap *mods;
6556 dpyinfo->meta_mod_mask = 0;
6557 dpyinfo->shift_lock_mask = 0;
6558 dpyinfo->alt_mod_mask = 0;
6559 dpyinfo->super_mod_mask = 0;
6560 dpyinfo->hyper_mod_mask = 0;
6562 #ifdef HAVE_X11R4
6563 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6564 #else
6565 min_code = dpyinfo->display->min_keycode;
6566 max_code = dpyinfo->display->max_keycode;
6567 #endif
6569 syms = XGetKeyboardMapping (dpyinfo->display,
6570 min_code, max_code - min_code + 1,
6571 &syms_per_code);
6572 mods = XGetModifierMapping (dpyinfo->display);
6574 /* Scan the modifier table to see which modifier bits the Meta and
6575 Alt keysyms are on. */
6577 int row, col; /* The row and column in the modifier table. */
6579 for (row = 3; row < 8; row++)
6580 for (col = 0; col < mods->max_keypermod; col++)
6582 KeyCode code
6583 = mods->modifiermap[(row * mods->max_keypermod) + col];
6585 /* Zeroes are used for filler. Skip them. */
6586 if (code == 0)
6587 continue;
6589 /* Are any of this keycode's keysyms a meta key? */
6591 int code_col;
6593 for (code_col = 0; code_col < syms_per_code; code_col++)
6595 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6597 switch (sym)
6599 case XK_Meta_L:
6600 case XK_Meta_R:
6601 dpyinfo->meta_mod_mask |= (1 << row);
6602 break;
6604 case XK_Alt_L:
6605 case XK_Alt_R:
6606 dpyinfo->alt_mod_mask |= (1 << row);
6607 break;
6609 case XK_Hyper_L:
6610 case XK_Hyper_R:
6611 dpyinfo->hyper_mod_mask |= (1 << row);
6612 break;
6614 case XK_Super_L:
6615 case XK_Super_R:
6616 dpyinfo->super_mod_mask |= (1 << row);
6617 break;
6619 case XK_Shift_Lock:
6620 /* Ignore this if it's not on the lock modifier. */
6621 if ((1 << row) == LockMask)
6622 dpyinfo->shift_lock_mask = LockMask;
6623 break;
6630 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6631 if (! dpyinfo->meta_mod_mask)
6633 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6634 dpyinfo->alt_mod_mask = 0;
6637 /* If some keys are both alt and meta,
6638 make them just meta, not alt. */
6639 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6641 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6644 XFree ((char *) syms);
6645 XFreeModifiermap (mods);
6648 /* Convert between the modifier bits X uses and the modifier bits
6649 Emacs uses. */
6651 static unsigned int
6652 x_x_to_emacs_modifiers (dpyinfo, state)
6653 struct x_display_info *dpyinfo;
6654 unsigned int state;
6656 EMACS_UINT mod_meta = meta_modifier;
6657 EMACS_UINT mod_alt = alt_modifier;
6658 EMACS_UINT mod_hyper = hyper_modifier;
6659 EMACS_UINT mod_super = super_modifier;
6660 Lisp_Object tem;
6662 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6663 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6664 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6665 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6666 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6667 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6668 tem = Fget (Vx_super_keysym, Qmodifier_value);
6669 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6672 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6673 | ((state & ControlMask) ? ctrl_modifier : 0)
6674 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
6675 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
6676 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
6677 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
6680 static unsigned int
6681 x_emacs_to_x_modifiers (dpyinfo, state)
6682 struct x_display_info *dpyinfo;
6683 unsigned int state;
6685 EMACS_UINT mod_meta = meta_modifier;
6686 EMACS_UINT mod_alt = alt_modifier;
6687 EMACS_UINT mod_hyper = hyper_modifier;
6688 EMACS_UINT mod_super = super_modifier;
6690 Lisp_Object tem;
6692 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6693 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6694 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6695 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6696 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6697 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6698 tem = Fget (Vx_super_keysym, Qmodifier_value);
6699 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6702 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
6703 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
6704 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
6705 | ((state & shift_modifier) ? ShiftMask : 0)
6706 | ((state & ctrl_modifier) ? ControlMask : 0)
6707 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
6710 /* Convert a keysym to its name. */
6712 char *
6713 x_get_keysym_name (keysym)
6714 KeySym keysym;
6716 char *value;
6718 BLOCK_INPUT;
6719 value = XKeysymToString (keysym);
6720 UNBLOCK_INPUT;
6722 return value;
6727 /* Mouse clicks and mouse movement. Rah. */
6729 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6730 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6731 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6732 not force the value into range. */
6734 void
6735 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6736 FRAME_PTR f;
6737 register int pix_x, pix_y;
6738 register int *x, *y;
6739 XRectangle *bounds;
6740 int noclip;
6742 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6743 even for negative values. */
6744 if (pix_x < 0)
6745 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6746 if (pix_y < 0)
6747 pix_y -= (f)->output_data.x->line_height - 1;
6749 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6750 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6752 if (bounds)
6754 bounds->width = FONT_WIDTH (f->output_data.x->font);
6755 bounds->height = f->output_data.x->line_height;
6756 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6757 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6760 if (!noclip)
6762 if (pix_x < 0)
6763 pix_x = 0;
6764 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6765 pix_x = FRAME_WINDOW_WIDTH (f);
6767 if (pix_y < 0)
6768 pix_y = 0;
6769 else if (pix_y > f->height)
6770 pix_y = f->height;
6773 *x = pix_x;
6774 *y = pix_y;
6778 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6779 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6780 can't tell the positions because W's display is not up to date,
6781 return 0. */
6784 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6785 struct window *w;
6786 int hpos, vpos;
6787 int *frame_x, *frame_y;
6789 int success_p;
6791 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6792 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6794 if (display_completed)
6796 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6797 struct glyph *glyph = row->glyphs[TEXT_AREA];
6798 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6800 *frame_y = row->y;
6801 *frame_x = row->x;
6802 while (glyph < end)
6804 *frame_x += glyph->pixel_width;
6805 ++glyph;
6808 success_p = 1;
6810 else
6812 *frame_y = *frame_x = 0;
6813 success_p = 0;
6816 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6817 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6818 return success_p;
6822 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6824 If the event is a button press, then note that we have grabbed
6825 the mouse. */
6827 static Lisp_Object
6828 construct_mouse_click (result, event, f)
6829 struct input_event *result;
6830 XButtonEvent *event;
6831 struct frame *f;
6833 /* Make the event type NO_EVENT; we'll change that when we decide
6834 otherwise. */
6835 result->kind = MOUSE_CLICK_EVENT;
6836 result->code = event->button - Button1;
6837 result->timestamp = event->time;
6838 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6839 event->state)
6840 | (event->type == ButtonRelease
6841 ? up_modifier
6842 : down_modifier));
6844 XSETINT (result->x, event->x);
6845 XSETINT (result->y, event->y);
6846 XSETFRAME (result->frame_or_window, f);
6847 result->arg = Qnil;
6848 return Qnil;
6852 /* Function to report a mouse movement to the mainstream Emacs code.
6853 The input handler calls this.
6855 We have received a mouse movement event, which is given in *event.
6856 If the mouse is over a different glyph than it was last time, tell
6857 the mainstream emacs code by setting mouse_moved. If not, ask for
6858 another motion event, so we can check again the next time it moves. */
6860 static XMotionEvent last_mouse_motion_event;
6861 static Lisp_Object last_mouse_motion_frame;
6863 static void
6864 note_mouse_movement (frame, event)
6865 FRAME_PTR frame;
6866 XMotionEvent *event;
6868 last_mouse_movement_time = event->time;
6869 last_mouse_motion_event = *event;
6870 XSETFRAME (last_mouse_motion_frame, frame);
6872 if (event->window != FRAME_X_WINDOW (frame))
6874 frame->mouse_moved = 1;
6875 last_mouse_scroll_bar = Qnil;
6876 note_mouse_highlight (frame, -1, -1);
6879 /* Has the mouse moved off the glyph it was on at the last sighting? */
6880 else if (event->x < last_mouse_glyph.x
6881 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6882 || event->y < last_mouse_glyph.y
6883 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6885 frame->mouse_moved = 1;
6886 last_mouse_scroll_bar = Qnil;
6887 note_mouse_highlight (frame, event->x, event->y);
6892 /************************************************************************
6893 Mouse Face
6894 ************************************************************************/
6896 /* Find the glyph under window-relative coordinates X/Y in window W.
6897 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6898 strings. Return in *HPOS and *VPOS the row and column number of
6899 the glyph found. Return in *AREA the glyph area containing X.
6900 Value is a pointer to the glyph found or null if X/Y is not on
6901 text, or we can't tell because W's current matrix is not up to
6902 date. */
6904 static struct glyph *
6905 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6906 struct window *w;
6907 int x, y;
6908 int *hpos, *vpos, *area;
6909 int buffer_only_p;
6911 struct glyph *glyph, *end;
6912 struct glyph_row *row = NULL;
6913 int x0, i, left_area_width;
6915 /* Find row containing Y. Give up if some row is not enabled. */
6916 for (i = 0; i < w->current_matrix->nrows; ++i)
6918 row = MATRIX_ROW (w->current_matrix, i);
6919 if (!row->enabled_p)
6920 return NULL;
6921 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6922 break;
6925 *vpos = i;
6926 *hpos = 0;
6928 /* Give up if Y is not in the window. */
6929 if (i == w->current_matrix->nrows)
6930 return NULL;
6932 /* Get the glyph area containing X. */
6933 if (w->pseudo_window_p)
6935 *area = TEXT_AREA;
6936 x0 = 0;
6938 else
6940 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6941 if (x < left_area_width)
6943 *area = LEFT_MARGIN_AREA;
6944 x0 = 0;
6946 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6948 *area = TEXT_AREA;
6949 x0 = row->x + left_area_width;
6951 else
6953 *area = RIGHT_MARGIN_AREA;
6954 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6958 /* Find glyph containing X. */
6959 glyph = row->glyphs[*area];
6960 end = glyph + row->used[*area];
6961 while (glyph < end)
6963 if (x < x0 + glyph->pixel_width)
6965 if (w->pseudo_window_p)
6966 break;
6967 else if (!buffer_only_p || BUFFERP (glyph->object))
6968 break;
6971 x0 += glyph->pixel_width;
6972 ++glyph;
6975 if (glyph == end)
6976 return NULL;
6978 *hpos = glyph - row->glyphs[*area];
6979 return glyph;
6983 /* Convert frame-relative x/y to coordinates relative to window W.
6984 Takes pseudo-windows into account. */
6986 static void
6987 frame_to_window_pixel_xy (w, x, y)
6988 struct window *w;
6989 int *x, *y;
6991 if (w->pseudo_window_p)
6993 /* A pseudo-window is always full-width, and starts at the
6994 left edge of the frame, plus a frame border. */
6995 struct frame *f = XFRAME (w->frame);
6996 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6997 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6999 else
7001 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
7002 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7007 /* Take proper action when mouse has moved to the mode or header line
7008 or marginal area of window W, x-position X and y-position Y. Area
7009 is 1, 3, 6 or 7 for the mode line, header line, left and right
7010 marginal area respectively. X is relative to the start of the text
7011 display area of W, so the width of bitmap areas and scroll bars
7012 must be subtracted to get a position relative to the start of the
7013 mode line. */
7015 static void
7016 note_mode_line_or_margin_highlight (w, x, y, portion)
7017 struct window *w;
7018 int x, y, portion;
7020 struct frame *f = XFRAME (w->frame);
7021 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7022 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
7023 int charpos;
7024 Lisp_Object string, help, map, pos;
7026 if (portion == 1 || portion == 3)
7027 string = mode_line_string (w, x, y, portion == 1, &charpos);
7028 else
7029 string = marginal_area_string (w, x, y, portion, &charpos);
7031 if (STRINGP (string))
7033 pos = make_number (charpos);
7035 /* If we're on a string with `help-echo' text property, arrange
7036 for the help to be displayed. This is done by setting the
7037 global variable help_echo to the help string. */
7038 help = Fget_text_property (pos, Qhelp_echo, string);
7039 if (!NILP (help))
7041 help_echo = help;
7042 XSETWINDOW (help_echo_window, w);
7043 help_echo_object = string;
7044 help_echo_pos = charpos;
7047 /* Change the mouse pointer according to what is under X/Y. */
7048 map = Fget_text_property (pos, Qlocal_map, string);
7049 if (!KEYMAPP (map))
7050 map = Fget_text_property (pos, Qkeymap, string);
7051 if (KEYMAPP (map))
7052 cursor = f->output_data.x->nontext_cursor;
7055 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7059 /* Take proper action when the mouse has moved to position X, Y on
7060 frame F as regards highlighting characters that have mouse-face
7061 properties. Also de-highlighting chars where the mouse was before.
7062 X and Y can be negative or out of range. */
7064 static void
7065 note_mouse_highlight (f, x, y)
7066 struct frame *f;
7067 int x, y;
7069 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7070 int portion;
7071 Lisp_Object window;
7072 struct window *w;
7073 Cursor cursor = None;
7074 struct buffer *b;
7076 /* When a menu is active, don't highlight because this looks odd. */
7077 #ifdef USE_X_TOOLKIT
7078 if (popup_activated ())
7079 return;
7080 #endif
7082 if (NILP (Vmouse_highlight)
7083 || !f->glyphs_initialized_p)
7084 return;
7086 dpyinfo->mouse_face_mouse_x = x;
7087 dpyinfo->mouse_face_mouse_y = y;
7088 dpyinfo->mouse_face_mouse_frame = f;
7090 if (dpyinfo->mouse_face_defer)
7091 return;
7093 if (gc_in_progress)
7095 dpyinfo->mouse_face_deferred_gc = 1;
7096 return;
7099 /* Which window is that in? */
7100 window = window_from_coordinates (f, x, y, &portion, 1);
7102 /* If we were displaying active text in another window, clear that. */
7103 if (! EQ (window, dpyinfo->mouse_face_window))
7104 clear_mouse_face (dpyinfo);
7106 /* Not on a window -> return. */
7107 if (!WINDOWP (window))
7108 return;
7110 /* Convert to window-relative pixel coordinates. */
7111 w = XWINDOW (window);
7112 frame_to_window_pixel_xy (w, &x, &y);
7114 /* Handle tool-bar window differently since it doesn't display a
7115 buffer. */
7116 if (EQ (window, f->tool_bar_window))
7118 note_tool_bar_highlight (f, x, y);
7119 return;
7122 /* Mouse is on the mode, header line or margin? */
7123 if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
7125 note_mode_line_or_margin_highlight (w, x, y, portion);
7126 return;
7129 if (portion == 2)
7130 cursor = f->output_data.x->horizontal_drag_cursor;
7131 else
7132 cursor = f->output_data.x->text_cursor;
7134 /* Are we in a window whose display is up to date?
7135 And verify the buffer's text has not changed. */
7136 b = XBUFFER (w->buffer);
7137 if (/* Within text portion of the window. */
7138 portion == 0
7139 && EQ (w->window_end_valid, w->buffer)
7140 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7141 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7143 int hpos, vpos, pos, i, area;
7144 struct glyph *glyph;
7145 Lisp_Object object;
7146 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7147 Lisp_Object *overlay_vec = NULL;
7148 int len, noverlays;
7149 struct buffer *obuf;
7150 int obegv, ozv, same_region;
7152 /* Find the glyph under X/Y. */
7153 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7155 /* Clear mouse face if X/Y not over text. */
7156 if (glyph == NULL
7157 || area != TEXT_AREA
7158 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7160 if (clear_mouse_face (dpyinfo))
7161 cursor = None;
7162 goto set_cursor;
7165 pos = glyph->charpos;
7166 object = glyph->object;
7167 if (!STRINGP (object) && !BUFFERP (object))
7168 goto set_cursor;
7170 /* If we get an out-of-range value, return now; avoid an error. */
7171 if (BUFFERP (object) && pos > BUF_Z (b))
7172 goto set_cursor;
7174 /* Make the window's buffer temporarily current for
7175 overlays_at and compute_char_face. */
7176 obuf = current_buffer;
7177 current_buffer = b;
7178 obegv = BEGV;
7179 ozv = ZV;
7180 BEGV = BEG;
7181 ZV = Z;
7183 /* Is this char mouse-active or does it have help-echo? */
7184 position = make_number (pos);
7186 if (BUFFERP (object))
7188 /* Put all the overlays we want in a vector in overlay_vec.
7189 Store the length in len. If there are more than 10, make
7190 enough space for all, and try again. */
7191 len = 10;
7192 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7193 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7194 if (noverlays > len)
7196 len = noverlays;
7197 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7198 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7201 /* Sort overlays into increasing priority order. */
7202 noverlays = sort_overlays (overlay_vec, noverlays, w);
7204 else
7205 noverlays = 0;
7207 same_region = (EQ (window, dpyinfo->mouse_face_window)
7208 && vpos >= dpyinfo->mouse_face_beg_row
7209 && vpos <= dpyinfo->mouse_face_end_row
7210 && (vpos > dpyinfo->mouse_face_beg_row
7211 || hpos >= dpyinfo->mouse_face_beg_col)
7212 && (vpos < dpyinfo->mouse_face_end_row
7213 || hpos < dpyinfo->mouse_face_end_col
7214 || dpyinfo->mouse_face_past_end));
7216 if (same_region)
7217 cursor = None;
7219 /* Check mouse-face highlighting. */
7220 if (! same_region
7221 /* If there exists an overlay with mouse-face overlapping
7222 the one we are currently highlighting, we have to
7223 check if we enter the overlapping overlay, and then
7224 highlight only that. */
7225 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7226 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7228 /* Find the highest priority overlay that has a mouse-face
7229 property. */
7230 overlay = Qnil;
7231 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7233 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7234 if (!NILP (mouse_face))
7235 overlay = overlay_vec[i];
7238 /* If we're actually highlighting the same overlay as
7239 before, there's no need to do that again. */
7240 if (!NILP (overlay)
7241 && EQ (overlay, dpyinfo->mouse_face_overlay))
7242 goto check_help_echo;
7244 dpyinfo->mouse_face_overlay = overlay;
7246 /* Clear the display of the old active region, if any. */
7247 if (clear_mouse_face (dpyinfo))
7248 cursor = None;
7250 /* If no overlay applies, get a text property. */
7251 if (NILP (overlay))
7252 mouse_face = Fget_text_property (position, Qmouse_face, object);
7254 /* Handle the overlay case. */
7255 if (!NILP (overlay))
7257 /* Find the range of text around this char that
7258 should be active. */
7259 Lisp_Object before, after;
7260 int ignore;
7262 before = Foverlay_start (overlay);
7263 after = Foverlay_end (overlay);
7264 /* Record this as the current active region. */
7265 fast_find_position (w, XFASTINT (before),
7266 &dpyinfo->mouse_face_beg_col,
7267 &dpyinfo->mouse_face_beg_row,
7268 &dpyinfo->mouse_face_beg_x,
7269 &dpyinfo->mouse_face_beg_y, Qnil);
7271 dpyinfo->mouse_face_past_end
7272 = !fast_find_position (w, XFASTINT (after),
7273 &dpyinfo->mouse_face_end_col,
7274 &dpyinfo->mouse_face_end_row,
7275 &dpyinfo->mouse_face_end_x,
7276 &dpyinfo->mouse_face_end_y, Qnil);
7277 dpyinfo->mouse_face_window = window;
7278 dpyinfo->mouse_face_face_id
7279 = face_at_buffer_position (w, pos, 0, 0,
7280 &ignore, pos + 1,
7281 !dpyinfo->mouse_face_hidden);
7283 /* Display it as active. */
7284 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7285 cursor = None;
7287 /* Handle the text property case. */
7288 else if (!NILP (mouse_face) && BUFFERP (object))
7290 /* Find the range of text around this char that
7291 should be active. */
7292 Lisp_Object before, after, beginning, end;
7293 int ignore;
7295 beginning = Fmarker_position (w->start);
7296 end = make_number (BUF_Z (XBUFFER (object))
7297 - XFASTINT (w->window_end_pos));
7298 before
7299 = Fprevious_single_property_change (make_number (pos + 1),
7300 Qmouse_face,
7301 object, beginning);
7302 after
7303 = Fnext_single_property_change (position, Qmouse_face,
7304 object, end);
7306 /* Record this as the current active region. */
7307 fast_find_position (w, XFASTINT (before),
7308 &dpyinfo->mouse_face_beg_col,
7309 &dpyinfo->mouse_face_beg_row,
7310 &dpyinfo->mouse_face_beg_x,
7311 &dpyinfo->mouse_face_beg_y, Qnil);
7312 dpyinfo->mouse_face_past_end
7313 = !fast_find_position (w, XFASTINT (after),
7314 &dpyinfo->mouse_face_end_col,
7315 &dpyinfo->mouse_face_end_row,
7316 &dpyinfo->mouse_face_end_x,
7317 &dpyinfo->mouse_face_end_y, Qnil);
7318 dpyinfo->mouse_face_window = window;
7320 if (BUFFERP (object))
7321 dpyinfo->mouse_face_face_id
7322 = face_at_buffer_position (w, pos, 0, 0,
7323 &ignore, pos + 1,
7324 !dpyinfo->mouse_face_hidden);
7326 /* Display it as active. */
7327 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7328 cursor = None;
7330 else if (!NILP (mouse_face) && STRINGP (object))
7332 Lisp_Object b, e;
7333 int ignore;
7335 b = Fprevious_single_property_change (make_number (pos + 1),
7336 Qmouse_face,
7337 object, Qnil);
7338 e = Fnext_single_property_change (position, Qmouse_face,
7339 object, Qnil);
7340 if (NILP (b))
7341 b = make_number (0);
7342 if (NILP (e))
7343 e = make_number (SCHARS (object) - 1);
7344 fast_find_string_pos (w, XINT (b), object,
7345 &dpyinfo->mouse_face_beg_col,
7346 &dpyinfo->mouse_face_beg_row,
7347 &dpyinfo->mouse_face_beg_x,
7348 &dpyinfo->mouse_face_beg_y, 0);
7349 fast_find_string_pos (w, XINT (e), object,
7350 &dpyinfo->mouse_face_end_col,
7351 &dpyinfo->mouse_face_end_row,
7352 &dpyinfo->mouse_face_end_x,
7353 &dpyinfo->mouse_face_end_y, 1);
7354 dpyinfo->mouse_face_past_end = 0;
7355 dpyinfo->mouse_face_window = window;
7356 dpyinfo->mouse_face_face_id
7357 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7358 glyph->face_id, 1);
7359 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7360 cursor = None;
7362 else if (STRINGP (object) && NILP (mouse_face))
7364 /* A string which doesn't have mouse-face, but
7365 the text ``under'' it might have. */
7366 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7367 int start = MATRIX_ROW_START_CHARPOS (r);
7369 pos = string_buffer_position (w, object, start);
7370 if (pos > 0)
7371 mouse_face = get_char_property_and_overlay (make_number (pos),
7372 Qmouse_face,
7373 w->buffer,
7374 &overlay);
7375 if (!NILP (mouse_face) && !NILP (overlay))
7377 Lisp_Object before = Foverlay_start (overlay);
7378 Lisp_Object after = Foverlay_end (overlay);
7379 int ignore;
7381 /* Note that we might not be able to find position
7382 BEFORE in the glyph matrix if the overlay is
7383 entirely covered by a `display' property. In
7384 this case, we overshoot. So let's stop in
7385 the glyph matrix before glyphs for OBJECT. */
7386 fast_find_position (w, XFASTINT (before),
7387 &dpyinfo->mouse_face_beg_col,
7388 &dpyinfo->mouse_face_beg_row,
7389 &dpyinfo->mouse_face_beg_x,
7390 &dpyinfo->mouse_face_beg_y,
7391 object);
7393 dpyinfo->mouse_face_past_end
7394 = !fast_find_position (w, XFASTINT (after),
7395 &dpyinfo->mouse_face_end_col,
7396 &dpyinfo->mouse_face_end_row,
7397 &dpyinfo->mouse_face_end_x,
7398 &dpyinfo->mouse_face_end_y,
7399 Qnil);
7400 dpyinfo->mouse_face_window = window;
7401 dpyinfo->mouse_face_face_id
7402 = face_at_buffer_position (w, pos, 0, 0,
7403 &ignore, pos + 1,
7404 !dpyinfo->mouse_face_hidden);
7406 /* Display it as active. */
7407 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7408 cursor = None;
7413 check_help_echo:
7415 /* Look for a `help-echo' property. */
7417 Lisp_Object help, overlay;
7419 /* Check overlays first. */
7420 help = overlay = Qnil;
7421 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7423 overlay = overlay_vec[i];
7424 help = Foverlay_get (overlay, Qhelp_echo);
7427 if (!NILP (help))
7429 help_echo = help;
7430 help_echo_window = window;
7431 help_echo_object = overlay;
7432 help_echo_pos = pos;
7434 else
7436 Lisp_Object object = glyph->object;
7437 int charpos = glyph->charpos;
7439 /* Try text properties. */
7440 if (STRINGP (object)
7441 && charpos >= 0
7442 && charpos < SCHARS (object))
7444 help = Fget_text_property (make_number (charpos),
7445 Qhelp_echo, object);
7446 if (NILP (help))
7448 /* If the string itself doesn't specify a help-echo,
7449 see if the buffer text ``under'' it does. */
7450 struct glyph_row *r
7451 = MATRIX_ROW (w->current_matrix, vpos);
7452 int start = MATRIX_ROW_START_CHARPOS (r);
7453 int pos = string_buffer_position (w, object, start);
7454 if (pos > 0)
7456 help = Fget_char_property (make_number (pos),
7457 Qhelp_echo, w->buffer);
7458 if (!NILP (help))
7460 charpos = pos;
7461 object = w->buffer;
7466 else if (BUFFERP (object)
7467 && charpos >= BEGV
7468 && charpos < ZV)
7469 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7470 object);
7472 if (!NILP (help))
7474 help_echo = help;
7475 help_echo_window = window;
7476 help_echo_object = object;
7477 help_echo_pos = charpos;
7482 BEGV = obegv;
7483 ZV = ozv;
7484 current_buffer = obuf;
7487 set_cursor:
7489 if (cursor != None)
7490 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7493 static void
7494 redo_mouse_highlight ()
7496 if (!NILP (last_mouse_motion_frame)
7497 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7498 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7499 last_mouse_motion_event.x,
7500 last_mouse_motion_event.y);
7505 /***********************************************************************
7506 Tool-bars
7507 ***********************************************************************/
7509 static int x_tool_bar_item P_ ((struct frame *, int, int,
7510 struct glyph **, int *, int *, int *));
7512 /* Tool-bar item index of the item on which a mouse button was pressed
7513 or -1. */
7515 static int last_tool_bar_item;
7518 /* Get information about the tool-bar item at position X/Y on frame F.
7519 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7520 the current matrix of the tool-bar window of F, or NULL if not
7521 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7522 item in F->tool_bar_items. Value is
7524 -1 if X/Y is not on a tool-bar item
7525 0 if X/Y is on the same item that was highlighted before.
7526 1 otherwise. */
7528 static int
7529 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7530 struct frame *f;
7531 int x, y;
7532 struct glyph **glyph;
7533 int *hpos, *vpos, *prop_idx;
7535 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7536 struct window *w = XWINDOW (f->tool_bar_window);
7537 int area;
7539 /* Find the glyph under X/Y. */
7540 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7541 if (*glyph == NULL)
7542 return -1;
7544 /* Get the start of this tool-bar item's properties in
7545 f->tool_bar_items. */
7546 if (!tool_bar_item_info (f, *glyph, prop_idx))
7547 return -1;
7549 /* Is mouse on the highlighted item? */
7550 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7551 && *vpos >= dpyinfo->mouse_face_beg_row
7552 && *vpos <= dpyinfo->mouse_face_end_row
7553 && (*vpos > dpyinfo->mouse_face_beg_row
7554 || *hpos >= dpyinfo->mouse_face_beg_col)
7555 && (*vpos < dpyinfo->mouse_face_end_row
7556 || *hpos < dpyinfo->mouse_face_end_col
7557 || dpyinfo->mouse_face_past_end))
7558 return 0;
7560 return 1;
7564 /* Handle mouse button event on the tool-bar of frame F, at
7565 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7566 or ButtonRelase. */
7568 static void
7569 x_handle_tool_bar_click (f, button_event)
7570 struct frame *f;
7571 XButtonEvent *button_event;
7573 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7574 struct window *w = XWINDOW (f->tool_bar_window);
7575 int hpos, vpos, prop_idx;
7576 struct glyph *glyph;
7577 Lisp_Object enabled_p;
7578 int x = button_event->x;
7579 int y = button_event->y;
7581 /* If not on the highlighted tool-bar item, return. */
7582 frame_to_window_pixel_xy (w, &x, &y);
7583 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7584 return;
7586 /* If item is disabled, do nothing. */
7587 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7588 if (NILP (enabled_p))
7589 return;
7591 if (button_event->type == ButtonPress)
7593 /* Show item in pressed state. */
7594 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7595 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7596 last_tool_bar_item = prop_idx;
7598 else
7600 Lisp_Object key, frame;
7601 struct input_event event;
7603 /* Show item in released state. */
7604 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7605 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7607 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7609 XSETFRAME (frame, f);
7610 event.kind = TOOL_BAR_EVENT;
7611 event.frame_or_window = frame;
7612 event.arg = frame;
7613 kbd_buffer_store_event (&event);
7615 event.kind = TOOL_BAR_EVENT;
7616 event.frame_or_window = frame;
7617 event.arg = key;
7618 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7619 button_event->state);
7620 kbd_buffer_store_event (&event);
7621 last_tool_bar_item = -1;
7626 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7627 tool-bar window-relative coordinates X/Y. Called from
7628 note_mouse_highlight. */
7630 static void
7631 note_tool_bar_highlight (f, x, y)
7632 struct frame *f;
7633 int x, y;
7635 Lisp_Object window = f->tool_bar_window;
7636 struct window *w = XWINDOW (window);
7637 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7638 int hpos, vpos;
7639 struct glyph *glyph;
7640 struct glyph_row *row;
7641 int i;
7642 Lisp_Object enabled_p;
7643 int prop_idx;
7644 enum draw_glyphs_face draw;
7645 int mouse_down_p, rc;
7647 /* Function note_mouse_highlight is called with negative x(y
7648 values when mouse moves outside of the frame. */
7649 if (x <= 0 || y <= 0)
7651 clear_mouse_face (dpyinfo);
7652 return;
7655 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7656 if (rc < 0)
7658 /* Not on tool-bar item. */
7659 clear_mouse_face (dpyinfo);
7660 return;
7662 else if (rc == 0)
7663 goto set_help_echo;
7665 clear_mouse_face (dpyinfo);
7667 /* Mouse is down, but on different tool-bar item? */
7668 mouse_down_p = (dpyinfo->grabbed
7669 && f == last_mouse_frame
7670 && FRAME_LIVE_P (f));
7671 if (mouse_down_p
7672 && last_tool_bar_item != prop_idx)
7673 return;
7675 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7676 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7678 /* If tool-bar item is not enabled, don't highlight it. */
7679 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7680 if (!NILP (enabled_p))
7682 /* Compute the x-position of the glyph. In front and past the
7683 image is a space. We include this is the highlighted area. */
7684 row = MATRIX_ROW (w->current_matrix, vpos);
7685 for (i = x = 0; i < hpos; ++i)
7686 x += row->glyphs[TEXT_AREA][i].pixel_width;
7688 /* Record this as the current active region. */
7689 dpyinfo->mouse_face_beg_col = hpos;
7690 dpyinfo->mouse_face_beg_row = vpos;
7691 dpyinfo->mouse_face_beg_x = x;
7692 dpyinfo->mouse_face_beg_y = row->y;
7693 dpyinfo->mouse_face_past_end = 0;
7695 dpyinfo->mouse_face_end_col = hpos + 1;
7696 dpyinfo->mouse_face_end_row = vpos;
7697 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7698 dpyinfo->mouse_face_end_y = row->y;
7699 dpyinfo->mouse_face_window = window;
7700 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7702 /* Display it as active. */
7703 show_mouse_face (dpyinfo, draw);
7704 dpyinfo->mouse_face_image_state = draw;
7707 set_help_echo:
7709 /* Set help_echo to a help string to display for this tool-bar item.
7710 XTread_socket does the rest. */
7711 help_echo_object = help_echo_window = Qnil;
7712 help_echo_pos = -1;
7713 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7714 if (NILP (help_echo))
7715 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7720 /* Find the glyph matrix position of buffer position CHARPOS in window
7721 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7722 current glyphs must be up to date. If CHARPOS is above window
7723 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7724 of last line in W. In the row containing CHARPOS, stop before glyphs
7725 having STOP as object. */
7727 #if 0 /* This is a version of fast_find_position that's more correct
7728 in the presence of hscrolling, for example. I didn't install
7729 it right away because the problem fixed is minor, it failed
7730 in 20.x as well, and I think it's too risky to install
7731 so near the release of 21.1. 2001-09-25 gerd. */
7733 static int
7734 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7735 struct window *w;
7736 int charpos;
7737 int *hpos, *vpos, *x, *y;
7738 Lisp_Object stop;
7740 struct glyph_row *row, *first;
7741 struct glyph *glyph, *end;
7742 int i, past_end = 0;
7744 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7745 row = row_containing_pos (w, charpos, first, NULL, 0);
7746 if (row == NULL)
7748 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7750 *x = *y = *hpos = *vpos = 0;
7751 return 0;
7753 else
7755 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7756 past_end = 1;
7760 *x = row->x;
7761 *y = row->y;
7762 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7764 glyph = row->glyphs[TEXT_AREA];
7765 end = glyph + row->used[TEXT_AREA];
7767 /* Skip over glyphs not having an object at the start of the row.
7768 These are special glyphs like truncation marks on terminal
7769 frames. */
7770 if (row->displays_text_p)
7771 while (glyph < end
7772 && INTEGERP (glyph->object)
7773 && !EQ (stop, glyph->object)
7774 && glyph->charpos < 0)
7776 *x += glyph->pixel_width;
7777 ++glyph;
7780 while (glyph < end
7781 && !INTEGERP (glyph->object)
7782 && !EQ (stop, glyph->object)
7783 && (!BUFFERP (glyph->object)
7784 || glyph->charpos < charpos))
7786 *x += glyph->pixel_width;
7787 ++glyph;
7790 *hpos = glyph - row->glyphs[TEXT_AREA];
7791 return past_end;
7794 #else /* not 0 */
7796 static int
7797 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7798 struct window *w;
7799 int pos;
7800 int *hpos, *vpos, *x, *y;
7801 Lisp_Object stop;
7803 int i;
7804 int lastcol;
7805 int maybe_next_line_p = 0;
7806 int line_start_position;
7807 int yb = window_text_bottom_y (w);
7808 struct glyph_row *row, *best_row;
7809 int row_vpos, best_row_vpos;
7810 int current_x;
7812 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7813 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7815 while (row->y < yb)
7817 if (row->used[TEXT_AREA])
7818 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7819 else
7820 line_start_position = 0;
7822 if (line_start_position > pos)
7823 break;
7824 /* If the position sought is the end of the buffer,
7825 don't include the blank lines at the bottom of the window. */
7826 else if (line_start_position == pos
7827 && pos == BUF_ZV (XBUFFER (w->buffer)))
7829 maybe_next_line_p = 1;
7830 break;
7832 else if (line_start_position > 0)
7834 best_row = row;
7835 best_row_vpos = row_vpos;
7838 if (row->y + row->height >= yb)
7839 break;
7841 ++row;
7842 ++row_vpos;
7845 /* Find the right column within BEST_ROW. */
7846 lastcol = 0;
7847 current_x = best_row->x;
7848 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7850 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7851 int charpos = glyph->charpos;
7853 if (BUFFERP (glyph->object))
7855 if (charpos == pos)
7857 *hpos = i;
7858 *vpos = best_row_vpos;
7859 *x = current_x;
7860 *y = best_row->y;
7861 return 1;
7863 else if (charpos > pos)
7864 break;
7866 else if (EQ (glyph->object, stop))
7867 break;
7869 if (charpos > 0)
7870 lastcol = i;
7871 current_x += glyph->pixel_width;
7874 /* If we're looking for the end of the buffer,
7875 and we didn't find it in the line we scanned,
7876 use the start of the following line. */
7877 if (maybe_next_line_p)
7879 ++best_row;
7880 ++best_row_vpos;
7881 lastcol = 0;
7882 current_x = best_row->x;
7885 *vpos = best_row_vpos;
7886 *hpos = lastcol + 1;
7887 *x = current_x;
7888 *y = best_row->y;
7889 return 0;
7892 #endif /* not 0 */
7895 /* Find the position of the glyph for position POS in OBJECT in
7896 window W's current matrix, and return in *X, *Y the pixel
7897 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7899 RIGHT_P non-zero means return the position of the right edge of the
7900 glyph, RIGHT_P zero means return the left edge position.
7902 If no glyph for POS exists in the matrix, return the position of
7903 the glyph with the next smaller position that is in the matrix, if
7904 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7905 exists in the matrix, return the position of the glyph with the
7906 next larger position in OBJECT.
7908 Value is non-zero if a glyph was found. */
7910 static int
7911 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7912 struct window *w;
7913 int pos;
7914 Lisp_Object object;
7915 int *hpos, *vpos, *x, *y;
7916 int right_p;
7918 int yb = window_text_bottom_y (w);
7919 struct glyph_row *r;
7920 struct glyph *best_glyph = NULL;
7921 struct glyph_row *best_row = NULL;
7922 int best_x = 0;
7924 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7925 r->enabled_p && r->y < yb;
7926 ++r)
7928 struct glyph *g = r->glyphs[TEXT_AREA];
7929 struct glyph *e = g + r->used[TEXT_AREA];
7930 int gx;
7932 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7933 if (EQ (g->object, object))
7935 if (g->charpos == pos)
7937 best_glyph = g;
7938 best_x = gx;
7939 best_row = r;
7940 goto found;
7942 else if (best_glyph == NULL
7943 || ((abs (g->charpos - pos)
7944 < abs (best_glyph->charpos - pos))
7945 && (right_p
7946 ? g->charpos < pos
7947 : g->charpos > pos)))
7949 best_glyph = g;
7950 best_x = gx;
7951 best_row = r;
7956 found:
7958 if (best_glyph)
7960 *x = best_x;
7961 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7963 if (right_p)
7965 *x += best_glyph->pixel_width;
7966 ++*hpos;
7969 *y = best_row->y;
7970 *vpos = best_row - w->current_matrix->rows;
7973 return best_glyph != NULL;
7977 /* Display the active region described by mouse_face_*
7978 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7980 static void
7981 show_mouse_face (dpyinfo, draw)
7982 struct x_display_info *dpyinfo;
7983 enum draw_glyphs_face draw;
7985 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7986 struct frame *f = XFRAME (WINDOW_FRAME (w));
7988 if (/* If window is in the process of being destroyed, don't bother
7989 to do anything. */
7990 w->current_matrix != NULL
7991 /* Don't update mouse highlight if hidden */
7992 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7993 /* Recognize when we are called to operate on rows that don't exist
7994 anymore. This can happen when a window is split. */
7995 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7997 int phys_cursor_on_p = w->phys_cursor_on_p;
7998 struct glyph_row *row, *first, *last;
8000 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8001 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8003 for (row = first; row <= last && row->enabled_p; ++row)
8005 int start_hpos, end_hpos, start_x;
8007 /* For all but the first row, the highlight starts at column 0. */
8008 if (row == first)
8010 start_hpos = dpyinfo->mouse_face_beg_col;
8011 start_x = dpyinfo->mouse_face_beg_x;
8013 else
8015 start_hpos = 0;
8016 start_x = 0;
8019 if (row == last)
8020 end_hpos = dpyinfo->mouse_face_end_col;
8021 else
8022 end_hpos = row->used[TEXT_AREA];
8024 if (end_hpos > start_hpos)
8026 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8027 start_hpos, end_hpos, draw, 0);
8029 row->mouse_face_p
8030 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8034 /* When we've written over the cursor, arrange for it to
8035 be displayed again. */
8036 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8037 x_display_cursor (w, 1,
8038 w->phys_cursor.hpos, w->phys_cursor.vpos,
8039 w->phys_cursor.x, w->phys_cursor.y);
8042 /* Change the mouse cursor. */
8043 if (draw == DRAW_NORMAL_TEXT)
8044 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8045 f->output_data.x->text_cursor);
8046 else if (draw == DRAW_MOUSE_FACE)
8047 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8048 f->output_data.x->cross_cursor);
8049 else
8050 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8051 f->output_data.x->nontext_cursor);
8054 /* Clear out the mouse-highlighted active region.
8055 Redraw it un-highlighted first. Value is non-zero if mouse
8056 face was actually drawn unhighlighted. */
8058 static int
8059 clear_mouse_face (dpyinfo)
8060 struct x_display_info *dpyinfo;
8062 int cleared = 0;
8064 if (!NILP (dpyinfo->mouse_face_window))
8066 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8067 cleared = 1;
8070 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8071 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8072 dpyinfo->mouse_face_window = Qnil;
8073 dpyinfo->mouse_face_overlay = Qnil;
8074 return cleared;
8078 /* Clear any mouse-face on window W. This function is part of the
8079 redisplay interface, and is called from try_window_id and similar
8080 functions to ensure the mouse-highlight is off. */
8082 static void
8083 x_clear_mouse_face (w)
8084 struct window *w;
8086 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
8087 Lisp_Object window;
8089 BLOCK_INPUT;
8090 XSETWINDOW (window, w);
8091 if (EQ (window, dpyinfo->mouse_face_window))
8092 clear_mouse_face (dpyinfo);
8093 UNBLOCK_INPUT;
8097 /* Just discard the mouse face information for frame F, if any.
8098 This is used when the size of F is changed. */
8100 void
8101 cancel_mouse_face (f)
8102 FRAME_PTR f;
8104 Lisp_Object window;
8105 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8107 window = dpyinfo->mouse_face_window;
8108 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8110 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8111 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8112 dpyinfo->mouse_face_window = Qnil;
8117 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
8120 /* Try to determine frame pixel position and size of the glyph under
8121 frame pixel coordinates X/Y on frame F . Return the position and
8122 size in *RECT. Value is non-zero if we could compute these
8123 values. */
8125 static int
8126 glyph_rect (f, x, y, rect)
8127 struct frame *f;
8128 int x, y;
8129 XRectangle *rect;
8131 Lisp_Object window;
8132 int part, found = 0;
8134 window = window_from_coordinates (f, x, y, &part, 0);
8135 if (!NILP (window))
8137 struct window *w = XWINDOW (window);
8138 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8139 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8141 frame_to_window_pixel_xy (w, &x, &y);
8143 for (; !found && r < end && r->enabled_p; ++r)
8144 if (r->y >= y)
8146 struct glyph *g = r->glyphs[TEXT_AREA];
8147 struct glyph *end = g + r->used[TEXT_AREA];
8148 int gx;
8150 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
8151 if (gx >= x)
8153 rect->width = g->pixel_width;
8154 rect->height = r->height;
8155 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8156 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8157 found = 1;
8162 return found;
8166 /* Return the current position of the mouse.
8167 *FP should be a frame which indicates which display to ask about.
8169 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
8170 and *PART to the frame, window, and scroll bar part that the mouse
8171 is over. Set *X and *Y to the portion and whole of the mouse's
8172 position on the scroll bar.
8174 If the mouse movement started elsewhere, set *FP to the frame the
8175 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
8176 the mouse is over.
8178 Set *TIME to the server time-stamp for the time at which the mouse
8179 was at this position.
8181 Don't store anything if we don't have a valid set of values to report.
8183 This clears the mouse_moved flag, so we can wait for the next mouse
8184 movement. */
8186 static void
8187 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8188 FRAME_PTR *fp;
8189 int insist;
8190 Lisp_Object *bar_window;
8191 enum scroll_bar_part *part;
8192 Lisp_Object *x, *y;
8193 unsigned long *time;
8195 FRAME_PTR f1;
8197 BLOCK_INPUT;
8199 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8200 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8201 else
8203 Window root;
8204 int root_x, root_y;
8206 Window dummy_window;
8207 int dummy;
8209 Lisp_Object frame, tail;
8211 /* Clear the mouse-moved flag for every frame on this display. */
8212 FOR_EACH_FRAME (tail, frame)
8213 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
8214 XFRAME (frame)->mouse_moved = 0;
8216 last_mouse_scroll_bar = Qnil;
8218 /* Figure out which root window we're on. */
8219 XQueryPointer (FRAME_X_DISPLAY (*fp),
8220 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
8222 /* The root window which contains the pointer. */
8223 &root,
8225 /* Trash which we can't trust if the pointer is on
8226 a different screen. */
8227 &dummy_window,
8229 /* The position on that root window. */
8230 &root_x, &root_y,
8232 /* More trash we can't trust. */
8233 &dummy, &dummy,
8235 /* Modifier keys and pointer buttons, about which
8236 we don't care. */
8237 (unsigned int *) &dummy);
8239 /* Now we have a position on the root; find the innermost window
8240 containing the pointer. */
8242 Window win, child;
8243 int win_x, win_y;
8244 int parent_x = 0, parent_y = 0;
8245 int count;
8247 win = root;
8249 /* XTranslateCoordinates can get errors if the window
8250 structure is changing at the same time this function
8251 is running. So at least we must not crash from them. */
8253 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8255 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8256 && FRAME_LIVE_P (last_mouse_frame))
8258 /* If mouse was grabbed on a frame, give coords for that frame
8259 even if the mouse is now outside it. */
8260 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8262 /* From-window, to-window. */
8263 root, FRAME_X_WINDOW (last_mouse_frame),
8265 /* From-position, to-position. */
8266 root_x, root_y, &win_x, &win_y,
8268 /* Child of win. */
8269 &child);
8270 f1 = last_mouse_frame;
8272 else
8274 while (1)
8276 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8278 /* From-window, to-window. */
8279 root, win,
8281 /* From-position, to-position. */
8282 root_x, root_y, &win_x, &win_y,
8284 /* Child of win. */
8285 &child);
8287 if (child == None || child == win)
8288 break;
8290 win = child;
8291 parent_x = win_x;
8292 parent_y = win_y;
8295 /* Now we know that:
8296 win is the innermost window containing the pointer
8297 (XTC says it has no child containing the pointer),
8298 win_x and win_y are the pointer's position in it
8299 (XTC did this the last time through), and
8300 parent_x and parent_y are the pointer's position in win's parent.
8301 (They are what win_x and win_y were when win was child.
8302 If win is the root window, it has no parent, and
8303 parent_{x,y} are invalid, but that's okay, because we'll
8304 never use them in that case.) */
8306 /* Is win one of our frames? */
8307 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8309 #ifdef USE_X_TOOLKIT
8310 /* If we end up with the menu bar window, say it's not
8311 on the frame. */
8312 if (f1 != NULL
8313 && f1->output_data.x->menubar_widget
8314 && win == XtWindow (f1->output_data.x->menubar_widget))
8315 f1 = NULL;
8316 #endif /* USE_X_TOOLKIT */
8319 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8320 f1 = 0;
8322 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8324 /* If not, is it one of our scroll bars? */
8325 if (! f1)
8327 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8329 if (bar)
8331 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8332 win_x = parent_x;
8333 win_y = parent_y;
8337 if (f1 == 0 && insist > 0)
8338 f1 = SELECTED_FRAME ();
8340 if (f1)
8342 /* Ok, we found a frame. Store all the values.
8343 last_mouse_glyph is a rectangle used to reduce the
8344 generation of mouse events. To not miss any motion
8345 events, we must divide the frame into rectangles of the
8346 size of the smallest character that could be displayed
8347 on it, i.e. into the same rectangles that matrices on
8348 the frame are divided into. */
8350 int width, height, gx, gy;
8351 XRectangle rect;
8353 if (glyph_rect (f1, win_x, win_y, &rect))
8354 last_mouse_glyph = rect;
8355 else
8357 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8358 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8359 gx = win_x;
8360 gy = win_y;
8362 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8363 round down even for negative values. */
8364 if (gx < 0)
8365 gx -= width - 1;
8366 if (gy < 0)
8367 gy -= height - 1;
8368 gx = (gx + width - 1) / width * width;
8369 gy = (gy + height - 1) / height * height;
8371 last_mouse_glyph.width = width;
8372 last_mouse_glyph.height = height;
8373 last_mouse_glyph.x = gx;
8374 last_mouse_glyph.y = gy;
8377 *bar_window = Qnil;
8378 *part = 0;
8379 *fp = f1;
8380 XSETINT (*x, win_x);
8381 XSETINT (*y, win_y);
8382 *time = last_mouse_movement_time;
8387 UNBLOCK_INPUT;
8391 #ifdef USE_X_TOOLKIT
8393 /* Atimer callback function for TIMER. Called every 0.1s to process
8394 Xt timeouts, if needed. We must avoid calling XtAppPending as
8395 much as possible because that function does an implicit XFlush
8396 that slows us down. */
8398 static void
8399 x_process_timeouts (timer)
8400 struct atimer *timer;
8402 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8404 BLOCK_INPUT;
8405 while (XtAppPending (Xt_app_con) & XtIMTimer)
8406 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8407 UNBLOCK_INPUT;
8411 #endif /* USE_X_TOOLKIT */
8414 /* Scroll bar support. */
8416 /* Given an X window ID, find the struct scroll_bar which manages it.
8417 This can be called in GC, so we have to make sure to strip off mark
8418 bits. */
8420 static struct scroll_bar *
8421 x_window_to_scroll_bar (window_id)
8422 Window window_id;
8424 Lisp_Object tail;
8426 for (tail = Vframe_list;
8427 XGCTYPE (tail) == Lisp_Cons;
8428 tail = XCDR (tail))
8430 Lisp_Object frame, bar, condemned;
8432 frame = XCAR (tail);
8433 /* All elements of Vframe_list should be frames. */
8434 if (! GC_FRAMEP (frame))
8435 abort ();
8437 /* Scan this frame's scroll bar list for a scroll bar with the
8438 right window ID. */
8439 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8440 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8441 /* This trick allows us to search both the ordinary and
8442 condemned scroll bar lists with one loop. */
8443 ! GC_NILP (bar) || (bar = condemned,
8444 condemned = Qnil,
8445 ! GC_NILP (bar));
8446 bar = XSCROLL_BAR (bar)->next)
8447 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8448 return XSCROLL_BAR (bar);
8451 return 0;
8455 #if defined USE_LUCID
8457 /* Return the Lucid menu bar WINDOW is part of. Return null
8458 if WINDOW is not part of a menu bar. */
8460 static Widget
8461 x_window_to_menu_bar (window)
8462 Window window;
8464 Lisp_Object tail;
8466 for (tail = Vframe_list;
8467 XGCTYPE (tail) == Lisp_Cons;
8468 tail = XCDR (tail))
8470 Lisp_Object frame = XCAR (tail);
8471 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8473 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8474 return menu_bar;
8477 return NULL;
8480 #endif /* USE_LUCID */
8483 /************************************************************************
8484 Toolkit scroll bars
8485 ************************************************************************/
8487 #ifdef USE_TOOLKIT_SCROLL_BARS
8489 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8490 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8491 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8492 struct scroll_bar *));
8493 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8494 int, int, int));
8497 /* Id of action hook installed for scroll bars. */
8499 static XtActionHookId action_hook_id;
8501 /* Lisp window being scrolled. Set when starting to interact with
8502 a toolkit scroll bar, reset to nil when ending the interaction. */
8504 static Lisp_Object window_being_scrolled;
8506 /* Last scroll bar part sent in xm_scroll_callback. */
8508 static int last_scroll_bar_part;
8510 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8511 that movements of 1/20 of the screen size are mapped to up/down. */
8513 static Boolean xaw3d_arrow_scroll;
8515 /* Whether the drag scrolling maintains the mouse at the top of the
8516 thumb. If not, resizing the thumb needs to be done more carefully
8517 to avoid jerkyness. */
8519 static Boolean xaw3d_pick_top;
8522 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8523 bars are used.. The hook is responsible for detecting when
8524 the user ends an interaction with the scroll bar, and generates
8525 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
8527 static void
8528 xt_action_hook (widget, client_data, action_name, event, params,
8529 num_params)
8530 Widget widget;
8531 XtPointer client_data;
8532 String action_name;
8533 XEvent *event;
8534 String *params;
8535 Cardinal *num_params;
8537 int scroll_bar_p;
8538 char *end_action;
8540 #ifdef USE_MOTIF
8541 scroll_bar_p = XmIsScrollBar (widget);
8542 end_action = "Release";
8543 #else /* !USE_MOTIF i.e. use Xaw */
8544 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8545 end_action = "EndScroll";
8546 #endif /* USE_MOTIF */
8548 if (scroll_bar_p
8549 && strcmp (action_name, end_action) == 0
8550 && WINDOWP (window_being_scrolled))
8552 struct window *w;
8554 x_send_scroll_bar_event (window_being_scrolled,
8555 scroll_bar_end_scroll, 0, 0);
8556 w = XWINDOW (window_being_scrolled);
8557 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8558 window_being_scrolled = Qnil;
8559 last_scroll_bar_part = -1;
8561 /* Xt timeouts no longer needed. */
8562 toolkit_scroll_bar_interaction = 0;
8566 /* A vector of windows used for communication between
8567 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8569 static struct window **scroll_bar_windows;
8570 static int scroll_bar_windows_size;
8573 /* Send a client message with message type Xatom_Scrollbar for a
8574 scroll action to the frame of WINDOW. PART is a value identifying
8575 the part of the scroll bar that was clicked on. PORTION is the
8576 amount to scroll of a whole of WHOLE. */
8578 static void
8579 x_send_scroll_bar_event (window, part, portion, whole)
8580 Lisp_Object window;
8581 int part, portion, whole;
8583 XEvent event;
8584 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8585 struct window *w = XWINDOW (window);
8586 struct frame *f = XFRAME (w->frame);
8587 int i;
8589 BLOCK_INPUT;
8591 /* Construct a ClientMessage event to send to the frame. */
8592 ev->type = ClientMessage;
8593 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8594 ev->display = FRAME_X_DISPLAY (f);
8595 ev->window = FRAME_X_WINDOW (f);
8596 ev->format = 32;
8598 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8599 not enough to store a pointer or Lisp_Object on a 64 bit system.
8600 So, store the window in scroll_bar_windows and pass the index
8601 into that array in the event. */
8602 for (i = 0; i < scroll_bar_windows_size; ++i)
8603 if (scroll_bar_windows[i] == NULL)
8604 break;
8606 if (i == scroll_bar_windows_size)
8608 int new_size = max (10, 2 * scroll_bar_windows_size);
8609 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8610 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8612 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8613 nbytes);
8614 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8615 scroll_bar_windows_size = new_size;
8618 scroll_bar_windows[i] = w;
8619 ev->data.l[0] = (long) i;
8620 ev->data.l[1] = (long) part;
8621 ev->data.l[2] = (long) 0;
8622 ev->data.l[3] = (long) portion;
8623 ev->data.l[4] = (long) whole;
8625 /* Make Xt timeouts work while the scroll bar is active. */
8626 toolkit_scroll_bar_interaction = 1;
8628 /* Setting the event mask to zero means that the message will
8629 be sent to the client that created the window, and if that
8630 window no longer exists, no event will be sent. */
8631 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8632 UNBLOCK_INPUT;
8636 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8637 in *IEVENT. */
8639 static void
8640 x_scroll_bar_to_input_event (event, ievent)
8641 XEvent *event;
8642 struct input_event *ievent;
8644 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8645 Lisp_Object window;
8646 struct frame *f;
8647 struct window *w;
8649 w = scroll_bar_windows[ev->data.l[0]];
8650 scroll_bar_windows[ev->data.l[0]] = NULL;
8652 XSETWINDOW (window, w);
8653 f = XFRAME (w->frame);
8655 ievent->kind = SCROLL_BAR_CLICK_EVENT;
8656 ievent->frame_or_window = window;
8657 ievent->arg = Qnil;
8658 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8659 ievent->part = ev->data.l[1];
8660 ievent->code = ev->data.l[2];
8661 ievent->x = make_number ((int) ev->data.l[3]);
8662 ievent->y = make_number ((int) ev->data.l[4]);
8663 ievent->modifiers = 0;
8667 #ifdef USE_MOTIF
8669 /* Minimum and maximum values used for Motif scroll bars. */
8671 #define XM_SB_MIN 1
8672 #define XM_SB_MAX 10000000
8673 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8676 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8677 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8678 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
8680 static void
8681 xm_scroll_callback (widget, client_data, call_data)
8682 Widget widget;
8683 XtPointer client_data, call_data;
8685 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8686 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8687 int part = -1, whole = 0, portion = 0;
8689 switch (cs->reason)
8691 case XmCR_DECREMENT:
8692 bar->dragging = Qnil;
8693 part = scroll_bar_up_arrow;
8694 break;
8696 case XmCR_INCREMENT:
8697 bar->dragging = Qnil;
8698 part = scroll_bar_down_arrow;
8699 break;
8701 case XmCR_PAGE_DECREMENT:
8702 bar->dragging = Qnil;
8703 part = scroll_bar_above_handle;
8704 break;
8706 case XmCR_PAGE_INCREMENT:
8707 bar->dragging = Qnil;
8708 part = scroll_bar_below_handle;
8709 break;
8711 case XmCR_TO_TOP:
8712 bar->dragging = Qnil;
8713 part = scroll_bar_to_top;
8714 break;
8716 case XmCR_TO_BOTTOM:
8717 bar->dragging = Qnil;
8718 part = scroll_bar_to_bottom;
8719 break;
8721 case XmCR_DRAG:
8723 int slider_size;
8724 int dragging_down_p = (INTEGERP (bar->dragging)
8725 && XINT (bar->dragging) <= cs->value);
8727 /* Get the slider size. */
8728 BLOCK_INPUT;
8729 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8730 UNBLOCK_INPUT;
8732 whole = XM_SB_RANGE - slider_size;
8733 portion = min (cs->value - XM_SB_MIN, whole);
8734 part = scroll_bar_handle;
8735 bar->dragging = make_number (cs->value);
8737 break;
8739 case XmCR_VALUE_CHANGED:
8740 break;
8743 if (part >= 0)
8745 window_being_scrolled = bar->window;
8746 last_scroll_bar_part = part;
8747 x_send_scroll_bar_event (bar->window, part, portion, whole);
8752 #else /* !USE_MOTIF, i.e. Xaw. */
8755 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8756 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8757 scroll bar struct. CALL_DATA is a pointer to a float saying where
8758 the thumb is. */
8760 static void
8761 xaw_jump_callback (widget, client_data, call_data)
8762 Widget widget;
8763 XtPointer client_data, call_data;
8765 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8766 float top = *(float *) call_data;
8767 float shown;
8768 int whole, portion, height;
8769 int part;
8771 /* Get the size of the thumb, a value between 0 and 1. */
8772 BLOCK_INPUT;
8773 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8774 UNBLOCK_INPUT;
8776 whole = 10000000;
8777 portion = shown < 1 ? top * whole : 0;
8779 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8780 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8781 the bottom, so we force the scrolling whenever we see that we're
8782 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8783 we try to ensure that we always stay two pixels away from the
8784 bottom). */
8785 part = scroll_bar_down_arrow;
8786 else
8787 part = scroll_bar_handle;
8789 window_being_scrolled = bar->window;
8790 bar->dragging = make_number (portion);
8791 last_scroll_bar_part = part;
8792 x_send_scroll_bar_event (bar->window, part, portion, whole);
8796 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8797 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8798 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8799 the scroll bar. CALL_DATA is an integer specifying the action that
8800 has taken place. Its magnitude is in the range 0..height of the
8801 scroll bar. Negative values mean scroll towards buffer start.
8802 Values < height of scroll bar mean line-wise movement. */
8804 static void
8805 xaw_scroll_callback (widget, client_data, call_data)
8806 Widget widget;
8807 XtPointer client_data, call_data;
8809 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8810 /* The position really is stored cast to a pointer. */
8811 int position = (long) call_data;
8812 Dimension height;
8813 int part;
8815 /* Get the height of the scroll bar. */
8816 BLOCK_INPUT;
8817 XtVaGetValues (widget, XtNheight, &height, NULL);
8818 UNBLOCK_INPUT;
8820 if (abs (position) >= height)
8821 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8823 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8824 it maps line-movement to call_data = max(5, height/20). */
8825 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8826 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8827 else
8828 part = scroll_bar_move_ratio;
8830 window_being_scrolled = bar->window;
8831 bar->dragging = Qnil;
8832 last_scroll_bar_part = part;
8833 x_send_scroll_bar_event (bar->window, part, position, height);
8837 #endif /* not USE_MOTIF */
8840 /* Create the widget for scroll bar BAR on frame F. Record the widget
8841 and X window of the scroll bar in BAR. */
8843 static void
8844 x_create_toolkit_scroll_bar (f, bar)
8845 struct frame *f;
8846 struct scroll_bar *bar;
8848 Window xwindow;
8849 Widget widget;
8850 Arg av[20];
8851 int ac = 0;
8852 char *scroll_bar_name = "verticalScrollBar";
8853 unsigned long pixel;
8855 BLOCK_INPUT;
8857 #ifdef USE_MOTIF
8858 /* Set resources. Create the widget. */
8859 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8860 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8861 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8862 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8863 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8864 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8865 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8867 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8868 if (pixel != -1)
8870 XtSetArg (av[ac], XmNforeground, pixel);
8871 ++ac;
8874 pixel = f->output_data.x->scroll_bar_background_pixel;
8875 if (pixel != -1)
8877 XtSetArg (av[ac], XmNbackground, pixel);
8878 ++ac;
8881 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8882 scroll_bar_name, av, ac);
8884 /* Add one callback for everything that can happen. */
8885 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8886 (XtPointer) bar);
8887 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8888 (XtPointer) bar);
8889 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8890 (XtPointer) bar);
8891 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8892 (XtPointer) bar);
8893 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8894 (XtPointer) bar);
8895 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8896 (XtPointer) bar);
8897 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8898 (XtPointer) bar);
8900 /* Realize the widget. Only after that is the X window created. */
8901 XtRealizeWidget (widget);
8903 /* Set the cursor to an arrow. I didn't find a resource to do that.
8904 And I'm wondering why it hasn't an arrow cursor by default. */
8905 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8906 f->output_data.x->nontext_cursor);
8908 #else /* !USE_MOTIF i.e. use Xaw */
8910 /* Set resources. Create the widget. The background of the
8911 Xaw3d scroll bar widget is a little bit light for my taste.
8912 We don't alter it here to let users change it according
8913 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8914 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8915 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8916 /* For smoother scrolling with Xaw3d -sm */
8917 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8919 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8920 if (pixel != -1)
8922 XtSetArg (av[ac], XtNforeground, pixel);
8923 ++ac;
8926 pixel = f->output_data.x->scroll_bar_background_pixel;
8927 if (pixel != -1)
8929 XtSetArg (av[ac], XtNbackground, pixel);
8930 ++ac;
8933 /* Top/bottom shadow colors. */
8935 /* Allocate them, if necessary. */
8936 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8938 pixel = f->output_data.x->scroll_bar_background_pixel;
8939 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8940 &pixel, 1.2, 0x8000))
8941 pixel = -1;
8942 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8944 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8946 pixel = f->output_data.x->scroll_bar_background_pixel;
8947 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8948 &pixel, 0.6, 0x4000))
8949 pixel = -1;
8950 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8953 /* Tell the toolkit about them. */
8954 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8955 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8956 /* We tried to allocate a color for the top/bottom shadow, and
8957 failed, so tell Xaw3d to use dithering instead. */
8959 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8960 ++ac;
8962 else
8963 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8964 be more consistent with other emacs 3d colors, and since Xaw3d is
8965 not good at dealing with allocation failure. */
8967 /* This tells Xaw3d to use real colors instead of dithering for
8968 the shadows. */
8969 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8970 ++ac;
8972 /* Specify the colors. */
8973 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8974 if (pixel != -1)
8976 XtSetArg (av[ac], "topShadowPixel", pixel);
8977 ++ac;
8979 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8980 if (pixel != -1)
8982 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8983 ++ac;
8987 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8988 f->output_data.x->edit_widget, av, ac);
8991 char *initial = "";
8992 char *val = initial;
8993 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8994 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8995 if (val == initial)
8996 { /* ARROW_SCROLL */
8997 xaw3d_arrow_scroll = True;
8998 /* Isn't that just a personal preference ? -sm */
8999 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
9003 /* Define callbacks. */
9004 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
9005 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
9006 (XtPointer) bar);
9008 /* Realize the widget. Only after that is the X window created. */
9009 XtRealizeWidget (widget);
9011 #endif /* !USE_MOTIF */
9013 /* Install an action hook that lets us detect when the user
9014 finishes interacting with a scroll bar. */
9015 if (action_hook_id == 0)
9016 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
9018 /* Remember X window and widget in the scroll bar vector. */
9019 SET_SCROLL_BAR_X_WIDGET (bar, widget);
9020 xwindow = XtWindow (widget);
9021 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
9023 UNBLOCK_INPUT;
9027 /* Set the thumb size and position of scroll bar BAR. We are currently
9028 displaying PORTION out of a whole WHOLE, and our position POSITION. */
9030 static void
9031 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
9032 struct scroll_bar *bar;
9033 int portion, position, whole;
9035 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9036 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9037 float top, shown;
9039 BLOCK_INPUT;
9041 #ifdef USE_MOTIF
9043 /* We use an estimate of 30 chars per line rather than the real
9044 `portion' value. This has the disadvantage that the thumb size
9045 is not very representative, but it makes our life a lot easier.
9046 Otherwise, we have to constantly adjust the thumb size, which
9047 we can't always do quickly enough: while dragging, the size of
9048 the thumb might prevent the user from dragging the thumb all the
9049 way to the end. but Motif and some versions of Xaw3d don't allow
9050 updating the thumb size while dragging. Also, even if we can update
9051 its size, the update will often happen too late.
9052 If you don't believe it, check out revision 1.650 of xterm.c to see
9053 what hoops we were going through and the still poor behavior we got. */
9054 portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
9055 /* When the thumb is at the bottom, position == whole.
9056 So we need to increase `whole' to make space for the thumb. */
9057 whole += portion;
9059 if (whole <= 0)
9060 top = 0, shown = 1;
9061 else
9063 top = (float) position / whole;
9064 shown = (float) portion / whole;
9067 if (NILP (bar->dragging))
9069 int size, value;
9071 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
9072 is the scroll bar's maximum and MIN is the scroll bar's minimum
9073 value. */
9074 size = shown * XM_SB_RANGE;
9075 size = min (size, XM_SB_RANGE);
9076 size = max (size, 1);
9078 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
9079 value = top * XM_SB_RANGE;
9080 value = min (value, XM_SB_MAX - size);
9081 value = max (value, XM_SB_MIN);
9083 XmScrollBarSetValues (widget, value, size, 0, 0, False);
9085 #else /* !USE_MOTIF i.e. use Xaw */
9087 if (whole == 0)
9088 top = 0, shown = 1;
9089 else
9091 top = (float) position / whole;
9092 shown = (float) portion / whole;
9096 float old_top, old_shown;
9097 Dimension height;
9098 XtVaGetValues (widget,
9099 XtNtopOfThumb, &old_top,
9100 XtNshown, &old_shown,
9101 XtNheight, &height,
9102 NULL);
9104 /* Massage the top+shown values. */
9105 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
9106 top = max (0, min (1, top));
9107 else
9108 top = old_top;
9109 /* Keep two pixels available for moving the thumb down. */
9110 shown = max (0, min (1 - top - (2.0 / height), shown));
9112 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
9113 check that your system's configuration file contains a define
9114 for `NARROWPROTO'. See s/freebsd.h for an example. */
9115 if (top != old_top || shown != old_shown)
9117 if (NILP (bar->dragging))
9118 XawScrollbarSetThumb (widget, top, shown);
9119 else
9121 #ifdef HAVE_XAW3D
9122 ScrollbarWidget sb = (ScrollbarWidget) widget;
9123 int scroll_mode = 0;
9125 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
9126 if (xaw3d_arrow_scroll)
9128 /* Xaw3d stupidly ignores resize requests while dragging
9129 so we have to make it believe it's not in dragging mode. */
9130 scroll_mode = sb->scrollbar.scroll_mode;
9131 if (scroll_mode == 2)
9132 sb->scrollbar.scroll_mode = 0;
9134 #endif
9135 /* Try to make the scrolling a tad smoother. */
9136 if (!xaw3d_pick_top)
9137 shown = min (shown, old_shown);
9139 XawScrollbarSetThumb (widget, top, shown);
9141 #ifdef HAVE_XAW3D
9142 if (xaw3d_arrow_scroll && scroll_mode == 2)
9143 sb->scrollbar.scroll_mode = scroll_mode;
9144 #endif
9148 #endif /* !USE_MOTIF */
9150 UNBLOCK_INPUT;
9153 #endif /* USE_TOOLKIT_SCROLL_BARS */
9157 /************************************************************************
9158 Scroll bars, general
9159 ************************************************************************/
9161 /* Create a scroll bar and return the scroll bar vector for it. W is
9162 the Emacs window on which to create the scroll bar. TOP, LEFT,
9163 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
9164 scroll bar. */
9166 static struct scroll_bar *
9167 x_scroll_bar_create (w, top, left, width, height)
9168 struct window *w;
9169 int top, left, width, height;
9171 struct frame *f = XFRAME (w->frame);
9172 struct scroll_bar *bar
9173 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
9175 BLOCK_INPUT;
9177 #ifdef USE_TOOLKIT_SCROLL_BARS
9178 x_create_toolkit_scroll_bar (f, bar);
9179 #else /* not USE_TOOLKIT_SCROLL_BARS */
9181 XSetWindowAttributes a;
9182 unsigned long mask;
9183 Window window;
9185 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
9186 if (a.background_pixel == -1)
9187 a.background_pixel = f->output_data.x->background_pixel;
9189 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9190 | ButtonMotionMask | PointerMotionHintMask
9191 | ExposureMask);
9192 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
9194 mask = (CWBackPixel | CWEventMask | CWCursor);
9196 /* Clear the area of W that will serve as a scroll bar. This is
9197 for the case that a window has been split horizontally. In
9198 this case, no clear_frame is generated to reduce flickering. */
9199 if (width > 0 && height > 0)
9200 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9201 left, top, width,
9202 window_box_height (w), False);
9204 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9205 /* Position and size of scroll bar. */
9206 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9207 top,
9208 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9209 height,
9210 /* Border width, depth, class, and visual. */
9212 CopyFromParent,
9213 CopyFromParent,
9214 CopyFromParent,
9215 /* Attributes. */
9216 mask, &a);
9217 SET_SCROLL_BAR_X_WINDOW (bar, window);
9219 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9221 XSETWINDOW (bar->window, w);
9222 XSETINT (bar->top, top);
9223 XSETINT (bar->left, left);
9224 XSETINT (bar->width, width);
9225 XSETINT (bar->height, height);
9226 XSETINT (bar->start, 0);
9227 XSETINT (bar->end, 0);
9228 bar->dragging = Qnil;
9230 /* Add bar to its frame's list of scroll bars. */
9231 bar->next = FRAME_SCROLL_BARS (f);
9232 bar->prev = Qnil;
9233 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9234 if (!NILP (bar->next))
9235 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9237 /* Map the window/widget. */
9238 #ifdef USE_TOOLKIT_SCROLL_BARS
9240 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9241 XtConfigureWidget (scroll_bar,
9242 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9243 top,
9244 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9245 max (height, 1), 0);
9246 XtMapWidget (scroll_bar);
9248 #else /* not USE_TOOLKIT_SCROLL_BARS */
9249 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9250 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9252 UNBLOCK_INPUT;
9253 return bar;
9257 /* Draw BAR's handle in the proper position.
9259 If the handle is already drawn from START to END, don't bother
9260 redrawing it, unless REBUILD is non-zero; in that case, always
9261 redraw it. (REBUILD is handy for drawing the handle after expose
9262 events.)
9264 Normally, we want to constrain the start and end of the handle to
9265 fit inside its rectangle, but if the user is dragging the scroll
9266 bar handle, we want to let them drag it down all the way, so that
9267 the bar's top is as far down as it goes; otherwise, there's no way
9268 to move to the very end of the buffer. */
9270 #ifndef USE_TOOLKIT_SCROLL_BARS
9272 static void
9273 x_scroll_bar_set_handle (bar, start, end, rebuild)
9274 struct scroll_bar *bar;
9275 int start, end;
9276 int rebuild;
9278 int dragging = ! NILP (bar->dragging);
9279 Window w = SCROLL_BAR_X_WINDOW (bar);
9280 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9281 GC gc = f->output_data.x->normal_gc;
9283 /* If the display is already accurate, do nothing. */
9284 if (! rebuild
9285 && start == XINT (bar->start)
9286 && end == XINT (bar->end))
9287 return;
9289 BLOCK_INPUT;
9292 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9293 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9294 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9296 /* Make sure the values are reasonable, and try to preserve
9297 the distance between start and end. */
9299 int length = end - start;
9301 if (start < 0)
9302 start = 0;
9303 else if (start > top_range)
9304 start = top_range;
9305 end = start + length;
9307 if (end < start)
9308 end = start;
9309 else if (end > top_range && ! dragging)
9310 end = top_range;
9313 /* Store the adjusted setting in the scroll bar. */
9314 XSETINT (bar->start, start);
9315 XSETINT (bar->end, end);
9317 /* Clip the end position, just for display. */
9318 if (end > top_range)
9319 end = top_range;
9321 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9322 below top positions, to make sure the handle is always at least
9323 that many pixels tall. */
9324 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9326 /* Draw the empty space above the handle. Note that we can't clear
9327 zero-height areas; that means "clear to end of window." */
9328 if (0 < start)
9329 x_clear_area (FRAME_X_DISPLAY (f), w,
9330 /* x, y, width, height, and exposures. */
9331 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9332 VERTICAL_SCROLL_BAR_TOP_BORDER,
9333 inside_width, start,
9334 False);
9336 /* Change to proper foreground color if one is specified. */
9337 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9338 XSetForeground (FRAME_X_DISPLAY (f), gc,
9339 f->output_data.x->scroll_bar_foreground_pixel);
9341 /* Draw the handle itself. */
9342 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9343 /* x, y, width, height */
9344 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9345 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9346 inside_width, end - start);
9348 /* Restore the foreground color of the GC if we changed it above. */
9349 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9350 XSetForeground (FRAME_X_DISPLAY (f), gc,
9351 f->output_data.x->foreground_pixel);
9353 /* Draw the empty space below the handle. Note that we can't
9354 clear zero-height areas; that means "clear to end of window." */
9355 if (end < inside_height)
9356 x_clear_area (FRAME_X_DISPLAY (f), w,
9357 /* x, y, width, height, and exposures. */
9358 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9359 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9360 inside_width, inside_height - end,
9361 False);
9365 UNBLOCK_INPUT;
9368 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9370 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9371 nil. */
9373 static void
9374 x_scroll_bar_remove (bar)
9375 struct scroll_bar *bar;
9377 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9378 BLOCK_INPUT;
9380 #ifdef USE_TOOLKIT_SCROLL_BARS
9381 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9382 #else
9383 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9384 #endif
9386 /* Disassociate this scroll bar from its window. */
9387 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9389 UNBLOCK_INPUT;
9393 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9394 that we are displaying PORTION characters out of a total of WHOLE
9395 characters, starting at POSITION. If WINDOW has no scroll bar,
9396 create one. */
9398 static void
9399 XTset_vertical_scroll_bar (w, portion, whole, position)
9400 struct window *w;
9401 int portion, whole, position;
9403 struct frame *f = XFRAME (w->frame);
9404 struct scroll_bar *bar;
9405 int top, height, left, sb_left, width, sb_width;
9406 int window_x, window_y, window_width, window_height;
9408 /* Get window dimensions. */
9409 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9410 top = window_y;
9411 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9412 height = window_height;
9414 /* Compute the left edge of the scroll bar area. */
9415 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9416 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9417 else
9418 left = XFASTINT (w->left);
9419 left *= CANON_X_UNIT (f);
9420 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9422 /* Compute the width of the scroll bar which might be less than
9423 the width of the area reserved for the scroll bar. */
9424 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9425 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9426 else
9427 sb_width = width;
9429 /* Compute the left edge of the scroll bar. */
9430 #ifdef USE_TOOLKIT_SCROLL_BARS
9431 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9432 sb_left = left + width - sb_width - (width - sb_width) / 2;
9433 else
9434 sb_left = left + (width - sb_width) / 2;
9435 #else
9436 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9437 sb_left = left + width - sb_width;
9438 else
9439 sb_left = left;
9440 #endif
9442 /* Does the scroll bar exist yet? */
9443 if (NILP (w->vertical_scroll_bar))
9445 if (width > 0 && height > 0)
9447 BLOCK_INPUT;
9448 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9449 left, top, width, height, False);
9450 UNBLOCK_INPUT;
9453 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9455 else
9457 /* It may just need to be moved and resized. */
9458 unsigned int mask = 0;
9460 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9462 BLOCK_INPUT;
9464 if (sb_left != XINT (bar->left))
9465 mask |= CWX;
9466 if (top != XINT (bar->top))
9467 mask |= CWY;
9468 if (sb_width != XINT (bar->width))
9469 mask |= CWWidth;
9470 if (height != XINT (bar->height))
9471 mask |= CWHeight;
9473 #ifdef USE_TOOLKIT_SCROLL_BARS
9475 /* Since toolkit scroll bars are smaller than the space reserved
9476 for them on the frame, we have to clear "under" them. */
9477 if (width > 0 && height > 0)
9478 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9479 left, top, width, height, False);
9481 /* Move/size the scroll bar widget. */
9482 if (mask)
9483 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9484 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9485 top,
9486 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9487 max (height, 1), 0);
9489 #else /* not USE_TOOLKIT_SCROLL_BARS */
9491 /* Clear areas not covered by the scroll bar because of
9492 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9493 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9495 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9496 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9497 height, False);
9498 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9499 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9500 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9501 height, False);
9504 /* Clear areas not covered by the scroll bar because it's not as
9505 wide as the area reserved for it. This makes sure a
9506 previous mode line display is cleared after C-x 2 C-x 1, for
9507 example. */
9509 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9510 int rest = area_width - sb_width;
9511 if (rest > 0 && height > 0)
9513 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9514 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9515 left + area_width - rest, top,
9516 rest, height, False);
9517 else
9518 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9519 left, top, rest, height, False);
9523 /* Move/size the scroll bar window. */
9524 if (mask)
9526 XWindowChanges wc;
9528 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9529 wc.y = top;
9530 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9531 wc.height = height;
9532 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9533 mask, &wc);
9536 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9538 /* Remember new settings. */
9539 XSETINT (bar->left, sb_left);
9540 XSETINT (bar->top, top);
9541 XSETINT (bar->width, sb_width);
9542 XSETINT (bar->height, height);
9544 UNBLOCK_INPUT;
9547 #ifdef USE_TOOLKIT_SCROLL_BARS
9548 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9549 #else /* not USE_TOOLKIT_SCROLL_BARS */
9550 /* Set the scroll bar's current state, unless we're currently being
9551 dragged. */
9552 if (NILP (bar->dragging))
9554 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9556 if (whole == 0)
9557 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9558 else
9560 int start = ((double) position * top_range) / whole;
9561 int end = ((double) (position + portion) * top_range) / whole;
9562 x_scroll_bar_set_handle (bar, start, end, 0);
9565 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9567 XSETVECTOR (w->vertical_scroll_bar, bar);
9571 /* The following three hooks are used when we're doing a thorough
9572 redisplay of the frame. We don't explicitly know which scroll bars
9573 are going to be deleted, because keeping track of when windows go
9574 away is a real pain - "Can you say set-window-configuration, boys
9575 and girls?" Instead, we just assert at the beginning of redisplay
9576 that *all* scroll bars are to be removed, and then save a scroll bar
9577 from the fiery pit when we actually redisplay its window. */
9579 /* Arrange for all scroll bars on FRAME to be removed at the next call
9580 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9581 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9583 static void
9584 XTcondemn_scroll_bars (frame)
9585 FRAME_PTR frame;
9587 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9588 while (! NILP (FRAME_SCROLL_BARS (frame)))
9590 Lisp_Object bar;
9591 bar = FRAME_SCROLL_BARS (frame);
9592 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9593 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9594 XSCROLL_BAR (bar)->prev = Qnil;
9595 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9596 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9597 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9602 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9603 Note that WINDOW isn't necessarily condemned at all. */
9605 static void
9606 XTredeem_scroll_bar (window)
9607 struct window *window;
9609 struct scroll_bar *bar;
9610 struct frame *f;
9612 /* We can't redeem this window's scroll bar if it doesn't have one. */
9613 if (NILP (window->vertical_scroll_bar))
9614 abort ();
9616 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9618 /* Unlink it from the condemned list. */
9619 f = XFRAME (WINDOW_FRAME (window));
9620 if (NILP (bar->prev))
9622 /* If the prev pointer is nil, it must be the first in one of
9623 the lists. */
9624 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9625 /* It's not condemned. Everything's fine. */
9626 return;
9627 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9628 window->vertical_scroll_bar))
9629 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9630 else
9631 /* If its prev pointer is nil, it must be at the front of
9632 one or the other! */
9633 abort ();
9635 else
9636 XSCROLL_BAR (bar->prev)->next = bar->next;
9638 if (! NILP (bar->next))
9639 XSCROLL_BAR (bar->next)->prev = bar->prev;
9641 bar->next = FRAME_SCROLL_BARS (f);
9642 bar->prev = Qnil;
9643 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9644 if (! NILP (bar->next))
9645 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9648 /* Remove all scroll bars on FRAME that haven't been saved since the
9649 last call to `*condemn_scroll_bars_hook'. */
9651 static void
9652 XTjudge_scroll_bars (f)
9653 FRAME_PTR f;
9655 Lisp_Object bar, next;
9657 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9659 /* Clear out the condemned list now so we won't try to process any
9660 more events on the hapless scroll bars. */
9661 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9663 for (; ! NILP (bar); bar = next)
9665 struct scroll_bar *b = XSCROLL_BAR (bar);
9667 x_scroll_bar_remove (b);
9669 next = b->next;
9670 b->next = b->prev = Qnil;
9673 /* Now there should be no references to the condemned scroll bars,
9674 and they should get garbage-collected. */
9678 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9679 is a no-op when using toolkit scroll bars.
9681 This may be called from a signal handler, so we have to ignore GC
9682 mark bits. */
9684 static void
9685 x_scroll_bar_expose (bar, event)
9686 struct scroll_bar *bar;
9687 XEvent *event;
9689 #ifndef USE_TOOLKIT_SCROLL_BARS
9691 Window w = SCROLL_BAR_X_WINDOW (bar);
9692 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9693 GC gc = f->output_data.x->normal_gc;
9694 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9696 BLOCK_INPUT;
9698 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9700 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9701 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9703 /* x, y, width, height */
9704 0, 0,
9705 XINT (bar->width) - 1 - width_trim - width_trim,
9706 XINT (bar->height) - 1);
9708 UNBLOCK_INPUT;
9710 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9713 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9714 is set to something other than NO_EVENT, it is enqueued.
9716 This may be called from a signal handler, so we have to ignore GC
9717 mark bits. */
9719 #ifndef USE_TOOLKIT_SCROLL_BARS
9721 static void
9722 x_scroll_bar_handle_click (bar, event, emacs_event)
9723 struct scroll_bar *bar;
9724 XEvent *event;
9725 struct input_event *emacs_event;
9727 if (! GC_WINDOWP (bar->window))
9728 abort ();
9730 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
9731 emacs_event->code = event->xbutton.button - Button1;
9732 emacs_event->modifiers
9733 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9734 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9735 event->xbutton.state)
9736 | (event->type == ButtonRelease
9737 ? up_modifier
9738 : down_modifier));
9739 emacs_event->frame_or_window = bar->window;
9740 emacs_event->arg = Qnil;
9741 emacs_event->timestamp = event->xbutton.time;
9743 #if 0
9744 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9745 int internal_height
9746 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9747 #endif
9748 int top_range
9749 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9750 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9752 if (y < 0) y = 0;
9753 if (y > top_range) y = top_range;
9755 if (y < XINT (bar->start))
9756 emacs_event->part = scroll_bar_above_handle;
9757 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9758 emacs_event->part = scroll_bar_handle;
9759 else
9760 emacs_event->part = scroll_bar_below_handle;
9762 /* Just because the user has clicked on the handle doesn't mean
9763 they want to drag it. Lisp code needs to be able to decide
9764 whether or not we're dragging. */
9765 #if 0
9766 /* If the user has just clicked on the handle, record where they're
9767 holding it. */
9768 if (event->type == ButtonPress
9769 && emacs_event->part == scroll_bar_handle)
9770 XSETINT (bar->dragging, y - XINT (bar->start));
9771 #endif
9773 /* If the user has released the handle, set it to its final position. */
9774 if (event->type == ButtonRelease
9775 && ! NILP (bar->dragging))
9777 int new_start = y - XINT (bar->dragging);
9778 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9780 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9781 bar->dragging = Qnil;
9784 /* Same deal here as the other #if 0. */
9785 #if 0
9786 /* Clicks on the handle are always reported as occurring at the top of
9787 the handle. */
9788 if (emacs_event->part == scroll_bar_handle)
9789 emacs_event->x = bar->start;
9790 else
9791 XSETINT (emacs_event->x, y);
9792 #else
9793 XSETINT (emacs_event->x, y);
9794 #endif
9796 XSETINT (emacs_event->y, top_range);
9800 /* Handle some mouse motion while someone is dragging the scroll bar.
9802 This may be called from a signal handler, so we have to ignore GC
9803 mark bits. */
9805 static void
9806 x_scroll_bar_note_movement (bar, event)
9807 struct scroll_bar *bar;
9808 XEvent *event;
9810 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9812 last_mouse_movement_time = event->xmotion.time;
9814 f->mouse_moved = 1;
9815 XSETVECTOR (last_mouse_scroll_bar, bar);
9817 /* If we're dragging the bar, display it. */
9818 if (! GC_NILP (bar->dragging))
9820 /* Where should the handle be now? */
9821 int new_start = event->xmotion.y - XINT (bar->dragging);
9823 if (new_start != XINT (bar->start))
9825 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9827 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9832 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9834 /* Return information to the user about the current position of the mouse
9835 on the scroll bar. */
9837 static void
9838 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9839 FRAME_PTR *fp;
9840 Lisp_Object *bar_window;
9841 enum scroll_bar_part *part;
9842 Lisp_Object *x, *y;
9843 unsigned long *time;
9845 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9846 Window w = SCROLL_BAR_X_WINDOW (bar);
9847 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9848 int win_x, win_y;
9849 Window dummy_window;
9850 int dummy_coord;
9851 unsigned int dummy_mask;
9853 BLOCK_INPUT;
9855 /* Get the mouse's position relative to the scroll bar window, and
9856 report that. */
9857 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9859 /* Root, child, root x and root y. */
9860 &dummy_window, &dummy_window,
9861 &dummy_coord, &dummy_coord,
9863 /* Position relative to scroll bar. */
9864 &win_x, &win_y,
9866 /* Mouse buttons and modifier keys. */
9867 &dummy_mask))
9869 else
9871 #if 0
9872 int inside_height
9873 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9874 #endif
9875 int top_range
9876 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9878 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9880 if (! NILP (bar->dragging))
9881 win_y -= XINT (bar->dragging);
9883 if (win_y < 0)
9884 win_y = 0;
9885 if (win_y > top_range)
9886 win_y = top_range;
9888 *fp = f;
9889 *bar_window = bar->window;
9891 if (! NILP (bar->dragging))
9892 *part = scroll_bar_handle;
9893 else if (win_y < XINT (bar->start))
9894 *part = scroll_bar_above_handle;
9895 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9896 *part = scroll_bar_handle;
9897 else
9898 *part = scroll_bar_below_handle;
9900 XSETINT (*x, win_y);
9901 XSETINT (*y, top_range);
9903 f->mouse_moved = 0;
9904 last_mouse_scroll_bar = Qnil;
9907 *time = last_mouse_movement_time;
9909 UNBLOCK_INPUT;
9913 /* The screen has been cleared so we may have changed foreground or
9914 background colors, and the scroll bars may need to be redrawn.
9915 Clear out the scroll bars, and ask for expose events, so we can
9916 redraw them. */
9918 void
9919 x_scroll_bar_clear (f)
9920 FRAME_PTR f;
9922 #ifndef USE_TOOLKIT_SCROLL_BARS
9923 Lisp_Object bar;
9925 /* We can have scroll bars even if this is 0,
9926 if we just turned off scroll bar mode.
9927 But in that case we should not clear them. */
9928 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9929 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9930 bar = XSCROLL_BAR (bar)->next)
9931 XClearArea (FRAME_X_DISPLAY (f),
9932 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9933 0, 0, 0, 0, True);
9934 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9937 /* This processes Expose events from the menu-bar specific X event
9938 loop in xmenu.c. This allows to redisplay the frame if necessary
9939 when handling menu-bar or pop-up items. */
9942 process_expose_from_menu (event)
9943 XEvent event;
9945 FRAME_PTR f;
9946 struct x_display_info *dpyinfo;
9947 int frame_exposed_p = 0;
9949 BLOCK_INPUT;
9951 dpyinfo = x_display_info_for_display (event.xexpose.display);
9952 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9953 if (f)
9955 if (f->async_visible == 0)
9957 f->async_visible = 1;
9958 f->async_iconified = 0;
9959 f->output_data.x->has_been_visible = 1;
9960 SET_FRAME_GARBAGED (f);
9962 else
9964 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9965 event.xexpose.x, event.xexpose.y,
9966 event.xexpose.width, event.xexpose.height);
9967 frame_exposed_p = 1;
9970 else
9972 struct scroll_bar *bar
9973 = x_window_to_scroll_bar (event.xexpose.window);
9975 if (bar)
9976 x_scroll_bar_expose (bar, &event);
9979 UNBLOCK_INPUT;
9980 return frame_exposed_p;
9983 /* Define a queue to save up SelectionRequest events for later handling. */
9985 struct selection_event_queue
9987 XEvent event;
9988 struct selection_event_queue *next;
9991 static struct selection_event_queue *queue;
9993 /* Nonzero means queue up certain events--don't process them yet. */
9995 static int x_queue_selection_requests;
9997 /* Queue up an X event *EVENT, to be processed later. */
9999 static void
10000 x_queue_event (f, event)
10001 FRAME_PTR f;
10002 XEvent *event;
10004 struct selection_event_queue *queue_tmp
10005 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
10007 if (queue_tmp != NULL)
10009 queue_tmp->event = *event;
10010 queue_tmp->next = queue;
10011 queue = queue_tmp;
10015 /* Take all the queued events and put them back
10016 so that they get processed afresh. */
10018 static void
10019 x_unqueue_events (display)
10020 Display *display;
10022 while (queue != NULL)
10024 struct selection_event_queue *queue_tmp = queue;
10025 XPutBackEvent (display, &queue_tmp->event);
10026 queue = queue_tmp->next;
10027 xfree ((char *)queue_tmp);
10031 /* Start queuing SelectionRequest events. */
10033 void
10034 x_start_queuing_selection_requests (display)
10035 Display *display;
10037 x_queue_selection_requests++;
10040 /* Stop queuing SelectionRequest events. */
10042 void
10043 x_stop_queuing_selection_requests (display)
10044 Display *display;
10046 x_queue_selection_requests--;
10047 x_unqueue_events (display);
10050 /* The main X event-reading loop - XTread_socket. */
10052 #if 0
10053 /* Time stamp of enter window event. This is only used by XTread_socket,
10054 but we have to put it out here, since static variables within functions
10055 sometimes don't work. */
10057 static Time enter_timestamp;
10058 #endif
10060 /* This holds the state XLookupString needs to implement dead keys
10061 and other tricks known as "compose processing". _X Window System_
10062 says that a portable program can't use this, but Stephen Gildea assures
10063 me that letting the compiler initialize it to zeros will work okay.
10065 This must be defined outside of XTread_socket, for the same reasons
10066 given for enter_timestamp, above. */
10068 static XComposeStatus compose_status;
10070 /* Record the last 100 characters stored
10071 to help debug the loss-of-chars-during-GC problem. */
10073 static int temp_index;
10074 static short temp_buffer[100];
10076 /* Set this to nonzero to fake an "X I/O error"
10077 on a particular display. */
10079 struct x_display_info *XTread_socket_fake_io_error;
10081 /* When we find no input here, we occasionally do a no-op command
10082 to verify that the X server is still running and we can still talk with it.
10083 We try all the open displays, one by one.
10084 This variable is used for cycling thru the displays. */
10086 static struct x_display_info *next_noop_dpyinfo;
10088 #define SET_SAVED_MENU_EVENT(size) \
10089 do \
10091 if (f->output_data.x->saved_menu_event == 0) \
10092 f->output_data.x->saved_menu_event \
10093 = (XEvent *) xmalloc (sizeof (XEvent)); \
10094 bcopy (&event, f->output_data.x->saved_menu_event, size); \
10095 if (numchars >= 1) \
10097 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
10098 XSETFRAME (bufp->frame_or_window, f); \
10099 bufp->arg = Qnil; \
10100 bufp++; \
10101 count++; \
10102 numchars--; \
10105 while (0)
10107 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10108 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10110 /* Read events coming from the X server.
10111 This routine is called by the SIGIO handler.
10112 We return as soon as there are no more events to be read.
10114 Events representing keys are stored in buffer BUFP,
10115 which can hold up to NUMCHARS characters.
10116 We return the number of characters stored into the buffer,
10117 thus pretending to be `read'.
10119 EXPECTED is nonzero if the caller knows input is available. */
10121 static int
10122 XTread_socket (sd, bufp, numchars, expected)
10123 register int sd;
10124 /* register */ struct input_event *bufp;
10125 /* register */ int numchars;
10126 int expected;
10128 int count = 0;
10129 int nbytes = 0;
10130 XEvent event;
10131 struct frame *f;
10132 int event_found = 0;
10133 struct x_display_info *dpyinfo;
10134 struct coding_system coding;
10136 if (interrupt_input_blocked)
10138 interrupt_input_pending = 1;
10139 return -1;
10142 interrupt_input_pending = 0;
10143 BLOCK_INPUT;
10145 /* So people can tell when we have read the available input. */
10146 input_signal_count++;
10148 if (numchars <= 0)
10149 abort (); /* Don't think this happens. */
10151 ++handling_signal;
10153 /* Find the display we are supposed to read input for.
10154 It's the one communicating on descriptor SD. */
10155 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
10157 #if 0 /* This ought to be unnecessary; let's verify it. */
10158 #ifdef FIOSNBIO
10159 /* If available, Xlib uses FIOSNBIO to make the socket
10160 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
10161 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
10162 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
10163 fcntl (dpyinfo->connection, F_SETFL, 0);
10164 #endif /* ! defined (FIOSNBIO) */
10165 #endif
10167 #if 0 /* This code can't be made to work, with multiple displays,
10168 and appears not to be used on any system any more.
10169 Also keyboard.c doesn't turn O_NDELAY on and off
10170 for X connections. */
10171 #ifndef SIGIO
10172 #ifndef HAVE_SELECT
10173 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
10175 extern int read_alarm_should_throw;
10176 read_alarm_should_throw = 1;
10177 XPeekEvent (dpyinfo->display, &event);
10178 read_alarm_should_throw = 0;
10180 #endif /* HAVE_SELECT */
10181 #endif /* SIGIO */
10182 #endif
10184 /* For debugging, this gives a way to fake an I/O error. */
10185 if (dpyinfo == XTread_socket_fake_io_error)
10187 XTread_socket_fake_io_error = 0;
10188 x_io_error_quitter (dpyinfo->display);
10191 #ifdef HAVE_X_SM
10192 BLOCK_INPUT;
10193 count += x_session_check_input (bufp, &numchars);
10194 UNBLOCK_INPUT;
10195 #endif
10197 while (XPending (dpyinfo->display))
10199 XNextEvent (dpyinfo->display, &event);
10201 #ifdef HAVE_X_I18N
10203 /* Filter events for the current X input method.
10204 XFilterEvent returns non-zero if the input method has
10205 consumed the event. We pass the frame's X window to
10206 XFilterEvent because that's the one for which the IC
10207 was created. */
10208 struct frame *f1 = x_any_window_to_frame (dpyinfo,
10209 event.xclient.window);
10210 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
10211 break;
10213 #endif
10214 event_found = 1;
10216 switch (event.type)
10218 case ClientMessage:
10220 if (event.xclient.message_type
10221 == dpyinfo->Xatom_wm_protocols
10222 && event.xclient.format == 32)
10224 if (event.xclient.data.l[0]
10225 == dpyinfo->Xatom_wm_take_focus)
10227 /* Use x_any_window_to_frame because this
10228 could be the shell widget window
10229 if the frame has no title bar. */
10230 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10231 #ifdef HAVE_X_I18N
10232 /* Not quite sure this is needed -pd */
10233 if (f && FRAME_XIC (f))
10234 XSetICFocus (FRAME_XIC (f));
10235 #endif
10236 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10237 instructs the WM to set the input focus automatically for
10238 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10239 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10240 it has set the focus. So, XSetInputFocus below is not
10241 needed.
10243 The call to XSetInputFocus below has also caused trouble. In
10244 cases where the XSetInputFocus done by the WM and the one
10245 below are temporally close (on a fast machine), the call
10246 below can generate additional FocusIn events which confuse
10247 Emacs. */
10249 /* Since we set WM_TAKE_FOCUS, we must call
10250 XSetInputFocus explicitly. But not if f is null,
10251 since that might be an event for a deleted frame. */
10252 if (f)
10254 Display *d = event.xclient.display;
10255 /* Catch and ignore errors, in case window has been
10256 iconified by a window manager such as GWM. */
10257 int count = x_catch_errors (d);
10258 XSetInputFocus (d, event.xclient.window,
10259 /* The ICCCM says this is
10260 the only valid choice. */
10261 RevertToParent,
10262 event.xclient.data.l[1]);
10263 /* This is needed to detect the error
10264 if there is an error. */
10265 XSync (d, False);
10266 x_uncatch_errors (d, count);
10268 /* Not certain about handling scroll bars here */
10269 #endif /* 0 */
10271 else if (event.xclient.data.l[0]
10272 == dpyinfo->Xatom_wm_save_yourself)
10274 /* Save state modify the WM_COMMAND property to
10275 something which can reinstate us. This notifies
10276 the session manager, who's looking for such a
10277 PropertyNotify. Can restart processing when
10278 a keyboard or mouse event arrives. */
10279 /* If we have a session manager, don't set this.
10280 KDE will then start two Emacsen, one for the
10281 session manager and one for this. */
10282 if (numchars > 0
10283 #ifdef HAVE_X_SM
10284 && ! x_session_have_connection ()
10285 #endif
10288 f = x_top_window_to_frame (dpyinfo,
10289 event.xclient.window);
10290 /* This is just so we only give real data once
10291 for a single Emacs process. */
10292 if (f == SELECTED_FRAME ())
10293 XSetCommand (FRAME_X_DISPLAY (f),
10294 event.xclient.window,
10295 initial_argv, initial_argc);
10296 else if (f)
10297 XSetCommand (FRAME_X_DISPLAY (f),
10298 event.xclient.window,
10299 0, 0);
10302 else if (event.xclient.data.l[0]
10303 == dpyinfo->Xatom_wm_delete_window)
10305 struct frame *f
10306 = x_any_window_to_frame (dpyinfo,
10307 event.xclient.window);
10309 if (f)
10311 if (numchars == 0)
10312 abort ();
10314 bufp->kind = DELETE_WINDOW_EVENT;
10315 XSETFRAME (bufp->frame_or_window, f);
10316 bufp->arg = Qnil;
10317 bufp++;
10319 count += 1;
10320 numchars -= 1;
10324 else if (event.xclient.message_type
10325 == dpyinfo->Xatom_wm_configure_denied)
10328 else if (event.xclient.message_type
10329 == dpyinfo->Xatom_wm_window_moved)
10331 int new_x, new_y;
10332 struct frame *f
10333 = x_window_to_frame (dpyinfo, event.xclient.window);
10335 new_x = event.xclient.data.s[0];
10336 new_y = event.xclient.data.s[1];
10338 if (f)
10340 f->output_data.x->left_pos = new_x;
10341 f->output_data.x->top_pos = new_y;
10344 #ifdef HACK_EDITRES
10345 else if (event.xclient.message_type
10346 == dpyinfo->Xatom_editres)
10348 struct frame *f
10349 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10350 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10351 &event, NULL);
10353 #endif /* HACK_EDITRES */
10354 else if ((event.xclient.message_type
10355 == dpyinfo->Xatom_DONE)
10356 || (event.xclient.message_type
10357 == dpyinfo->Xatom_PAGE))
10359 /* Ghostview job completed. Kill it. We could
10360 reply with "Next" if we received "Page", but we
10361 currently never do because we are interested in
10362 images, only, which should have 1 page. */
10363 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10364 struct frame *f
10365 = x_window_to_frame (dpyinfo, event.xclient.window);
10366 x_kill_gs_process (pixmap, f);
10367 expose_frame (f, 0, 0, 0, 0);
10369 #ifdef USE_TOOLKIT_SCROLL_BARS
10370 /* Scroll bar callbacks send a ClientMessage from which
10371 we construct an input_event. */
10372 else if (event.xclient.message_type
10373 == dpyinfo->Xatom_Scrollbar)
10375 x_scroll_bar_to_input_event (&event, bufp);
10376 ++bufp, ++count, --numchars;
10377 goto out;
10379 #endif /* USE_TOOLKIT_SCROLL_BARS */
10380 else
10381 goto OTHER;
10383 break;
10385 case SelectionNotify:
10386 #ifdef USE_X_TOOLKIT
10387 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10388 goto OTHER;
10389 #endif /* not USE_X_TOOLKIT */
10390 x_handle_selection_notify (&event.xselection);
10391 break;
10393 case SelectionClear: /* Someone has grabbed ownership. */
10394 #ifdef USE_X_TOOLKIT
10395 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10396 goto OTHER;
10397 #endif /* USE_X_TOOLKIT */
10399 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10401 if (numchars == 0)
10402 abort ();
10404 bufp->kind = SELECTION_CLEAR_EVENT;
10405 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10406 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10407 SELECTION_EVENT_TIME (bufp) = eventp->time;
10408 bufp->frame_or_window = Qnil;
10409 bufp->arg = Qnil;
10410 bufp++;
10412 count += 1;
10413 numchars -= 1;
10415 break;
10417 case SelectionRequest: /* Someone wants our selection. */
10418 #ifdef USE_X_TOOLKIT
10419 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10420 goto OTHER;
10421 #endif /* USE_X_TOOLKIT */
10422 if (x_queue_selection_requests)
10423 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10424 &event);
10425 else
10427 XSelectionRequestEvent *eventp
10428 = (XSelectionRequestEvent *) &event;
10430 if (numchars == 0)
10431 abort ();
10433 bufp->kind = SELECTION_REQUEST_EVENT;
10434 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10435 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10436 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10437 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10438 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10439 SELECTION_EVENT_TIME (bufp) = eventp->time;
10440 bufp->frame_or_window = Qnil;
10441 bufp->arg = Qnil;
10442 bufp++;
10444 count += 1;
10445 numchars -= 1;
10447 break;
10449 case PropertyNotify:
10450 #if 0 /* This is plain wrong. In the case that we are waiting for a
10451 PropertyNotify used as an ACK in incremental selection
10452 transfer, the property will be on the receiver's window. */
10453 #if defined USE_X_TOOLKIT
10454 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10455 goto OTHER;
10456 #endif
10457 #endif
10458 x_handle_property_notify (&event.xproperty);
10459 goto OTHER;
10461 case ReparentNotify:
10462 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10463 if (f)
10465 int x, y;
10466 f->output_data.x->parent_desc = event.xreparent.parent;
10467 x_real_positions (f, &x, &y);
10468 f->output_data.x->left_pos = x;
10469 f->output_data.x->top_pos = y;
10470 goto OTHER;
10472 break;
10474 case Expose:
10475 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10476 if (f)
10478 x_check_fullscreen (f);
10480 if (f->async_visible == 0)
10482 f->async_visible = 1;
10483 f->async_iconified = 0;
10484 f->output_data.x->has_been_visible = 1;
10485 SET_FRAME_GARBAGED (f);
10487 else
10488 expose_frame (x_window_to_frame (dpyinfo,
10489 event.xexpose.window),
10490 event.xexpose.x, event.xexpose.y,
10491 event.xexpose.width, event.xexpose.height);
10493 else
10495 #ifndef USE_TOOLKIT_SCROLL_BARS
10496 struct scroll_bar *bar;
10497 #endif
10498 #if defined USE_LUCID
10499 /* Submenus of the Lucid menu bar aren't widgets
10500 themselves, so there's no way to dispatch events
10501 to them. Recognize this case separately. */
10503 Widget widget
10504 = x_window_to_menu_bar (event.xexpose.window);
10505 if (widget)
10506 xlwmenu_redisplay (widget);
10508 #endif /* USE_LUCID */
10510 #ifdef USE_TOOLKIT_SCROLL_BARS
10511 /* Dispatch event to the widget. */
10512 goto OTHER;
10513 #else /* not USE_TOOLKIT_SCROLL_BARS */
10514 bar = x_window_to_scroll_bar (event.xexpose.window);
10516 if (bar)
10517 x_scroll_bar_expose (bar, &event);
10518 #ifdef USE_X_TOOLKIT
10519 else
10520 goto OTHER;
10521 #endif /* USE_X_TOOLKIT */
10522 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10524 break;
10526 case GraphicsExpose: /* This occurs when an XCopyArea's
10527 source area was obscured or not
10528 available. */
10529 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10530 if (f)
10532 expose_frame (f,
10533 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10534 event.xgraphicsexpose.width,
10535 event.xgraphicsexpose.height);
10537 #ifdef USE_X_TOOLKIT
10538 else
10539 goto OTHER;
10540 #endif /* USE_X_TOOLKIT */
10541 break;
10543 case NoExpose: /* This occurs when an XCopyArea's
10544 source area was completely
10545 available. */
10546 break;
10548 case UnmapNotify:
10549 /* Redo the mouse-highlight after the tooltip has gone. */
10550 if (event.xmap.window == tip_window)
10552 tip_window = 0;
10553 redo_mouse_highlight ();
10556 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10557 if (f) /* F may no longer exist if
10558 the frame was deleted. */
10560 /* While a frame is unmapped, display generation is
10561 disabled; you don't want to spend time updating a
10562 display that won't ever be seen. */
10563 f->async_visible = 0;
10564 /* We can't distinguish, from the event, whether the window
10565 has become iconified or invisible. So assume, if it
10566 was previously visible, than now it is iconified.
10567 But x_make_frame_invisible clears both
10568 the visible flag and the iconified flag;
10569 and that way, we know the window is not iconified now. */
10570 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10572 f->async_iconified = 1;
10574 bufp->kind = ICONIFY_EVENT;
10575 XSETFRAME (bufp->frame_or_window, f);
10576 bufp->arg = Qnil;
10577 bufp++;
10578 count++;
10579 numchars--;
10582 goto OTHER;
10584 case MapNotify:
10585 if (event.xmap.window == tip_window)
10586 /* The tooltip has been drawn already. Avoid
10587 the SET_FRAME_GARBAGED below. */
10588 goto OTHER;
10590 /* We use x_top_window_to_frame because map events can
10591 come for sub-windows and they don't mean that the
10592 frame is visible. */
10593 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10594 if (f)
10596 f->async_visible = 1;
10597 f->async_iconified = 0;
10598 f->output_data.x->has_been_visible = 1;
10600 /* wait_reading_process_input will notice this and update
10601 the frame's display structures. */
10602 SET_FRAME_GARBAGED (f);
10604 if (f->iconified)
10606 bufp->kind = DEICONIFY_EVENT;
10607 XSETFRAME (bufp->frame_or_window, f);
10608 bufp->arg = Qnil;
10609 bufp++;
10610 count++;
10611 numchars--;
10613 else if (! NILP (Vframe_list)
10614 && ! NILP (XCDR (Vframe_list)))
10615 /* Force a redisplay sooner or later
10616 to update the frame titles
10617 in case this is the second frame. */
10618 record_asynch_buffer_change ();
10620 goto OTHER;
10622 case KeyPress:
10624 /* Dispatch KeyPress events when in menu. */
10625 if (popup_activated_flag)
10626 goto OTHER;
10628 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10630 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10632 dpyinfo->mouse_face_hidden = 1;
10633 clear_mouse_face (dpyinfo);
10636 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10637 if (f == 0)
10639 /* Scroll bars consume key events, but we want
10640 the keys to go to the scroll bar's frame. */
10641 Widget widget = XtWindowToWidget (dpyinfo->display,
10642 event.xkey.window);
10643 if (widget && XmIsScrollBar (widget))
10645 widget = XtParent (widget);
10646 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10649 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10651 if (f != 0)
10653 KeySym keysym, orig_keysym;
10654 /* al%imercury@uunet.uu.net says that making this 81
10655 instead of 80 fixed a bug whereby meta chars made
10656 his Emacs hang.
10658 It seems that some version of XmbLookupString has
10659 a bug of not returning XBufferOverflow in
10660 status_return even if the input is too long to
10661 fit in 81 bytes. So, we must prepare sufficient
10662 bytes for copy_buffer. 513 bytes (256 chars for
10663 two-byte character set) seems to be a fairly good
10664 approximation. -- 2000.8.10 handa@etl.go.jp */
10665 unsigned char copy_buffer[513];
10666 unsigned char *copy_bufptr = copy_buffer;
10667 int copy_bufsiz = sizeof (copy_buffer);
10668 int modifiers;
10669 Lisp_Object coding_system = Qlatin_1;
10671 event.xkey.state
10672 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10673 extra_keyboard_modifiers);
10674 modifiers = event.xkey.state;
10676 /* This will have to go some day... */
10678 /* make_lispy_event turns chars into control chars.
10679 Don't do it here because XLookupString is too eager. */
10680 event.xkey.state &= ~ControlMask;
10681 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10682 | dpyinfo->super_mod_mask
10683 | dpyinfo->hyper_mod_mask
10684 | dpyinfo->alt_mod_mask);
10686 /* In case Meta is ComposeCharacter,
10687 clear its status. According to Markus Ehrnsperger
10688 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10689 this enables ComposeCharacter to work whether or
10690 not it is combined with Meta. */
10691 if (modifiers & dpyinfo->meta_mod_mask)
10692 bzero (&compose_status, sizeof (compose_status));
10694 #ifdef HAVE_X_I18N
10695 if (FRAME_XIC (f))
10697 Status status_return;
10699 coding_system = Vlocale_coding_system;
10700 nbytes = XmbLookupString (FRAME_XIC (f),
10701 &event.xkey, copy_bufptr,
10702 copy_bufsiz, &keysym,
10703 &status_return);
10704 if (status_return == XBufferOverflow)
10706 copy_bufsiz = nbytes + 1;
10707 copy_bufptr = (char *) alloca (copy_bufsiz);
10708 nbytes = XmbLookupString (FRAME_XIC (f),
10709 &event.xkey, copy_bufptr,
10710 copy_bufsiz, &keysym,
10711 &status_return);
10713 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10714 #if 0 && defined X_HAVE_UTF8_STRING
10715 else if (status_return == XLookupKeySym)
10716 { /* Try again but with utf-8. */
10717 coding_system = Qutf_8;
10718 nbytes = Xutf8LookupString (FRAME_XIC (f),
10719 &event.xkey, copy_bufptr,
10720 copy_bufsiz, &keysym,
10721 &status_return);
10722 if (status_return == XBufferOverflow)
10724 copy_bufsiz = nbytes + 1;
10725 copy_bufptr = (char *) alloca (copy_bufsiz);
10726 nbytes = Xutf8LookupString (FRAME_XIC (f),
10727 &event.xkey,
10728 copy_bufptr,
10729 copy_bufsiz, &keysym,
10730 &status_return);
10733 #endif
10735 if (status_return == XLookupNone)
10736 break;
10737 else if (status_return == XLookupChars)
10739 keysym = NoSymbol;
10740 modifiers = 0;
10742 else if (status_return != XLookupKeySym
10743 && status_return != XLookupBoth)
10744 abort ();
10746 else
10747 nbytes = XLookupString (&event.xkey, copy_bufptr,
10748 copy_bufsiz, &keysym,
10749 &compose_status);
10750 #else
10751 nbytes = XLookupString (&event.xkey, copy_bufptr,
10752 copy_bufsiz, &keysym,
10753 &compose_status);
10754 #endif
10756 orig_keysym = keysym;
10758 if (numchars > 1)
10760 Lisp_Object c;
10762 /* First deal with keysyms which have defined
10763 translations to characters. */
10764 if (keysym >= 32 && keysym < 128)
10765 /* Avoid explicitly decoding each ASCII character. */
10767 bufp->kind = ASCII_KEYSTROKE_EVENT;
10768 bufp->code = keysym;
10769 XSETFRAME (bufp->frame_or_window, f);
10770 bufp->arg = Qnil;
10771 bufp->modifiers
10772 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10773 modifiers);
10774 bufp->timestamp = event.xkey.time;
10775 bufp++;
10776 count++;
10777 numchars--;
10779 /* Now non-ASCII. */
10780 else if (HASH_TABLE_P (Vx_keysym_table)
10781 && (NATNUMP (c = Fgethash (make_number (keysym),
10782 Vx_keysym_table,
10783 Qnil))))
10785 bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
10786 ? ASCII_KEYSTROKE_EVENT
10787 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10788 bufp->code = XFASTINT (c);
10789 XSETFRAME (bufp->frame_or_window, f);
10790 bufp->arg = Qnil;
10791 bufp->modifiers
10792 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10793 modifiers);
10794 bufp->timestamp = event.xkey.time;
10795 bufp++;
10796 count++;
10797 numchars--;
10799 /* Random non-modifier sorts of keysyms. */
10800 else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10801 || keysym == XK_Delete
10802 #ifdef XK_ISO_Left_Tab
10803 || (keysym >= XK_ISO_Left_Tab
10804 && keysym <= XK_ISO_Enter)
10805 #endif
10806 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10807 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10808 #ifdef HPUX
10809 /* This recognizes the "extended function
10810 keys". It seems there's no cleaner way.
10811 Test IsModifierKey to avoid handling
10812 mode_switch incorrectly. */
10813 || ((unsigned) (keysym) >= XK_Select
10814 && (unsigned)(keysym) < XK_KP_Space)
10815 #endif
10816 #ifdef XK_dead_circumflex
10817 || orig_keysym == XK_dead_circumflex
10818 #endif
10819 #ifdef XK_dead_grave
10820 || orig_keysym == XK_dead_grave
10821 #endif
10822 #ifdef XK_dead_tilde
10823 || orig_keysym == XK_dead_tilde
10824 #endif
10825 #ifdef XK_dead_diaeresis
10826 || orig_keysym == XK_dead_diaeresis
10827 #endif
10828 #ifdef XK_dead_macron
10829 || orig_keysym == XK_dead_macron
10830 #endif
10831 #ifdef XK_dead_degree
10832 || orig_keysym == XK_dead_degree
10833 #endif
10834 #ifdef XK_dead_acute
10835 || orig_keysym == XK_dead_acute
10836 #endif
10837 #ifdef XK_dead_cedilla
10838 || orig_keysym == XK_dead_cedilla
10839 #endif
10840 #ifdef XK_dead_breve
10841 || orig_keysym == XK_dead_breve
10842 #endif
10843 #ifdef XK_dead_ogonek
10844 || orig_keysym == XK_dead_ogonek
10845 #endif
10846 #ifdef XK_dead_caron
10847 || orig_keysym == XK_dead_caron
10848 #endif
10849 #ifdef XK_dead_doubleacute
10850 || orig_keysym == XK_dead_doubleacute
10851 #endif
10852 #ifdef XK_dead_abovedot
10853 || orig_keysym == XK_dead_abovedot
10854 #endif
10855 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10856 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10857 /* Any "vendor-specific" key is ok. */
10858 || (orig_keysym & (1 << 28))
10859 || (keysym != NoSymbol && nbytes == 0))
10860 && ! (IsModifierKey (orig_keysym)
10861 #ifndef HAVE_X11R5
10862 #ifdef XK_Mode_switch
10863 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10864 #endif
10865 #ifdef XK_Num_Lock
10866 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10867 #endif
10868 #endif /* not HAVE_X11R5 */
10869 /* The symbols from XK_ISO_Lock
10870 to XK_ISO_Last_Group_Lock
10871 don't have real modifiers but
10872 should be treated similarly to
10873 Mode_switch by Emacs. */
10874 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10875 || ((unsigned)(orig_keysym)
10876 >= XK_ISO_Lock
10877 && (unsigned)(orig_keysym)
10878 <= XK_ISO_Last_Group_Lock)
10879 #endif
10882 if (temp_index == sizeof temp_buffer / sizeof (short))
10883 temp_index = 0;
10884 temp_buffer[temp_index++] = keysym;
10885 /* make_lispy_event will convert this to a symbolic
10886 key. */
10887 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10888 bufp->code = keysym;
10889 XSETFRAME (bufp->frame_or_window, f);
10890 bufp->arg = Qnil;
10891 bufp->modifiers
10892 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10893 modifiers);
10894 bufp->timestamp = event.xkey.time;
10895 bufp++;
10896 count++;
10897 numchars--;
10899 else if (numchars > nbytes)
10900 { /* Raw bytes, not keysym. */
10901 register int i;
10902 register int c;
10903 int nchars, len;
10905 /* The input should be decoded with `coding_system'
10906 which depends on which X*LookupString function
10907 we used just above and the locale. */
10908 setup_coding_system (coding_system, &coding);
10909 coding.src_multibyte = 0;
10910 coding.dst_multibyte = 1;
10911 /* The input is converted to events, thus we can't
10912 handle composition. Anyway, there's no XIM that
10913 gives us composition information. */
10914 coding.composing = COMPOSITION_DISABLED;
10916 for (i = 0; i < nbytes; i++)
10918 if (temp_index == (sizeof temp_buffer
10919 / sizeof (short)))
10920 temp_index = 0;
10921 temp_buffer[temp_index++] = copy_bufptr[i];
10925 /* Decode the input data. */
10926 int require;
10927 unsigned char *p;
10929 require = decoding_buffer_size (&coding, nbytes);
10930 p = (unsigned char *) alloca (require);
10931 coding.mode |= CODING_MODE_LAST_BLOCK;
10932 /* We explicitely disable composition
10933 handling because key data should
10934 not contain any composition
10935 sequence. */
10936 coding.composing = COMPOSITION_DISABLED;
10937 decode_coding (&coding, copy_bufptr, p,
10938 nbytes, require);
10939 nbytes = coding.produced;
10940 nchars = coding.produced_char;
10941 copy_bufptr = p;
10944 /* Convert the input data to a sequence of
10945 character events. */
10946 for (i = 0; i < nbytes; i += len)
10948 if (nchars == nbytes)
10949 c = copy_bufptr[i], len = 1;
10950 else
10951 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10952 nbytes - i, len);
10954 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10955 ? ASCII_KEYSTROKE_EVENT
10956 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10957 bufp->code = c;
10958 XSETFRAME (bufp->frame_or_window, f);
10959 bufp->arg = Qnil;
10960 bufp->modifiers
10961 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10962 modifiers);
10963 bufp->timestamp = event.xkey.time;
10964 bufp++;
10967 count += nchars;
10968 numchars -= nchars;
10970 if (keysym == NoSymbol)
10971 break;
10973 else
10974 abort ();
10976 else
10977 abort ();
10979 #ifdef HAVE_X_I18N
10980 /* Don't dispatch this event since XtDispatchEvent calls
10981 XFilterEvent, and two calls in a row may freeze the
10982 client. */
10983 break;
10984 #else
10985 goto OTHER;
10986 #endif
10988 case KeyRelease:
10989 #ifdef HAVE_X_I18N
10990 /* Don't dispatch this event since XtDispatchEvent calls
10991 XFilterEvent, and two calls in a row may freeze the
10992 client. */
10993 break;
10994 #else
10995 goto OTHER;
10996 #endif
10998 case EnterNotify:
11000 int n;
11002 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11003 if (n > 0)
11005 bufp += n, count += n, numchars -= n;
11008 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
11010 #if 0
11011 if (event.xcrossing.focus)
11013 /* Avoid nasty pop/raise loops. */
11014 if (f && (!(f->auto_raise)
11015 || !(f->auto_lower)
11016 || (event.xcrossing.time - enter_timestamp) > 500))
11018 x_new_focus_frame (dpyinfo, f);
11019 enter_timestamp = event.xcrossing.time;
11022 else if (f == dpyinfo->x_focus_frame)
11023 x_new_focus_frame (dpyinfo, 0);
11024 #endif
11026 /* EnterNotify counts as mouse movement,
11027 so update things that depend on mouse position. */
11028 if (f && !f->output_data.x->hourglass_p)
11029 note_mouse_movement (f, &event.xmotion);
11030 goto OTHER;
11033 case FocusIn:
11035 int n;
11037 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11038 if (n > 0)
11040 bufp += n, count += n, numchars -= n;
11044 goto OTHER;
11046 case LeaveNotify:
11048 int n;
11050 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11051 if (n > 0)
11053 bufp += n, count += n, numchars -= n;
11057 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
11058 if (f)
11060 if (f == dpyinfo->mouse_face_mouse_frame)
11062 /* If we move outside the frame, then we're
11063 certainly no longer on any text in the frame. */
11064 clear_mouse_face (dpyinfo);
11065 dpyinfo->mouse_face_mouse_frame = 0;
11068 /* Generate a nil HELP_EVENT to cancel a help-echo.
11069 Do it only if there's something to cancel.
11070 Otherwise, the startup message is cleared when
11071 the mouse leaves the frame. */
11072 if (any_help_event_p)
11074 Lisp_Object frame;
11075 int n;
11077 XSETFRAME (frame, f);
11078 help_echo = Qnil;
11079 n = gen_help_event (bufp, numchars,
11080 Qnil, frame, Qnil, Qnil, 0);
11081 bufp += n, count += n, numchars -= n;
11085 goto OTHER;
11087 case FocusOut:
11089 int n;
11091 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11092 if (n > 0)
11094 bufp += n, count += n, numchars -= n;
11098 goto OTHER;
11100 case MotionNotify:
11102 previous_help_echo = help_echo;
11103 help_echo = help_echo_object = help_echo_window = Qnil;
11104 help_echo_pos = -1;
11106 if (dpyinfo->grabbed && last_mouse_frame
11107 && FRAME_LIVE_P (last_mouse_frame))
11108 f = last_mouse_frame;
11109 else
11110 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11112 if (dpyinfo->mouse_face_hidden)
11114 dpyinfo->mouse_face_hidden = 0;
11115 clear_mouse_face (dpyinfo);
11118 if (f)
11121 /* Generate SELECT_WINDOW_EVENTs when needed. */
11122 if (mouse_autoselect_window)
11124 Lisp_Object window;
11125 int area;
11127 window = window_from_coordinates (f,
11128 event.xmotion.x, event.xmotion.y,
11129 &area, 0);
11131 /* Window will be selected only when it is not selected now and
11132 last mouse movement event was not in it. Minibuffer window
11133 will be selected iff it is active. */
11134 if (WINDOWP(window)
11135 && !EQ (window, last_window)
11136 && !EQ (window, selected_window)
11137 && numchars > 0)
11139 bufp->kind = SELECT_WINDOW_EVENT;
11140 bufp->frame_or_window = window;
11141 bufp->arg = Qnil;
11142 ++bufp, ++count, --numchars;
11145 last_window=window;
11147 note_mouse_movement (f, &event.xmotion);
11149 else
11151 #ifndef USE_TOOLKIT_SCROLL_BARS
11152 struct scroll_bar *bar
11153 = x_window_to_scroll_bar (event.xmotion.window);
11155 if (bar)
11156 x_scroll_bar_note_movement (bar, &event);
11157 #endif /* USE_TOOLKIT_SCROLL_BARS */
11159 /* If we move outside the frame, then we're
11160 certainly no longer on any text in the frame. */
11161 clear_mouse_face (dpyinfo);
11164 /* If the contents of the global variable help_echo
11165 has changed, generate a HELP_EVENT. */
11166 if (!NILP (help_echo)
11167 || !NILP (previous_help_echo))
11169 Lisp_Object frame;
11170 int n;
11172 if (f)
11173 XSETFRAME (frame, f);
11174 else
11175 frame = Qnil;
11177 any_help_event_p = 1;
11178 n = gen_help_event (bufp, numchars, help_echo, frame,
11179 help_echo_window, help_echo_object,
11180 help_echo_pos);
11181 bufp += n, count += n, numchars -= n;
11184 goto OTHER;
11187 case ConfigureNotify:
11188 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11189 if (f)
11191 #ifndef USE_X_TOOLKIT
11192 /* If there is a pending resize for fullscreen, don't
11193 do this one, the right one will come later.
11194 The toolkit version doesn't seem to need this, but we
11195 need to reset it below. */
11196 int dont_resize =
11197 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11198 && FRAME_NEW_WIDTH (f) != 0);
11199 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11200 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11201 if (dont_resize)
11202 goto OTHER;
11204 /* In the toolkit version, change_frame_size
11205 is called by the code that handles resizing
11206 of the EmacsFrame widget. */
11208 /* Even if the number of character rows and columns has
11209 not changed, the font size may have changed, so we need
11210 to check the pixel dimensions as well. */
11211 if (columns != f->width
11212 || rows != f->height
11213 || event.xconfigure.width != f->output_data.x->pixel_width
11214 || event.xconfigure.height != f->output_data.x->pixel_height)
11216 change_frame_size (f, rows, columns, 0, 1, 0);
11217 SET_FRAME_GARBAGED (f);
11218 cancel_mouse_face (f);
11220 #endif
11222 f->output_data.x->pixel_width = event.xconfigure.width;
11223 f->output_data.x->pixel_height = event.xconfigure.height;
11225 /* What we have now is the position of Emacs's own window.
11226 Convert that to the position of the window manager window. */
11227 x_real_positions (f, &f->output_data.x->left_pos,
11228 &f->output_data.x->top_pos);
11230 x_check_fullscreen_move(f);
11231 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11232 f->output_data.x->want_fullscreen &=
11233 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11234 #ifdef HAVE_X_I18N
11235 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11236 xic_set_statusarea (f);
11237 #endif
11239 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11241 /* Since the WM decorations come below top_pos now,
11242 we must put them below top_pos in the future. */
11243 f->output_data.x->win_gravity = NorthWestGravity;
11244 x_wm_set_size_hint (f, (long) 0, 0);
11247 goto OTHER;
11249 case ButtonPress:
11250 case ButtonRelease:
11252 /* If we decide we want to generate an event to be seen
11253 by the rest of Emacs, we put it here. */
11254 struct input_event emacs_event;
11255 int tool_bar_p = 0;
11257 emacs_event.kind = NO_EVENT;
11258 bzero (&compose_status, sizeof (compose_status));
11260 if (dpyinfo->grabbed
11261 && last_mouse_frame
11262 && FRAME_LIVE_P (last_mouse_frame))
11263 f = last_mouse_frame;
11264 else
11265 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11267 if (f)
11269 /* Is this in the tool-bar? */
11270 if (WINDOWP (f->tool_bar_window)
11271 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11273 Lisp_Object window;
11274 int p, x, y;
11276 x = event.xbutton.x;
11277 y = event.xbutton.y;
11279 /* Set x and y. */
11280 window = window_from_coordinates (f, x, y, &p, 1);
11281 if (EQ (window, f->tool_bar_window))
11283 x_handle_tool_bar_click (f, &event.xbutton);
11284 tool_bar_p = 1;
11288 if (!tool_bar_p)
11289 if (!dpyinfo->x_focus_frame
11290 || f == dpyinfo->x_focus_frame)
11291 construct_mouse_click (&emacs_event, &event, f);
11293 else
11295 #ifndef USE_TOOLKIT_SCROLL_BARS
11296 struct scroll_bar *bar
11297 = x_window_to_scroll_bar (event.xbutton.window);
11299 if (bar)
11300 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11301 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11304 if (event.type == ButtonPress)
11306 dpyinfo->grabbed |= (1 << event.xbutton.button);
11307 last_mouse_frame = f;
11308 /* Ignore any mouse motion that happened
11309 before this event; any subsequent mouse-movement
11310 Emacs events should reflect only motion after
11311 the ButtonPress. */
11312 if (f != 0)
11313 f->mouse_moved = 0;
11315 if (!tool_bar_p)
11316 last_tool_bar_item = -1;
11318 else
11320 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11323 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11325 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11326 bufp++;
11327 count++;
11328 numchars--;
11331 #ifdef USE_X_TOOLKIT
11332 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11333 /* For a down-event in the menu bar,
11334 don't pass it to Xt right now.
11335 Instead, save it away
11336 and we will pass it to Xt from kbd_buffer_get_event.
11337 That way, we can run some Lisp code first. */
11338 if (f && event.type == ButtonPress
11339 /* Verify the event is really within the menu bar
11340 and not just sent to it due to grabbing. */
11341 && event.xbutton.x >= 0
11342 && event.xbutton.x < f->output_data.x->pixel_width
11343 && event.xbutton.y >= 0
11344 && event.xbutton.y < f->output_data.x->menubar_height
11345 && event.xbutton.same_screen)
11347 SET_SAVED_BUTTON_EVENT;
11348 XSETFRAME (last_mouse_press_frame, f);
11350 else if (event.type == ButtonPress)
11352 last_mouse_press_frame = Qnil;
11353 goto OTHER;
11356 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11357 but I am trying to be cautious. */
11358 else if (event.type == ButtonRelease)
11360 if (!NILP (last_mouse_press_frame))
11362 f = XFRAME (last_mouse_press_frame);
11363 if (f->output_data.x)
11364 SET_SAVED_BUTTON_EVENT;
11366 else
11367 goto OTHER;
11369 #endif /* USE_MOTIF */
11370 else
11371 goto OTHER;
11372 #endif /* USE_X_TOOLKIT */
11374 break;
11376 case CirculateNotify:
11377 goto OTHER;
11379 case CirculateRequest:
11380 goto OTHER;
11382 case VisibilityNotify:
11383 goto OTHER;
11385 case MappingNotify:
11386 /* Someone has changed the keyboard mapping - update the
11387 local cache. */
11388 switch (event.xmapping.request)
11390 case MappingModifier:
11391 x_find_modifier_meanings (dpyinfo);
11392 /* This is meant to fall through. */
11393 case MappingKeyboard:
11394 XRefreshKeyboardMapping (&event.xmapping);
11396 goto OTHER;
11398 default:
11399 OTHER:
11400 #ifdef USE_X_TOOLKIT
11401 BLOCK_INPUT;
11402 XtDispatchEvent (&event);
11403 UNBLOCK_INPUT;
11404 #endif /* USE_X_TOOLKIT */
11405 break;
11410 out:;
11412 /* On some systems, an X bug causes Emacs to get no more events
11413 when the window is destroyed. Detect that. (1994.) */
11414 if (! event_found)
11416 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11417 One XNOOP in 100 loops will make Emacs terminate.
11418 B. Bretthauer, 1994 */
11419 x_noop_count++;
11420 if (x_noop_count >= 100)
11422 x_noop_count=0;
11424 if (next_noop_dpyinfo == 0)
11425 next_noop_dpyinfo = x_display_list;
11427 XNoOp (next_noop_dpyinfo->display);
11429 /* Each time we get here, cycle through the displays now open. */
11430 next_noop_dpyinfo = next_noop_dpyinfo->next;
11434 /* If the focus was just given to an auto-raising frame,
11435 raise it now. */
11436 /* ??? This ought to be able to handle more than one such frame. */
11437 if (pending_autoraise_frame)
11439 x_raise_frame (pending_autoraise_frame);
11440 pending_autoraise_frame = 0;
11443 UNBLOCK_INPUT;
11444 --handling_signal;
11445 return count;
11451 /***********************************************************************
11452 Text Cursor
11453 ***********************************************************************/
11455 /* Notice when the text cursor of window W has been completely
11456 overwritten by a drawing operation that outputs glyphs in AREA
11457 starting at X0 and ending at X1 in the line starting at Y0 and
11458 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11459 the rest of the line after X0 has been written. Y coordinates
11460 are window-relative. */
11462 static void
11463 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
11464 struct window *w;
11465 enum glyph_row_area area;
11466 int x0, y0, x1, y1;
11468 if (area == TEXT_AREA && w->phys_cursor_on_p)
11470 int cx0 = w->phys_cursor.x;
11471 int cx1 = cx0 + w->phys_cursor_width;
11472 int cy0 = w->phys_cursor.y;
11473 int cy1 = cy0 + w->phys_cursor_height;
11475 if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
11477 /* The cursor image will be completely removed from the
11478 screen if the output area intersects the cursor area in
11479 y-direction. When we draw in [y0 y1[, and some part of
11480 the cursor is at y < y0, that part must have been drawn
11481 before. When scrolling, the cursor is erased before
11482 actually scrolling, so we don't come here. When not
11483 scrolling, the rows above the old cursor row must have
11484 changed, and in this case these rows must have written
11485 over the cursor image.
11487 Likewise if part of the cursor is below y1, with the
11488 exception of the cursor being in the first blank row at
11489 the buffer and window end because update_text_area
11490 doesn't draw that row. (Except when it does, but
11491 that's handled in update_text_area.) */
11493 if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
11494 && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
11495 w->phys_cursor_on_p = 0;
11501 /* Set clipping for output in glyph row ROW. W is the window in which
11502 we operate. GC is the graphics context to set clipping in.
11503 WHOLE_LINE_P non-zero means include the areas used for truncation
11504 mark display and alike in the clipping rectangle.
11506 ROW may be a text row or, e.g., a mode line. Text rows must be
11507 clipped to the interior of the window dedicated to text display,
11508 mode lines must be clipped to the whole window. */
11510 static void
11511 x_clip_to_row (w, row, gc, whole_line_p)
11512 struct window *w;
11513 struct glyph_row *row;
11514 GC gc;
11515 int whole_line_p;
11517 struct frame *f = XFRAME (WINDOW_FRAME (w));
11518 XRectangle clip_rect;
11519 int window_x, window_y, window_width, window_height;
11521 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11523 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11524 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11525 clip_rect.y = max (clip_rect.y, window_y);
11526 clip_rect.width = window_width;
11527 clip_rect.height = row->visible_height;
11529 /* If clipping to the whole line, including trunc marks, extend
11530 the rectangle to the left and increase its width. */
11531 if (whole_line_p)
11533 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11534 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11537 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11541 /* Draw a hollow box cursor on window W in glyph row ROW. */
11543 static void
11544 x_draw_hollow_cursor (w, row)
11545 struct window *w;
11546 struct glyph_row *row;
11548 struct frame *f = XFRAME (WINDOW_FRAME (w));
11549 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11550 Display *dpy = FRAME_X_DISPLAY (f);
11551 int x, y, wd, h;
11552 XGCValues xgcv;
11553 struct glyph *cursor_glyph;
11554 GC gc;
11556 /* Compute frame-relative coordinates from window-relative
11557 coordinates. */
11558 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11559 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11560 + row->ascent - w->phys_cursor_ascent);
11561 h = row->height - 1;
11563 /* Get the glyph the cursor is on. If we can't tell because
11564 the current matrix is invalid or such, give up. */
11565 cursor_glyph = get_phys_cursor_glyph (w);
11566 if (cursor_glyph == NULL)
11567 return;
11569 /* Compute the width of the rectangle to draw. If on a stretch
11570 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11571 rectangle as wide as the glyph, but use a canonical character
11572 width instead. */
11573 wd = cursor_glyph->pixel_width - 1;
11574 if (cursor_glyph->type == STRETCH_GLYPH
11575 && !x_stretch_cursor_p)
11576 wd = min (CANON_X_UNIT (f), wd);
11577 w->phys_cursor_width = wd;
11579 /* The foreground of cursor_gc is typically the same as the normal
11580 background color, which can cause the cursor box to be invisible. */
11581 xgcv.foreground = f->output_data.x->cursor_pixel;
11582 if (dpyinfo->scratch_cursor_gc)
11583 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11584 else
11585 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11586 GCForeground, &xgcv);
11587 gc = dpyinfo->scratch_cursor_gc;
11589 /* Set clipping, draw the rectangle, and reset clipping again. */
11590 x_clip_to_row (w, row, gc, 0);
11591 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11592 XSetClipMask (dpy, gc, None);
11596 /* Draw a bar cursor on window W in glyph row ROW.
11598 Implementation note: One would like to draw a bar cursor with an
11599 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11600 Unfortunately, I didn't find a font yet that has this property set.
11601 --gerd. */
11603 static void
11604 x_draw_bar_cursor (w, row, width, kind)
11605 struct window *w;
11606 struct glyph_row *row;
11607 int width;
11608 enum text_cursor_kinds kind;
11610 struct frame *f = XFRAME (w->frame);
11611 struct glyph *cursor_glyph;
11613 /* If cursor is out of bounds, don't draw garbage. This can happen
11614 in mini-buffer windows when switching between echo area glyphs
11615 and mini-buffer. */
11616 cursor_glyph = get_phys_cursor_glyph (w);
11617 if (cursor_glyph == NULL)
11618 return;
11620 /* If on an image, draw like a normal cursor. That's usually better
11621 visible than drawing a bar, esp. if the image is large so that
11622 the bar might not be in the window. */
11623 if (cursor_glyph->type == IMAGE_GLYPH)
11625 struct glyph_row *row;
11626 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11627 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11629 else
11631 Display *dpy = FRAME_X_DISPLAY (f);
11632 Window window = FRAME_X_WINDOW (f);
11633 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11634 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11635 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11636 XGCValues xgcv;
11638 /* If the glyph's background equals the color we normally draw
11639 the bar cursor in, the bar cursor in its normal color is
11640 invisible. Use the glyph's foreground color instead in this
11641 case, on the assumption that the glyph's colors are chosen so
11642 that the glyph is legible. */
11643 if (face->background == f->output_data.x->cursor_pixel)
11644 xgcv.background = xgcv.foreground = face->foreground;
11645 else
11646 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11647 xgcv.graphics_exposures = 0;
11649 if (gc)
11650 XChangeGC (dpy, gc, mask, &xgcv);
11651 else
11653 gc = XCreateGC (dpy, window, mask, &xgcv);
11654 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11657 if (width < 0)
11658 width = FRAME_CURSOR_WIDTH (f);
11659 width = min (cursor_glyph->pixel_width, width);
11661 w->phys_cursor_width = width;
11662 x_clip_to_row (w, row, gc, 0);
11664 if (kind == BAR_CURSOR)
11665 XFillRectangle (dpy, window, gc,
11666 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11667 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11668 width, row->height);
11669 else
11670 XFillRectangle (dpy, window, gc,
11671 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11672 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
11673 row->height - width),
11674 cursor_glyph->pixel_width,
11675 width);
11677 XSetClipMask (dpy, gc, None);
11682 /* Clear the cursor of window W to background color, and mark the
11683 cursor as not shown. This is used when the text where the cursor
11684 is is about to be rewritten. */
11686 static void
11687 x_clear_cursor (w)
11688 struct window *w;
11690 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11691 x_update_window_cursor (w, 0);
11695 /* Draw the cursor glyph of window W in glyph row ROW. See the
11696 comment of x_draw_glyphs for the meaning of HL. */
11698 static void
11699 x_draw_phys_cursor_glyph (w, row, hl)
11700 struct window *w;
11701 struct glyph_row *row;
11702 enum draw_glyphs_face hl;
11704 /* If cursor hpos is out of bounds, don't draw garbage. This can
11705 happen in mini-buffer windows when switching between echo area
11706 glyphs and mini-buffer. */
11707 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11709 int on_p = w->phys_cursor_on_p;
11710 int x1;
11712 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11713 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11714 hl, 0);
11715 w->phys_cursor_on_p = on_p;
11717 if (hl == DRAW_CURSOR)
11718 w->phys_cursor_width = x1 - w->phys_cursor.x;
11720 /* When we erase the cursor, and ROW is overlapped by other
11721 rows, make sure that these overlapping parts of other rows
11722 are redrawn. */
11723 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11725 if (row > w->current_matrix->rows
11726 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11727 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11729 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11730 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11731 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11737 /* Erase the image of a cursor of window W from the screen. */
11739 static void
11740 x_erase_phys_cursor (w)
11741 struct window *w;
11743 struct frame *f = XFRAME (w->frame);
11744 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11745 int hpos = w->phys_cursor.hpos;
11746 int vpos = w->phys_cursor.vpos;
11747 int mouse_face_here_p = 0;
11748 struct glyph_matrix *active_glyphs = w->current_matrix;
11749 struct glyph_row *cursor_row;
11750 struct glyph *cursor_glyph;
11751 enum draw_glyphs_face hl;
11753 /* No cursor displayed or row invalidated => nothing to do on the
11754 screen. */
11755 if (w->phys_cursor_type == NO_CURSOR)
11756 goto mark_cursor_off;
11758 /* VPOS >= active_glyphs->nrows means that window has been resized.
11759 Don't bother to erase the cursor. */
11760 if (vpos >= active_glyphs->nrows)
11761 goto mark_cursor_off;
11763 /* If row containing cursor is marked invalid, there is nothing we
11764 can do. */
11765 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11766 if (!cursor_row->enabled_p)
11767 goto mark_cursor_off;
11769 /* If row is completely invisible, don't attempt to delete a cursor which
11770 isn't there. This can happen if cursor is at top of a window, and
11771 we switch to a buffer with a header line in that window. */
11772 if (cursor_row->visible_height <= 0)
11773 goto mark_cursor_off;
11775 /* This can happen when the new row is shorter than the old one.
11776 In this case, either x_draw_glyphs or clear_end_of_line
11777 should have cleared the cursor. Note that we wouldn't be
11778 able to erase the cursor in this case because we don't have a
11779 cursor glyph at hand. */
11780 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11781 goto mark_cursor_off;
11783 /* If the cursor is in the mouse face area, redisplay that when
11784 we clear the cursor. */
11785 if (! NILP (dpyinfo->mouse_face_window)
11786 && w == XWINDOW (dpyinfo->mouse_face_window)
11787 && (vpos > dpyinfo->mouse_face_beg_row
11788 || (vpos == dpyinfo->mouse_face_beg_row
11789 && hpos >= dpyinfo->mouse_face_beg_col))
11790 && (vpos < dpyinfo->mouse_face_end_row
11791 || (vpos == dpyinfo->mouse_face_end_row
11792 && hpos < dpyinfo->mouse_face_end_col))
11793 /* Don't redraw the cursor's spot in mouse face if it is at the
11794 end of a line (on a newline). The cursor appears there, but
11795 mouse highlighting does not. */
11796 && cursor_row->used[TEXT_AREA] > hpos)
11797 mouse_face_here_p = 1;
11799 /* Maybe clear the display under the cursor. */
11800 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11802 int x;
11803 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11805 cursor_glyph = get_phys_cursor_glyph (w);
11806 if (cursor_glyph == NULL)
11807 goto mark_cursor_off;
11809 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11811 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11813 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11814 cursor_row->y)),
11815 cursor_glyph->pixel_width,
11816 cursor_row->visible_height,
11817 False);
11820 /* Erase the cursor by redrawing the character underneath it. */
11821 if (mouse_face_here_p)
11822 hl = DRAW_MOUSE_FACE;
11823 else
11824 hl = DRAW_NORMAL_TEXT;
11825 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11827 mark_cursor_off:
11828 w->phys_cursor_on_p = 0;
11829 w->phys_cursor_type = NO_CURSOR;
11833 /* Non-zero if physical cursor of window W is within mouse face. */
11835 static int
11836 cursor_in_mouse_face_p (w)
11837 struct window *w;
11839 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11840 int in_mouse_face = 0;
11842 if (WINDOWP (dpyinfo->mouse_face_window)
11843 && XWINDOW (dpyinfo->mouse_face_window) == w)
11845 int hpos = w->phys_cursor.hpos;
11846 int vpos = w->phys_cursor.vpos;
11848 if (vpos >= dpyinfo->mouse_face_beg_row
11849 && vpos <= dpyinfo->mouse_face_end_row
11850 && (vpos > dpyinfo->mouse_face_beg_row
11851 || hpos >= dpyinfo->mouse_face_beg_col)
11852 && (vpos < dpyinfo->mouse_face_end_row
11853 || hpos < dpyinfo->mouse_face_end_col
11854 || dpyinfo->mouse_face_past_end))
11855 in_mouse_face = 1;
11858 return in_mouse_face;
11862 /* Display or clear cursor of window W. If ON is zero, clear the
11863 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11864 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11866 void
11867 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11868 struct window *w;
11869 int on, hpos, vpos, x, y;
11871 struct frame *f = XFRAME (w->frame);
11872 int new_cursor_type;
11873 int new_cursor_width;
11874 int active_cursor;
11875 struct glyph_matrix *current_glyphs;
11876 struct glyph_row *glyph_row;
11877 struct glyph *glyph;
11879 /* This is pointless on invisible frames, and dangerous on garbaged
11880 windows and frames; in the latter case, the frame or window may
11881 be in the midst of changing its size, and x and y may be off the
11882 window. */
11883 if (! FRAME_VISIBLE_P (f)
11884 || FRAME_GARBAGED_P (f)
11885 || vpos >= w->current_matrix->nrows
11886 || hpos >= w->current_matrix->matrix_w)
11887 return;
11889 /* If cursor is off and we want it off, return quickly. */
11890 if (!on && !w->phys_cursor_on_p)
11891 return;
11893 current_glyphs = w->current_matrix;
11894 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11895 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11897 /* If cursor row is not enabled, we don't really know where to
11898 display the cursor. */
11899 if (!glyph_row->enabled_p)
11901 w->phys_cursor_on_p = 0;
11902 return;
11905 xassert (interrupt_input_blocked);
11907 /* Set new_cursor_type to the cursor we want to be displayed. */
11908 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
11910 /* If cursor is currently being shown and we don't want it to be or
11911 it is in the wrong place, or the cursor type is not what we want,
11912 erase it. */
11913 if (w->phys_cursor_on_p
11914 && (!on
11915 || w->phys_cursor.x != x
11916 || w->phys_cursor.y != y
11917 || new_cursor_type != w->phys_cursor_type
11918 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
11919 && new_cursor_width != w->phys_cursor_width)))
11920 x_erase_phys_cursor (w);
11922 /* Don't check phys_cursor_on_p here because that flag is only set
11923 to zero in some cases where we know that the cursor has been
11924 completely erased, to avoid the extra work of erasing the cursor
11925 twice. In other words, phys_cursor_on_p can be 1 and the cursor
11926 still not be visible, or it has only been partly erased. */
11927 if (on)
11929 w->phys_cursor_ascent = glyph_row->ascent;
11930 w->phys_cursor_height = glyph_row->height;
11932 /* Set phys_cursor_.* before x_draw_.* is called because some
11933 of them may need the information. */
11934 w->phys_cursor.x = x;
11935 w->phys_cursor.y = glyph_row->y;
11936 w->phys_cursor.hpos = hpos;
11937 w->phys_cursor.vpos = vpos;
11938 w->phys_cursor_type = new_cursor_type;
11939 w->phys_cursor_on_p = 1;
11941 switch (new_cursor_type)
11943 case HOLLOW_BOX_CURSOR:
11944 x_draw_hollow_cursor (w, glyph_row);
11945 break;
11947 case FILLED_BOX_CURSOR:
11948 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11949 break;
11951 case BAR_CURSOR:
11952 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
11953 break;
11955 case HBAR_CURSOR:
11956 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
11957 break;
11959 case NO_CURSOR:
11960 w->phys_cursor_width = 0;
11961 break;
11963 default:
11964 abort ();
11967 #ifdef HAVE_X_I18N
11968 if (w == XWINDOW (f->selected_window))
11969 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11970 xic_set_preeditarea (w, x, y);
11971 #endif
11974 #ifndef XFlush
11975 if (updating_frame != f)
11976 XFlush (FRAME_X_DISPLAY (f));
11977 #endif
11981 /* Display the cursor on window W, or clear it. X and Y are window
11982 relative pixel coordinates. HPOS and VPOS are glyph matrix
11983 positions. If W is not the selected window, display a hollow
11984 cursor. ON non-zero means display the cursor at X, Y which
11985 correspond to HPOS, VPOS, otherwise it is cleared. */
11987 void
11988 x_display_cursor (w, on, hpos, vpos, x, y)
11989 struct window *w;
11990 int on, hpos, vpos, x, y;
11992 BLOCK_INPUT;
11993 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11994 UNBLOCK_INPUT;
11998 /* Display the cursor on window W, or clear it, according to ON_P.
11999 Don't change the cursor's position. */
12001 void
12002 x_update_cursor (f, on_p)
12003 struct frame *f;
12004 int on_p;
12006 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
12010 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
12011 in the window tree rooted at W. */
12013 static void
12014 x_update_cursor_in_window_tree (w, on_p)
12015 struct window *w;
12016 int on_p;
12018 while (w)
12020 if (!NILP (w->hchild))
12021 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
12022 else if (!NILP (w->vchild))
12023 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
12024 else
12025 x_update_window_cursor (w, on_p);
12027 w = NILP (w->next) ? 0 : XWINDOW (w->next);
12032 /* Switch the display of W's cursor on or off, according to the value
12033 of ON. */
12035 static void
12036 x_update_window_cursor (w, on)
12037 struct window *w;
12038 int on;
12040 /* Don't update cursor in windows whose frame is in the process
12041 of being deleted. */
12042 if (w->current_matrix)
12044 BLOCK_INPUT;
12045 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
12046 w->phys_cursor.x, w->phys_cursor.y);
12047 UNBLOCK_INPUT;
12054 /* Icons. */
12056 /* Make the x-window of frame F use the gnu icon bitmap. */
12059 x_bitmap_icon (f, file)
12060 struct frame *f;
12061 Lisp_Object file;
12063 int bitmap_id;
12065 if (FRAME_X_WINDOW (f) == 0)
12066 return 1;
12068 /* Free up our existing icon bitmap if any. */
12069 if (f->output_data.x->icon_bitmap > 0)
12070 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12071 f->output_data.x->icon_bitmap = 0;
12073 if (STRINGP (file))
12074 bitmap_id = x_create_bitmap_from_file (f, file);
12075 else
12077 /* Create the GNU bitmap if necessary. */
12078 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
12079 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
12080 = x_create_bitmap_from_data (f, gnu_bits,
12081 gnu_width, gnu_height);
12083 /* The first time we create the GNU bitmap,
12084 this increments the ref-count one extra time.
12085 As a result, the GNU bitmap is never freed.
12086 That way, we don't have to worry about allocating it again. */
12087 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
12089 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
12092 x_wm_set_icon_pixmap (f, bitmap_id);
12093 f->output_data.x->icon_bitmap = bitmap_id;
12095 return 0;
12099 /* Make the x-window of frame F use a rectangle with text.
12100 Use ICON_NAME as the text. */
12103 x_text_icon (f, icon_name)
12104 struct frame *f;
12105 char *icon_name;
12107 if (FRAME_X_WINDOW (f) == 0)
12108 return 1;
12110 #ifdef HAVE_X11R4
12112 XTextProperty text;
12113 text.value = (unsigned char *) icon_name;
12114 text.encoding = XA_STRING;
12115 text.format = 8;
12116 text.nitems = strlen (icon_name);
12117 #ifdef USE_X_TOOLKIT
12118 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12119 &text);
12120 #else /* not USE_X_TOOLKIT */
12121 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
12122 #endif /* not USE_X_TOOLKIT */
12124 #else /* not HAVE_X11R4 */
12125 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
12126 #endif /* not HAVE_X11R4 */
12128 if (f->output_data.x->icon_bitmap > 0)
12129 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12130 f->output_data.x->icon_bitmap = 0;
12131 x_wm_set_icon_pixmap (f, 0);
12133 return 0;
12136 #define X_ERROR_MESSAGE_SIZE 200
12138 /* If non-nil, this should be a string.
12139 It means catch X errors and store the error message in this string. */
12141 static Lisp_Object x_error_message_string;
12143 /* An X error handler which stores the error message in
12144 x_error_message_string. This is called from x_error_handler if
12145 x_catch_errors is in effect. */
12147 static void
12148 x_error_catcher (display, error)
12149 Display *display;
12150 XErrorEvent *error;
12152 XGetErrorText (display, error->error_code,
12153 SDATA (x_error_message_string),
12154 X_ERROR_MESSAGE_SIZE);
12157 /* Begin trapping X errors for display DPY. Actually we trap X errors
12158 for all displays, but DPY should be the display you are actually
12159 operating on.
12161 After calling this function, X protocol errors no longer cause
12162 Emacs to exit; instead, they are recorded in the string
12163 stored in x_error_message_string.
12165 Calling x_check_errors signals an Emacs error if an X error has
12166 occurred since the last call to x_catch_errors or x_check_errors.
12168 Calling x_uncatch_errors resumes the normal error handling. */
12170 void x_check_errors ();
12171 static Lisp_Object x_catch_errors_unwind ();
12174 x_catch_errors (dpy)
12175 Display *dpy;
12177 int count = SPECPDL_INDEX ();
12179 /* Make sure any errors from previous requests have been dealt with. */
12180 XSync (dpy, False);
12182 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
12184 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
12185 SSET (x_error_message_string, 0, 0);
12187 return count;
12190 /* Unbind the binding that we made to check for X errors. */
12192 static Lisp_Object
12193 x_catch_errors_unwind (old_val)
12194 Lisp_Object old_val;
12196 x_error_message_string = old_val;
12197 return Qnil;
12200 /* If any X protocol errors have arrived since the last call to
12201 x_catch_errors or x_check_errors, signal an Emacs error using
12202 sprintf (a buffer, FORMAT, the x error message text) as the text. */
12204 void
12205 x_check_errors (dpy, format)
12206 Display *dpy;
12207 char *format;
12209 /* Make sure to catch any errors incurred so far. */
12210 XSync (dpy, False);
12212 if (SREF (x_error_message_string, 0))
12213 error (format, SDATA (x_error_message_string));
12216 /* Nonzero if we had any X protocol errors
12217 since we did x_catch_errors on DPY. */
12220 x_had_errors_p (dpy)
12221 Display *dpy;
12223 /* Make sure to catch any errors incurred so far. */
12224 XSync (dpy, False);
12226 return SREF (x_error_message_string, 0) != 0;
12229 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
12231 void
12232 x_clear_errors (dpy)
12233 Display *dpy;
12235 SSET (x_error_message_string, 0, 0);
12238 /* Stop catching X protocol errors and let them make Emacs die.
12239 DPY should be the display that was passed to x_catch_errors.
12240 COUNT should be the value that was returned by
12241 the corresponding call to x_catch_errors. */
12243 void
12244 x_uncatch_errors (dpy, count)
12245 Display *dpy;
12246 int count;
12248 unbind_to (count, Qnil);
12251 #if 0
12252 static unsigned int x_wire_count;
12253 x_trace_wire ()
12255 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
12257 #endif /* ! 0 */
12260 /* Handle SIGPIPE, which can happen when the connection to a server
12261 simply goes away. SIGPIPE is handled by x_connection_signal.
12262 Don't need to do anything, because the write which caused the
12263 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12264 which will do the appropriate cleanup for us. */
12266 static SIGTYPE
12267 x_connection_signal (signalnum) /* If we don't have an argument, */
12268 int signalnum; /* some compilers complain in signal calls. */
12270 #ifdef USG
12271 /* USG systems forget handlers when they are used;
12272 must reestablish each time */
12273 signal (signalnum, x_connection_signal);
12274 #endif /* USG */
12278 /************************************************************************
12279 Handling X errors
12280 ************************************************************************/
12282 /* Error message passed to x_connection_closed. */
12284 static char *error_msg;
12286 /* Function installed as fatal_error_signal_hook in
12287 x_connection_closed. Print the X error message, and exit normally,
12288 instead of dumping core when XtCloseDisplay fails. */
12290 static void
12291 x_fatal_error_signal ()
12293 fprintf (stderr, "%s\n", error_msg);
12294 exit (70);
12297 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12298 the text of an error message that lead to the connection loss. */
12300 static SIGTYPE
12301 x_connection_closed (dpy, error_message)
12302 Display *dpy;
12303 char *error_message;
12305 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
12306 Lisp_Object frame, tail;
12307 int count;
12309 error_msg = (char *) alloca (strlen (error_message) + 1);
12310 strcpy (error_msg, error_message);
12311 handling_signal = 0;
12313 /* Prevent being called recursively because of an error condition
12314 below. Otherwise, we might end up with printing ``can't find per
12315 display information'' in the recursive call instead of printing
12316 the original message here. */
12317 count = x_catch_errors (dpy);
12319 /* We have to close the display to inform Xt that it doesn't
12320 exist anymore. If we don't, Xt will continue to wait for
12321 events from the display. As a consequence, a sequence of
12323 M-x make-frame-on-display RET :1 RET
12324 ...kill the new frame, so that we get an IO error...
12325 M-x make-frame-on-display RET :1 RET
12327 will indefinitely wait in Xt for events for display `:1', opened
12328 in the first class to make-frame-on-display.
12330 Closing the display is reported to lead to a bus error on
12331 OpenWindows in certain situations. I suspect that is a bug
12332 in OpenWindows. I don't know how to cicumvent it here. */
12334 #ifdef USE_X_TOOLKIT
12335 /* If DPYINFO is null, this means we didn't open the display
12336 in the first place, so don't try to close it. */
12337 if (dpyinfo)
12339 extern void (*fatal_error_signal_hook) P_ ((void));
12340 fatal_error_signal_hook = x_fatal_error_signal;
12341 XtCloseDisplay (dpy);
12342 fatal_error_signal_hook = NULL;
12344 #endif
12346 /* Indicate that this display is dead. */
12347 if (dpyinfo)
12348 dpyinfo->display = 0;
12350 /* First delete frames whose mini-buffers are on frames
12351 that are on the dead display. */
12352 FOR_EACH_FRAME (tail, frame)
12354 Lisp_Object minibuf_frame;
12355 minibuf_frame
12356 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
12357 if (FRAME_X_P (XFRAME (frame))
12358 && FRAME_X_P (XFRAME (minibuf_frame))
12359 && ! EQ (frame, minibuf_frame)
12360 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
12361 Fdelete_frame (frame, Qt);
12364 /* Now delete all remaining frames on the dead display.
12365 We are now sure none of these is used as the mini-buffer
12366 for another frame that we need to delete. */
12367 FOR_EACH_FRAME (tail, frame)
12368 if (FRAME_X_P (XFRAME (frame))
12369 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12371 /* Set this to t so that Fdelete_frame won't get confused
12372 trying to find a replacement. */
12373 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12374 Fdelete_frame (frame, Qt);
12377 if (dpyinfo)
12378 x_delete_display (dpyinfo);
12380 x_uncatch_errors (dpy, count);
12382 if (x_display_list == 0)
12384 fprintf (stderr, "%s\n", error_msg);
12385 shut_down_emacs (0, 0, Qnil);
12386 exit (70);
12389 /* Ordinary stack unwind doesn't deal with these. */
12390 #ifdef SIGIO
12391 sigunblock (sigmask (SIGIO));
12392 #endif
12393 sigunblock (sigmask (SIGALRM));
12394 TOTALLY_UNBLOCK_INPUT;
12396 clear_waiting_for_input ();
12397 error ("%s", error_msg);
12401 /* This is the usual handler for X protocol errors.
12402 It kills all frames on the display that we got the error for.
12403 If that was the only one, it prints an error message and kills Emacs. */
12405 static void
12406 x_error_quitter (display, error)
12407 Display *display;
12408 XErrorEvent *error;
12410 char buf[256], buf1[356];
12412 /* Note that there is no real way portable across R3/R4 to get the
12413 original error handler. */
12415 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12416 sprintf (buf1, "X protocol error: %s on protocol request %d",
12417 buf, error->request_code);
12418 x_connection_closed (display, buf1);
12422 /* This is the first-level handler for X protocol errors.
12423 It calls x_error_quitter or x_error_catcher. */
12425 static int
12426 x_error_handler (display, error)
12427 Display *display;
12428 XErrorEvent *error;
12430 if (! NILP (x_error_message_string))
12431 x_error_catcher (display, error);
12432 else
12433 x_error_quitter (display, error);
12434 return 0;
12437 /* This is the handler for X IO errors, always.
12438 It kills all frames on the display that we lost touch with.
12439 If that was the only one, it prints an error message and kills Emacs. */
12441 static int
12442 x_io_error_quitter (display)
12443 Display *display;
12445 char buf[256];
12447 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12448 x_connection_closed (display, buf);
12449 return 0;
12452 /* Changing the font of the frame. */
12454 /* Give frame F the font named FONTNAME as its default font, and
12455 return the full name of that font. FONTNAME may be a wildcard
12456 pattern; in that case, we choose some font that fits the pattern.
12457 The return value shows which font we chose. */
12459 Lisp_Object
12460 x_new_font (f, fontname)
12461 struct frame *f;
12462 register char *fontname;
12464 struct font_info *fontp
12465 = FS_LOAD_FONT (f, 0, fontname, -1);
12467 if (!fontp)
12468 return Qnil;
12470 f->output_data.x->font = (XFontStruct *) (fontp->font);
12471 f->output_data.x->baseline_offset = fontp->baseline_offset;
12472 f->output_data.x->fontset = -1;
12474 x_compute_fringe_widths (f, 1);
12476 /* Compute the scroll bar width in character columns. */
12477 if (f->scroll_bar_pixel_width > 0)
12479 int wid = FONT_WIDTH (f->output_data.x->font);
12480 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12482 else
12484 int wid = FONT_WIDTH (f->output_data.x->font);
12485 f->scroll_bar_cols = (14 + wid - 1) / wid;
12488 /* Now make the frame display the given font. */
12489 if (FRAME_X_WINDOW (f) != 0)
12491 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12492 f->output_data.x->font->fid);
12493 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12494 f->output_data.x->font->fid);
12495 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12496 f->output_data.x->font->fid);
12498 frame_update_line_height (f);
12500 /* Don't change the size of a tip frame; there's no point in
12501 doing it because it's done in Fx_show_tip, and it leads to
12502 problems because the tip frame has no widget. */
12503 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12504 x_set_window_size (f, 0, f->width, f->height);
12506 else
12507 /* If we are setting a new frame's font for the first time,
12508 there are no faces yet, so this font's height is the line height. */
12509 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12511 return build_string (fontp->full_name);
12514 /* Give frame F the fontset named FONTSETNAME as its default font, and
12515 return the full name of that fontset. FONTSETNAME may be a wildcard
12516 pattern; in that case, we choose some fontset that fits the pattern.
12517 The return value shows which fontset we chose. */
12519 Lisp_Object
12520 x_new_fontset (f, fontsetname)
12521 struct frame *f;
12522 char *fontsetname;
12524 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12525 Lisp_Object result;
12527 if (fontset < 0)
12528 return Qnil;
12530 if (f->output_data.x->fontset == fontset)
12531 /* This fontset is already set in frame F. There's nothing more
12532 to do. */
12533 return fontset_name (fontset);
12535 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
12537 if (!STRINGP (result))
12538 /* Can't load ASCII font. */
12539 return Qnil;
12541 /* Since x_new_font doesn't update any fontset information, do it now. */
12542 f->output_data.x->fontset = fontset;
12544 #ifdef HAVE_X_I18N
12545 if (FRAME_XIC (f)
12546 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12547 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
12548 #endif
12550 return build_string (fontsetname);
12553 /* Compute actual fringe widths */
12555 void
12556 x_compute_fringe_widths (f, redraw)
12557 struct frame *f;
12558 int redraw;
12560 int o_left = f->output_data.x->left_fringe_width;
12561 int o_right = f->output_data.x->right_fringe_width;
12562 int o_cols = f->output_data.x->fringe_cols;
12564 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12565 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12566 int left_fringe_width, right_fringe_width;
12568 if (!NILP (left_fringe))
12569 left_fringe = Fcdr (left_fringe);
12570 if (!NILP (right_fringe))
12571 right_fringe = Fcdr (right_fringe);
12573 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12574 XINT (left_fringe));
12575 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12576 XINT (right_fringe));
12578 if (left_fringe_width || right_fringe_width)
12580 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12581 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12582 int conf_wid = left_wid + right_wid;
12583 int font_wid = FONT_WIDTH (f->output_data.x->font);
12584 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12585 int real_wid = cols * font_wid;
12586 if (left_wid && right_wid)
12588 if (left_fringe_width < 0)
12590 /* Left fringe width is fixed, adjust right fringe if necessary */
12591 f->output_data.x->left_fringe_width = left_wid;
12592 f->output_data.x->right_fringe_width = real_wid - left_wid;
12594 else if (right_fringe_width < 0)
12596 /* Right fringe width is fixed, adjust left fringe if necessary */
12597 f->output_data.x->left_fringe_width = real_wid - right_wid;
12598 f->output_data.x->right_fringe_width = right_wid;
12600 else
12602 /* Adjust both fringes with an equal amount.
12603 Note that we are doing integer arithmetic here, so don't
12604 lose a pixel if the total width is an odd number. */
12605 int fill = real_wid - conf_wid;
12606 f->output_data.x->left_fringe_width = left_wid + fill/2;
12607 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12610 else if (left_fringe_width)
12612 f->output_data.x->left_fringe_width = real_wid;
12613 f->output_data.x->right_fringe_width = 0;
12615 else
12617 f->output_data.x->left_fringe_width = 0;
12618 f->output_data.x->right_fringe_width = real_wid;
12620 f->output_data.x->fringe_cols = cols;
12621 f->output_data.x->fringes_extra = real_wid;
12623 else
12625 f->output_data.x->left_fringe_width = 0;
12626 f->output_data.x->right_fringe_width = 0;
12627 f->output_data.x->fringe_cols = 0;
12628 f->output_data.x->fringes_extra = 0;
12631 if (redraw && FRAME_VISIBLE_P (f))
12632 if (o_left != f->output_data.x->left_fringe_width ||
12633 o_right != f->output_data.x->right_fringe_width ||
12634 o_cols != f->output_data.x->fringe_cols)
12635 redraw_frame (f);
12638 /***********************************************************************
12639 X Input Methods
12640 ***********************************************************************/
12642 #ifdef HAVE_X_I18N
12644 #ifdef HAVE_X11R6
12646 /* XIM destroy callback function, which is called whenever the
12647 connection to input method XIM dies. CLIENT_DATA contains a
12648 pointer to the x_display_info structure corresponding to XIM. */
12650 static void
12651 xim_destroy_callback (xim, client_data, call_data)
12652 XIM xim;
12653 XPointer client_data;
12654 XPointer call_data;
12656 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12657 Lisp_Object frame, tail;
12659 BLOCK_INPUT;
12661 /* No need to call XDestroyIC.. */
12662 FOR_EACH_FRAME (tail, frame)
12664 struct frame *f = XFRAME (frame);
12665 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12667 FRAME_XIC (f) = NULL;
12668 if (FRAME_XIC_FONTSET (f))
12670 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12671 FRAME_XIC_FONTSET (f) = NULL;
12676 /* No need to call XCloseIM. */
12677 dpyinfo->xim = NULL;
12678 XFree (dpyinfo->xim_styles);
12679 UNBLOCK_INPUT;
12682 #endif /* HAVE_X11R6 */
12684 #ifdef HAVE_X11R6
12685 /* This isn't prototyped in OSF 5.0 or 5.1a. */
12686 extern char *XSetIMValues P_ ((XIM, ...));
12687 #endif
12689 /* Open the connection to the XIM server on display DPYINFO.
12690 RESOURCE_NAME is the resource name Emacs uses. */
12692 static void
12693 xim_open_dpy (dpyinfo, resource_name)
12694 struct x_display_info *dpyinfo;
12695 char *resource_name;
12697 #ifdef USE_XIM
12698 XIM xim;
12700 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12701 dpyinfo->xim = xim;
12703 if (xim)
12705 #ifdef HAVE_X11R6
12706 XIMCallback destroy;
12707 #endif
12709 /* Get supported styles and XIM values. */
12710 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12712 #ifdef HAVE_X11R6
12713 destroy.callback = xim_destroy_callback;
12714 destroy.client_data = (XPointer)dpyinfo;
12715 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12716 #endif
12719 #else /* not USE_XIM */
12720 dpyinfo->xim = NULL;
12721 #endif /* not USE_XIM */
12725 #ifdef HAVE_X11R6_XIM
12727 struct xim_inst_t
12729 struct x_display_info *dpyinfo;
12730 char *resource_name;
12733 /* XIM instantiate callback function, which is called whenever an XIM
12734 server is available. DISPLAY is teh display of the XIM.
12735 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12736 when the callback was registered. */
12738 static void
12739 xim_instantiate_callback (display, client_data, call_data)
12740 Display *display;
12741 XPointer client_data;
12742 XPointer call_data;
12744 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12745 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12747 /* We don't support multiple XIM connections. */
12748 if (dpyinfo->xim)
12749 return;
12751 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12753 /* Create XIC for the existing frames on the same display, as long
12754 as they have no XIC. */
12755 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12757 Lisp_Object tail, frame;
12759 BLOCK_INPUT;
12760 FOR_EACH_FRAME (tail, frame)
12762 struct frame *f = XFRAME (frame);
12764 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12765 if (FRAME_XIC (f) == NULL)
12767 create_frame_xic (f);
12768 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12769 xic_set_statusarea (f);
12770 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12772 struct window *w = XWINDOW (f->selected_window);
12773 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12778 UNBLOCK_INPUT;
12782 #endif /* HAVE_X11R6_XIM */
12785 /* Open a connection to the XIM server on display DPYINFO.
12786 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12787 connection only at the first time. On X11R6, open the connection
12788 in the XIM instantiate callback function. */
12790 static void
12791 xim_initialize (dpyinfo, resource_name)
12792 struct x_display_info *dpyinfo;
12793 char *resource_name;
12795 #ifdef USE_XIM
12796 #ifdef HAVE_X11R6_XIM
12797 struct xim_inst_t *xim_inst;
12798 int len;
12800 dpyinfo->xim = NULL;
12801 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12802 xim_inst->dpyinfo = dpyinfo;
12803 len = strlen (resource_name);
12804 xim_inst->resource_name = (char *) xmalloc (len + 1);
12805 bcopy (resource_name, xim_inst->resource_name, len + 1);
12806 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12807 resource_name, EMACS_CLASS,
12808 xim_instantiate_callback,
12809 /* Fixme: This is XPointer in
12810 XFree86 but (XPointer *) on
12811 Tru64, at least. */
12812 (XPointer) xim_inst);
12813 #else /* not HAVE_X11R6_XIM */
12814 dpyinfo->xim = NULL;
12815 xim_open_dpy (dpyinfo, resource_name);
12816 #endif /* not HAVE_X11R6_XIM */
12818 #else /* not USE_XIM */
12819 dpyinfo->xim = NULL;
12820 #endif /* not USE_XIM */
12824 /* Close the connection to the XIM server on display DPYINFO. */
12826 static void
12827 xim_close_dpy (dpyinfo)
12828 struct x_display_info *dpyinfo;
12830 #ifdef USE_XIM
12831 #ifdef HAVE_X11R6_XIM
12832 if (dpyinfo->display)
12833 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12834 NULL, EMACS_CLASS,
12835 xim_instantiate_callback, NULL);
12836 #endif /* not HAVE_X11R6_XIM */
12837 if (dpyinfo->display)
12838 XCloseIM (dpyinfo->xim);
12839 dpyinfo->xim = NULL;
12840 XFree (dpyinfo->xim_styles);
12841 #endif /* USE_XIM */
12844 #endif /* not HAVE_X11R6_XIM */
12848 /* Calculate the absolute position in frame F
12849 from its current recorded position values and gravity. */
12851 void
12852 x_calc_absolute_position (f)
12853 struct frame *f;
12855 Window child;
12856 int win_x = 0, win_y = 0;
12857 int flags = f->output_data.x->size_hint_flags;
12858 int this_window;
12860 /* We have nothing to do if the current position
12861 is already for the top-left corner. */
12862 if (! ((flags & XNegative) || (flags & YNegative)))
12863 return;
12865 #ifdef USE_X_TOOLKIT
12866 this_window = XtWindow (f->output_data.x->widget);
12867 #else
12868 this_window = FRAME_X_WINDOW (f);
12869 #endif
12871 /* Find the position of the outside upper-left corner of
12872 the inner window, with respect to the outer window.
12873 But do this only if we will need the results. */
12874 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12876 int count;
12878 BLOCK_INPUT;
12879 count = x_catch_errors (FRAME_X_DISPLAY (f));
12880 while (1)
12882 x_clear_errors (FRAME_X_DISPLAY (f));
12883 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12885 /* From-window, to-window. */
12886 this_window,
12887 f->output_data.x->parent_desc,
12889 /* From-position, to-position. */
12890 0, 0, &win_x, &win_y,
12892 /* Child of win. */
12893 &child);
12894 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12896 Window newroot, newparent = 0xdeadbeef;
12897 Window *newchildren;
12898 unsigned int nchildren;
12900 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12901 &newparent, &newchildren, &nchildren))
12902 break;
12904 XFree ((char *) newchildren);
12906 f->output_data.x->parent_desc = newparent;
12908 else
12909 break;
12912 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12913 UNBLOCK_INPUT;
12916 /* Treat negative positions as relative to the leftmost bottommost
12917 position that fits on the screen. */
12918 if (flags & XNegative)
12919 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12920 - 2 * f->output_data.x->border_width - win_x
12921 - PIXEL_WIDTH (f)
12922 + f->output_data.x->left_pos);
12925 int height = PIXEL_HEIGHT (f);
12927 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12928 /* Something is fishy here. When using Motif, starting Emacs with
12929 `-g -0-0', the frame appears too low by a few pixels.
12931 This seems to be so because initially, while Emacs is starting,
12932 the column widget's height and the frame's pixel height are
12933 different. The column widget's height is the right one. In
12934 later invocations, when Emacs is up, the frame's pixel height
12935 is right, though.
12937 It's not obvious where the initial small difference comes from.
12938 2000-12-01, gerd. */
12940 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12941 #endif
12943 if (flags & YNegative)
12944 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12945 - 2 * f->output_data.x->border_width
12946 - win_y
12947 - height
12948 + f->output_data.x->top_pos);
12951 /* The left_pos and top_pos
12952 are now relative to the top and left screen edges,
12953 so the flags should correspond. */
12954 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12957 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12958 to really change the position, and 0 when calling from
12959 x_make_frame_visible (in that case, XOFF and YOFF are the current
12960 position values). It is -1 when calling from x_set_frame_parameters,
12961 which means, do adjust for borders but don't change the gravity. */
12963 void
12964 x_set_offset (f, xoff, yoff, change_gravity)
12965 struct frame *f;
12966 register int xoff, yoff;
12967 int change_gravity;
12969 int modified_top, modified_left;
12971 if (change_gravity > 0)
12973 f->output_data.x->top_pos = yoff;
12974 f->output_data.x->left_pos = xoff;
12975 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12976 if (xoff < 0)
12977 f->output_data.x->size_hint_flags |= XNegative;
12978 if (yoff < 0)
12979 f->output_data.x->size_hint_flags |= YNegative;
12980 f->output_data.x->win_gravity = NorthWestGravity;
12982 x_calc_absolute_position (f);
12984 BLOCK_INPUT;
12985 x_wm_set_size_hint (f, (long) 0, 0);
12987 modified_left = f->output_data.x->left_pos;
12988 modified_top = f->output_data.x->top_pos;
12989 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12990 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12991 /* It is a mystery why we need to add the border_width here
12992 when the frame is already visible, but experiment says we do. */
12993 if (change_gravity != 0)
12995 modified_left += f->output_data.x->border_width;
12996 modified_top += f->output_data.x->border_width;
12998 #endif
13000 #ifdef USE_X_TOOLKIT
13001 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
13002 modified_left, modified_top);
13003 #else /* not USE_X_TOOLKIT */
13004 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13005 modified_left, modified_top);
13006 #endif /* not USE_X_TOOLKIT */
13007 UNBLOCK_INPUT;
13010 /* Check if we need to resize the frame due to a fullscreen request.
13011 If so needed, resize the frame. */
13012 static void
13013 x_check_fullscreen (f)
13014 struct frame *f;
13016 if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
13018 int width, height, ign;
13020 x_real_positions (f, &f->output_data.x->left_pos,
13021 &f->output_data.x->top_pos);
13023 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
13025 /* We do not need to move the window, it shall be taken care of
13026 when setting WM manager hints.
13027 If the frame is visible already, the position is checked by
13028 x_check_fullscreen_move. */
13029 if (f->width != width || f->height != height)
13031 change_frame_size (f, height, width, 0, 1, 0);
13032 SET_FRAME_GARBAGED (f);
13033 cancel_mouse_face (f);
13035 /* Wait for the change of frame size to occur */
13036 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
13042 /* If frame parameters are set after the frame is mapped, we need to move
13043 the window. This is done in xfns.c.
13044 Some window managers moves the window to the right position, some
13045 moves the outer window manager window to the specified position.
13046 Here we check that we are in the right spot. If not, make a second
13047 move, assuming we are dealing with the second kind of window manager. */
13048 static void
13049 x_check_fullscreen_move (f)
13050 struct frame *f;
13052 if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
13054 int expect_top = f->output_data.x->top_pos;
13055 int expect_left = f->output_data.x->left_pos;
13057 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13058 expect_top = 0;
13059 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13060 expect_left = 0;
13062 if (expect_top != f->output_data.x->top_pos
13063 || expect_left != f->output_data.x->left_pos)
13064 x_set_offset (f, expect_left, expect_top, 1);
13066 /* Just do this once */
13067 f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
13072 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
13073 wanted positions of the WM window (not emacs window).
13074 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
13075 window (FRAME_X_WINDOW).
13077 void
13078 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
13079 struct frame *f;
13080 int *width;
13081 int *height;
13082 int *top_pos;
13083 int *left_pos;
13085 int newwidth = f->width, newheight = f->height;
13087 *top_pos = f->output_data.x->top_pos;
13088 *left_pos = f->output_data.x->left_pos;
13090 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13092 int ph;
13094 ph = FRAME_X_DISPLAY_INFO (f)->height;
13095 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13096 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
13097 - f->output_data.x->y_pixels_diff;
13098 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13099 *top_pos = 0;
13102 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13104 int pw;
13106 pw = FRAME_X_DISPLAY_INFO (f)->width;
13107 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13108 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
13109 - f->output_data.x->x_pixels_diff;
13110 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13111 *left_pos = 0;
13114 *width = newwidth;
13115 *height = newheight;
13119 /* Change the size of frame F's X window to COLS/ROWS in the case F
13120 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
13121 top-left-corner window gravity for this size change and subsequent
13122 size changes. Otherwise we leave the window gravity unchanged. */
13124 static void
13125 x_set_window_size_1 (f, change_gravity, cols, rows)
13126 struct frame *f;
13127 int change_gravity;
13128 int cols, rows;
13130 int pixelwidth, pixelheight;
13132 check_frame_size (f, &rows, &cols);
13133 f->output_data.x->vertical_scroll_bar_extra
13134 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
13136 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
13137 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
13138 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
13140 x_compute_fringe_widths (f, 0);
13142 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
13143 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
13145 f->output_data.x->win_gravity = NorthWestGravity;
13146 x_wm_set_size_hint (f, (long) 0, 0);
13148 XSync (FRAME_X_DISPLAY (f), False);
13149 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13150 pixelwidth, pixelheight);
13152 /* Now, strictly speaking, we can't be sure that this is accurate,
13153 but the window manager will get around to dealing with the size
13154 change request eventually, and we'll hear how it went when the
13155 ConfigureNotify event gets here.
13157 We could just not bother storing any of this information here,
13158 and let the ConfigureNotify event set everything up, but that
13159 might be kind of confusing to the Lisp code, since size changes
13160 wouldn't be reported in the frame parameters until some random
13161 point in the future when the ConfigureNotify event arrives.
13163 We pass 1 for DELAY since we can't run Lisp code inside of
13164 a BLOCK_INPUT. */
13165 change_frame_size (f, rows, cols, 0, 1, 0);
13166 PIXEL_WIDTH (f) = pixelwidth;
13167 PIXEL_HEIGHT (f) = pixelheight;
13169 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
13170 receive in the ConfigureNotify event; if we get what we asked
13171 for, then the event won't cause the screen to become garbaged, so
13172 we have to make sure to do it here. */
13173 SET_FRAME_GARBAGED (f);
13175 XFlush (FRAME_X_DISPLAY (f));
13179 /* Call this to change the size of frame F's x-window.
13180 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
13181 for this size change and subsequent size changes.
13182 Otherwise we leave the window gravity unchanged. */
13184 void
13185 x_set_window_size (f, change_gravity, cols, rows)
13186 struct frame *f;
13187 int change_gravity;
13188 int cols, rows;
13190 BLOCK_INPUT;
13192 #ifdef USE_X_TOOLKIT
13194 if (f->output_data.x->widget != NULL)
13196 /* The x and y position of the widget is clobbered by the
13197 call to XtSetValues within EmacsFrameSetCharSize.
13198 This is a real kludge, but I don't understand Xt so I can't
13199 figure out a correct fix. Can anyone else tell me? -- rms. */
13200 int xpos = f->output_data.x->widget->core.x;
13201 int ypos = f->output_data.x->widget->core.y;
13202 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
13203 f->output_data.x->widget->core.x = xpos;
13204 f->output_data.x->widget->core.y = ypos;
13206 else
13207 x_set_window_size_1 (f, change_gravity, cols, rows);
13209 #else /* not USE_X_TOOLKIT */
13211 x_set_window_size_1 (f, change_gravity, cols, rows);
13213 #endif /* not USE_X_TOOLKIT */
13215 /* If cursor was outside the new size, mark it as off. */
13216 mark_window_cursors_off (XWINDOW (f->root_window));
13218 /* Clear out any recollection of where the mouse highlighting was,
13219 since it might be in a place that's outside the new frame size.
13220 Actually checking whether it is outside is a pain in the neck,
13221 so don't try--just let the highlighting be done afresh with new size. */
13222 cancel_mouse_face (f);
13224 UNBLOCK_INPUT;
13227 /* Mouse warping. */
13229 void
13230 x_set_mouse_position (f, x, y)
13231 struct frame *f;
13232 int x, y;
13234 int pix_x, pix_y;
13236 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
13237 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
13239 if (pix_x < 0) pix_x = 0;
13240 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
13242 if (pix_y < 0) pix_y = 0;
13243 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
13245 BLOCK_INPUT;
13247 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13248 0, 0, 0, 0, pix_x, pix_y);
13249 UNBLOCK_INPUT;
13252 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13254 void
13255 x_set_mouse_pixel_position (f, pix_x, pix_y)
13256 struct frame *f;
13257 int pix_x, pix_y;
13259 BLOCK_INPUT;
13261 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13262 0, 0, 0, 0, pix_x, pix_y);
13263 UNBLOCK_INPUT;
13266 /* focus shifting, raising and lowering. */
13268 void
13269 x_focus_on_frame (f)
13270 struct frame *f;
13272 #if 0 /* This proves to be unpleasant. */
13273 x_raise_frame (f);
13274 #endif
13275 #if 0
13276 /* I don't think that the ICCCM allows programs to do things like this
13277 without the interaction of the window manager. Whatever you end up
13278 doing with this code, do it to x_unfocus_frame too. */
13279 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13280 RevertToPointerRoot, CurrentTime);
13281 #endif /* ! 0 */
13284 void
13285 x_unfocus_frame (f)
13286 struct frame *f;
13288 #if 0
13289 /* Look at the remarks in x_focus_on_frame. */
13290 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
13291 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
13292 RevertToPointerRoot, CurrentTime);
13293 #endif /* ! 0 */
13296 /* Raise frame F. */
13298 void
13299 x_raise_frame (f)
13300 struct frame *f;
13302 if (f->async_visible)
13304 BLOCK_INPUT;
13305 #ifdef USE_X_TOOLKIT
13306 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13307 #else /* not USE_X_TOOLKIT */
13308 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13309 #endif /* not USE_X_TOOLKIT */
13310 XFlush (FRAME_X_DISPLAY (f));
13311 UNBLOCK_INPUT;
13315 /* Lower frame F. */
13317 void
13318 x_lower_frame (f)
13319 struct frame *f;
13321 if (f->async_visible)
13323 BLOCK_INPUT;
13324 #ifdef USE_X_TOOLKIT
13325 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13326 #else /* not USE_X_TOOLKIT */
13327 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13328 #endif /* not USE_X_TOOLKIT */
13329 XFlush (FRAME_X_DISPLAY (f));
13330 UNBLOCK_INPUT;
13334 static void
13335 XTframe_raise_lower (f, raise_flag)
13336 FRAME_PTR f;
13337 int raise_flag;
13339 if (raise_flag)
13340 x_raise_frame (f);
13341 else
13342 x_lower_frame (f);
13345 /* Change of visibility. */
13347 /* This tries to wait until the frame is really visible.
13348 However, if the window manager asks the user where to position
13349 the frame, this will return before the user finishes doing that.
13350 The frame will not actually be visible at that time,
13351 but it will become visible later when the window manager
13352 finishes with it. */
13354 void
13355 x_make_frame_visible (f)
13356 struct frame *f;
13358 Lisp_Object type;
13359 int original_top, original_left;
13360 int retry_count = 2;
13362 retry:
13364 BLOCK_INPUT;
13366 type = x_icon_type (f);
13367 if (!NILP (type))
13368 x_bitmap_icon (f, type);
13370 if (! FRAME_VISIBLE_P (f))
13372 /* We test FRAME_GARBAGED_P here to make sure we don't
13373 call x_set_offset a second time
13374 if we get to x_make_frame_visible a second time
13375 before the window gets really visible. */
13376 if (! FRAME_ICONIFIED_P (f)
13377 && ! f->output_data.x->asked_for_visible)
13378 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13380 f->output_data.x->asked_for_visible = 1;
13382 if (! EQ (Vx_no_window_manager, Qt))
13383 x_wm_set_window_state (f, NormalState);
13384 #ifdef USE_X_TOOLKIT
13385 /* This was XtPopup, but that did nothing for an iconified frame. */
13386 XtMapWidget (f->output_data.x->widget);
13387 #else /* not USE_X_TOOLKIT */
13388 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13389 #endif /* not USE_X_TOOLKIT */
13390 #if 0 /* This seems to bring back scroll bars in the wrong places
13391 if the window configuration has changed. They seem
13392 to come back ok without this. */
13393 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
13394 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13395 #endif
13398 XFlush (FRAME_X_DISPLAY (f));
13400 /* Synchronize to ensure Emacs knows the frame is visible
13401 before we do anything else. We do this loop with input not blocked
13402 so that incoming events are handled. */
13404 Lisp_Object frame;
13405 int count;
13406 /* This must be before UNBLOCK_INPUT
13407 since events that arrive in response to the actions above
13408 will set it when they are handled. */
13409 int previously_visible = f->output_data.x->has_been_visible;
13411 original_left = f->output_data.x->left_pos;
13412 original_top = f->output_data.x->top_pos;
13414 /* This must come after we set COUNT. */
13415 UNBLOCK_INPUT;
13417 /* We unblock here so that arriving X events are processed. */
13419 /* Now move the window back to where it was "supposed to be".
13420 But don't do it if the gravity is negative.
13421 When the gravity is negative, this uses a position
13422 that is 3 pixels too low. Perhaps that's really the border width.
13424 Don't do this if the window has never been visible before,
13425 because the window manager may choose the position
13426 and we don't want to override it. */
13428 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
13429 && f->output_data.x->win_gravity == NorthWestGravity
13430 && previously_visible)
13432 Drawable rootw;
13433 int x, y;
13434 unsigned int width, height, border, depth;
13436 BLOCK_INPUT;
13438 /* On some window managers (such as FVWM) moving an existing
13439 window, even to the same place, causes the window manager
13440 to introduce an offset. This can cause the window to move
13441 to an unexpected location. Check the geometry (a little
13442 slow here) and then verify that the window is in the right
13443 place. If the window is not in the right place, move it
13444 there, and take the potential window manager hit. */
13445 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13446 &rootw, &x, &y, &width, &height, &border, &depth);
13448 if (original_left != x || original_top != y)
13449 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13450 original_left, original_top);
13452 UNBLOCK_INPUT;
13455 XSETFRAME (frame, f);
13457 /* Wait until the frame is visible. Process X events until a
13458 MapNotify event has been seen, or until we think we won't get a
13459 MapNotify at all.. */
13460 for (count = input_signal_count + 10;
13461 input_signal_count < count && !FRAME_VISIBLE_P (f);)
13463 /* Force processing of queued events. */
13464 x_sync (f);
13466 /* Machines that do polling rather than SIGIO have been
13467 observed to go into a busy-wait here. So we'll fake an
13468 alarm signal to let the handler know that there's something
13469 to be read. We used to raise a real alarm, but it seems
13470 that the handler isn't always enabled here. This is
13471 probably a bug. */
13472 if (input_polling_used ())
13474 /* It could be confusing if a real alarm arrives while
13475 processing the fake one. Turn it off and let the
13476 handler reset it. */
13477 extern void poll_for_input_1 P_ ((void));
13478 int old_poll_suppress_count = poll_suppress_count;
13479 poll_suppress_count = 1;
13480 poll_for_input_1 ();
13481 poll_suppress_count = old_poll_suppress_count;
13484 /* See if a MapNotify event has been processed. */
13485 FRAME_SAMPLE_VISIBILITY (f);
13488 /* 2000-09-28: In
13490 (let ((f (selected-frame)))
13491 (iconify-frame f)
13492 (raise-frame f))
13494 the frame is not raised with various window managers on
13495 FreeBSD, Linux and Solaris. It turns out that, for some
13496 unknown reason, the call to XtMapWidget is completely ignored.
13497 Mapping the widget a second time works. */
13499 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13500 goto retry;
13504 /* Change from mapped state to withdrawn state. */
13506 /* Make the frame visible (mapped and not iconified). */
13508 void
13509 x_make_frame_invisible (f)
13510 struct frame *f;
13512 Window window;
13514 #ifdef USE_X_TOOLKIT
13515 /* Use the frame's outermost window, not the one we normally draw on. */
13516 window = XtWindow (f->output_data.x->widget);
13517 #else /* not USE_X_TOOLKIT */
13518 window = FRAME_X_WINDOW (f);
13519 #endif /* not USE_X_TOOLKIT */
13521 /* Don't keep the highlight on an invisible frame. */
13522 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13523 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13525 #if 0/* This might add unreliability; I don't trust it -- rms. */
13526 if (! f->async_visible && ! f->async_iconified)
13527 return;
13528 #endif
13530 BLOCK_INPUT;
13532 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13533 that the current position of the window is user-specified, rather than
13534 program-specified, so that when the window is mapped again, it will be
13535 placed at the same location, without forcing the user to position it
13536 by hand again (they have already done that once for this window.) */
13537 x_wm_set_size_hint (f, (long) 0, 1);
13539 #ifdef HAVE_X11R4
13541 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13542 DefaultScreen (FRAME_X_DISPLAY (f))))
13544 UNBLOCK_INPUT_RESIGNAL;
13545 error ("Can't notify window manager of window withdrawal");
13547 #else /* ! defined (HAVE_X11R4) */
13549 /* Tell the window manager what we're going to do. */
13550 if (! EQ (Vx_no_window_manager, Qt))
13552 XEvent unmap;
13554 unmap.xunmap.type = UnmapNotify;
13555 unmap.xunmap.window = window;
13556 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13557 unmap.xunmap.from_configure = False;
13558 if (! XSendEvent (FRAME_X_DISPLAY (f),
13559 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13560 False,
13561 SubstructureRedirectMaskSubstructureNotifyMask,
13562 &unmap))
13564 UNBLOCK_INPUT_RESIGNAL;
13565 error ("Can't notify window manager of withdrawal");
13569 /* Unmap the window ourselves. Cheeky! */
13570 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13571 #endif /* ! defined (HAVE_X11R4) */
13573 /* We can't distinguish this from iconification
13574 just by the event that we get from the server.
13575 So we can't win using the usual strategy of letting
13576 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13577 and synchronize with the server to make sure we agree. */
13578 f->visible = 0;
13579 FRAME_ICONIFIED_P (f) = 0;
13580 f->async_visible = 0;
13581 f->async_iconified = 0;
13583 x_sync (f);
13585 UNBLOCK_INPUT;
13588 /* Change window state from mapped to iconified. */
13590 void
13591 x_iconify_frame (f)
13592 struct frame *f;
13594 int result;
13595 Lisp_Object type;
13597 /* Don't keep the highlight on an invisible frame. */
13598 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13599 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13601 if (f->async_iconified)
13602 return;
13604 BLOCK_INPUT;
13606 FRAME_SAMPLE_VISIBILITY (f);
13608 type = x_icon_type (f);
13609 if (!NILP (type))
13610 x_bitmap_icon (f, type);
13612 #ifdef USE_X_TOOLKIT
13614 if (! FRAME_VISIBLE_P (f))
13616 if (! EQ (Vx_no_window_manager, Qt))
13617 x_wm_set_window_state (f, IconicState);
13618 /* This was XtPopup, but that did nothing for an iconified frame. */
13619 XtMapWidget (f->output_data.x->widget);
13620 /* The server won't give us any event to indicate
13621 that an invisible frame was changed to an icon,
13622 so we have to record it here. */
13623 f->iconified = 1;
13624 f->visible = 1;
13625 f->async_iconified = 1;
13626 f->async_visible = 0;
13627 UNBLOCK_INPUT;
13628 return;
13631 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13632 XtWindow (f->output_data.x->widget),
13633 DefaultScreen (FRAME_X_DISPLAY (f)));
13634 UNBLOCK_INPUT;
13636 if (!result)
13637 error ("Can't notify window manager of iconification");
13639 f->async_iconified = 1;
13640 f->async_visible = 0;
13643 BLOCK_INPUT;
13644 XFlush (FRAME_X_DISPLAY (f));
13645 UNBLOCK_INPUT;
13646 #else /* not USE_X_TOOLKIT */
13648 /* Make sure the X server knows where the window should be positioned,
13649 in case the user deiconifies with the window manager. */
13650 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13651 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13653 /* Since we don't know which revision of X we're running, we'll use both
13654 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13656 /* X11R4: send a ClientMessage to the window manager using the
13657 WM_CHANGE_STATE type. */
13659 XEvent message;
13661 message.xclient.window = FRAME_X_WINDOW (f);
13662 message.xclient.type = ClientMessage;
13663 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13664 message.xclient.format = 32;
13665 message.xclient.data.l[0] = IconicState;
13667 if (! XSendEvent (FRAME_X_DISPLAY (f),
13668 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13669 False,
13670 SubstructureRedirectMask | SubstructureNotifyMask,
13671 &message))
13673 UNBLOCK_INPUT_RESIGNAL;
13674 error ("Can't notify window manager of iconification");
13678 /* X11R3: set the initial_state field of the window manager hints to
13679 IconicState. */
13680 x_wm_set_window_state (f, IconicState);
13682 if (!FRAME_VISIBLE_P (f))
13684 /* If the frame was withdrawn, before, we must map it. */
13685 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13688 f->async_iconified = 1;
13689 f->async_visible = 0;
13691 XFlush (FRAME_X_DISPLAY (f));
13692 UNBLOCK_INPUT;
13693 #endif /* not USE_X_TOOLKIT */
13697 /* Free X resources of frame F. */
13699 void
13700 x_free_frame_resources (f)
13701 struct frame *f;
13703 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13704 Lisp_Object bar;
13705 struct scroll_bar *b;
13707 BLOCK_INPUT;
13709 /* If a display connection is dead, don't try sending more
13710 commands to the X server. */
13711 if (dpyinfo->display)
13713 if (f->output_data.x->icon_desc)
13714 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13716 #ifdef USE_X_TOOLKIT
13717 /* Explicitly destroy the scroll bars of the frame. Without
13718 this, we get "BadDrawable" errors from the toolkit later on,
13719 presumably from expose events generated for the disappearing
13720 toolkit scroll bars. */
13721 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13723 b = XSCROLL_BAR (bar);
13724 x_scroll_bar_remove (b);
13726 #endif
13728 #ifdef HAVE_X_I18N
13729 if (FRAME_XIC (f))
13730 free_frame_xic (f);
13731 #endif
13733 #ifdef USE_X_TOOLKIT
13734 if (f->output_data.x->widget)
13736 XtDestroyWidget (f->output_data.x->widget);
13737 f->output_data.x->widget = NULL;
13739 /* Tooltips don't have widgets, only a simple X window, even if
13740 we are using a toolkit. */
13741 else if (FRAME_X_WINDOW (f))
13742 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13744 free_frame_menubar (f);
13745 #else /* !USE_X_TOOLKIT */
13746 if (FRAME_X_WINDOW (f))
13747 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13748 #endif /* !USE_X_TOOLKIT */
13750 unload_color (f, f->output_data.x->foreground_pixel);
13751 unload_color (f, f->output_data.x->background_pixel);
13752 unload_color (f, f->output_data.x->cursor_pixel);
13753 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13754 unload_color (f, f->output_data.x->border_pixel);
13755 unload_color (f, f->output_data.x->mouse_pixel);
13757 if (f->output_data.x->scroll_bar_background_pixel != -1)
13758 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13759 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13760 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13761 #ifdef USE_TOOLKIT_SCROLL_BARS
13762 /* Scrollbar shadow colors. */
13763 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13764 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13765 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13766 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13767 #endif /* USE_TOOLKIT_SCROLL_BARS */
13768 if (f->output_data.x->white_relief.allocated_p)
13769 unload_color (f, f->output_data.x->white_relief.pixel);
13770 if (f->output_data.x->black_relief.allocated_p)
13771 unload_color (f, f->output_data.x->black_relief.pixel);
13773 if (FRAME_FACE_CACHE (f))
13774 free_frame_faces (f);
13776 x_free_gcs (f);
13777 XFlush (FRAME_X_DISPLAY (f));
13780 if (f->output_data.x->saved_menu_event)
13781 xfree (f->output_data.x->saved_menu_event);
13783 xfree (f->output_data.x);
13784 f->output_data.x = NULL;
13786 if (f == dpyinfo->x_focus_frame)
13787 dpyinfo->x_focus_frame = 0;
13788 if (f == dpyinfo->x_focus_event_frame)
13789 dpyinfo->x_focus_event_frame = 0;
13790 if (f == dpyinfo->x_highlight_frame)
13791 dpyinfo->x_highlight_frame = 0;
13793 if (f == dpyinfo->mouse_face_mouse_frame)
13795 dpyinfo->mouse_face_beg_row
13796 = dpyinfo->mouse_face_beg_col = -1;
13797 dpyinfo->mouse_face_end_row
13798 = dpyinfo->mouse_face_end_col = -1;
13799 dpyinfo->mouse_face_window = Qnil;
13800 dpyinfo->mouse_face_deferred_gc = 0;
13801 dpyinfo->mouse_face_mouse_frame = 0;
13804 UNBLOCK_INPUT;
13808 /* Destroy the X window of frame F. */
13810 void
13811 x_destroy_window (f)
13812 struct frame *f;
13814 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13816 /* If a display connection is dead, don't try sending more
13817 commands to the X server. */
13818 if (dpyinfo->display != 0)
13819 x_free_frame_resources (f);
13821 dpyinfo->reference_count--;
13825 /* Setting window manager hints. */
13827 /* Set the normal size hints for the window manager, for frame F.
13828 FLAGS is the flags word to use--or 0 meaning preserve the flags
13829 that the window now has.
13830 If USER_POSITION is nonzero, we set the USPosition
13831 flag (this is useful when FLAGS is 0). */
13833 void
13834 x_wm_set_size_hint (f, flags, user_position)
13835 struct frame *f;
13836 long flags;
13837 int user_position;
13839 XSizeHints size_hints;
13841 #ifdef USE_X_TOOLKIT
13842 Arg al[2];
13843 int ac = 0;
13844 Dimension widget_width, widget_height;
13845 Window window = XtWindow (f->output_data.x->widget);
13846 #else /* not USE_X_TOOLKIT */
13847 Window window = FRAME_X_WINDOW (f);
13848 #endif /* not USE_X_TOOLKIT */
13850 /* Setting PMaxSize caused various problems. */
13851 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13853 size_hints.x = f->output_data.x->left_pos;
13854 size_hints.y = f->output_data.x->top_pos;
13856 #ifdef USE_X_TOOLKIT
13857 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13858 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13859 XtGetValues (f->output_data.x->widget, al, ac);
13860 size_hints.height = widget_height;
13861 size_hints.width = widget_width;
13862 #else /* not USE_X_TOOLKIT */
13863 size_hints.height = PIXEL_HEIGHT (f);
13864 size_hints.width = PIXEL_WIDTH (f);
13865 #endif /* not USE_X_TOOLKIT */
13867 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13868 size_hints.height_inc = f->output_data.x->line_height;
13869 size_hints.max_width
13870 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13871 size_hints.max_height
13872 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13874 /* Calculate the base and minimum sizes.
13876 (When we use the X toolkit, we don't do it here.
13877 Instead we copy the values that the widgets are using, below.) */
13878 #ifndef USE_X_TOOLKIT
13880 int base_width, base_height;
13881 int min_rows = 0, min_cols = 0;
13883 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13884 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13886 check_frame_size (f, &min_rows, &min_cols);
13888 /* The window manager uses the base width hints to calculate the
13889 current number of rows and columns in the frame while
13890 resizing; min_width and min_height aren't useful for this
13891 purpose, since they might not give the dimensions for a
13892 zero-row, zero-column frame.
13894 We use the base_width and base_height members if we have
13895 them; otherwise, we set the min_width and min_height members
13896 to the size for a zero x zero frame. */
13898 #ifdef HAVE_X11R4
13899 size_hints.flags |= PBaseSize;
13900 size_hints.base_width = base_width;
13901 size_hints.base_height = base_height;
13902 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13903 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13904 #else
13905 size_hints.min_width = base_width;
13906 size_hints.min_height = base_height;
13907 #endif
13910 /* If we don't need the old flags, we don't need the old hint at all. */
13911 if (flags)
13913 size_hints.flags |= flags;
13914 goto no_read;
13916 #endif /* not USE_X_TOOLKIT */
13919 XSizeHints hints; /* Sometimes I hate X Windows... */
13920 long supplied_return;
13921 int value;
13923 #ifdef HAVE_X11R4
13924 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13925 &supplied_return);
13926 #else
13927 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13928 #endif
13930 #ifdef USE_X_TOOLKIT
13931 size_hints.base_height = hints.base_height;
13932 size_hints.base_width = hints.base_width;
13933 size_hints.min_height = hints.min_height;
13934 size_hints.min_width = hints.min_width;
13935 #endif
13937 if (flags)
13938 size_hints.flags |= flags;
13939 else
13941 if (value == 0)
13942 hints.flags = 0;
13943 if (hints.flags & PSize)
13944 size_hints.flags |= PSize;
13945 if (hints.flags & PPosition)
13946 size_hints.flags |= PPosition;
13947 if (hints.flags & USPosition)
13948 size_hints.flags |= USPosition;
13949 if (hints.flags & USSize)
13950 size_hints.flags |= USSize;
13954 #ifndef USE_X_TOOLKIT
13955 no_read:
13956 #endif
13958 #ifdef PWinGravity
13959 size_hints.win_gravity = f->output_data.x->win_gravity;
13960 size_hints.flags |= PWinGravity;
13962 if (user_position)
13964 size_hints.flags &= ~ PPosition;
13965 size_hints.flags |= USPosition;
13967 #endif /* PWinGravity */
13969 #ifdef HAVE_X11R4
13970 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13971 #else
13972 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13973 #endif
13976 /* Used for IconicState or NormalState */
13978 void
13979 x_wm_set_window_state (f, state)
13980 struct frame *f;
13981 int state;
13983 #ifdef USE_X_TOOLKIT
13984 Arg al[1];
13986 XtSetArg (al[0], XtNinitialState, state);
13987 XtSetValues (f->output_data.x->widget, al, 1);
13988 #else /* not USE_X_TOOLKIT */
13989 Window window = FRAME_X_WINDOW (f);
13991 f->output_data.x->wm_hints.flags |= StateHint;
13992 f->output_data.x->wm_hints.initial_state = state;
13994 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13995 #endif /* not USE_X_TOOLKIT */
13998 void
13999 x_wm_set_icon_pixmap (f, pixmap_id)
14000 struct frame *f;
14001 int pixmap_id;
14003 Pixmap icon_pixmap;
14005 #ifndef USE_X_TOOLKIT
14006 Window window = FRAME_X_WINDOW (f);
14007 #endif
14009 if (pixmap_id > 0)
14011 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
14012 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
14014 else
14016 /* It seems there is no way to turn off use of an icon pixmap.
14017 The following line does it, only if no icon has yet been created,
14018 for some window managers. But with mwm it crashes.
14019 Some people say it should clear the IconPixmapHint bit in this case,
14020 but that doesn't work, and the X consortium said it isn't the
14021 right thing at all. Since there is no way to win,
14022 best to explicitly give up. */
14023 #if 0
14024 f->output_data.x->wm_hints.icon_pixmap = None;
14025 #else
14026 return;
14027 #endif
14030 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
14033 Arg al[1];
14034 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
14035 XtSetValues (f->output_data.x->widget, al, 1);
14038 #else /* not USE_X_TOOLKIT */
14040 f->output_data.x->wm_hints.flags |= IconPixmapHint;
14041 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14043 #endif /* not USE_X_TOOLKIT */
14046 void
14047 x_wm_set_icon_position (f, icon_x, icon_y)
14048 struct frame *f;
14049 int icon_x, icon_y;
14051 #ifdef USE_X_TOOLKIT
14052 Window window = XtWindow (f->output_data.x->widget);
14053 #else
14054 Window window = FRAME_X_WINDOW (f);
14055 #endif
14057 f->output_data.x->wm_hints.flags |= IconPositionHint;
14058 f->output_data.x->wm_hints.icon_x = icon_x;
14059 f->output_data.x->wm_hints.icon_y = icon_y;
14061 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14065 /***********************************************************************
14066 Fonts
14067 ***********************************************************************/
14069 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
14071 struct font_info *
14072 x_get_font_info (f, font_idx)
14073 FRAME_PTR f;
14074 int font_idx;
14076 return (FRAME_X_FONT_TABLE (f) + font_idx);
14080 /* Return a list of names of available fonts matching PATTERN on frame F.
14082 If SIZE is > 0, it is the size (maximum bounds width) of fonts
14083 to be listed.
14085 SIZE < 0 means include scalable fonts.
14087 Frame F null means we have not yet created any frame on X, and
14088 consult the first display in x_display_list. MAXNAMES sets a limit
14089 on how many fonts to match. */
14091 Lisp_Object
14092 x_list_fonts (f, pattern, size, maxnames)
14093 struct frame *f;
14094 Lisp_Object pattern;
14095 int size;
14096 int maxnames;
14098 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
14099 Lisp_Object tem, second_best;
14100 struct x_display_info *dpyinfo
14101 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
14102 Display *dpy = dpyinfo->display;
14103 int try_XLoadQueryFont = 0;
14104 int count;
14105 int allow_scalable_fonts_p = 0;
14107 if (size < 0)
14109 allow_scalable_fonts_p = 1;
14110 size = 0;
14113 patterns = Fassoc (pattern, Valternate_fontname_alist);
14114 if (NILP (patterns))
14115 patterns = Fcons (pattern, Qnil);
14117 if (maxnames == 1 && !size)
14118 /* We can return any single font matching PATTERN. */
14119 try_XLoadQueryFont = 1;
14121 for (; CONSP (patterns); patterns = XCDR (patterns))
14123 int num_fonts;
14124 char **names = NULL;
14126 pattern = XCAR (patterns);
14127 /* See if we cached the result for this particular query.
14128 The cache is an alist of the form:
14129 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
14130 tem = XCDR (dpyinfo->name_list_element);
14131 key = Fcons (Fcons (pattern, make_number (maxnames)),
14132 allow_scalable_fonts_p ? Qt : Qnil);
14133 list = Fassoc (key, tem);
14134 if (!NILP (list))
14136 list = Fcdr_safe (list);
14137 /* We have a cashed list. Don't have to get the list again. */
14138 goto label_cached;
14141 /* At first, put PATTERN in the cache. */
14143 BLOCK_INPUT;
14144 count = x_catch_errors (dpy);
14146 if (try_XLoadQueryFont)
14148 XFontStruct *font;
14149 unsigned long value;
14151 font = XLoadQueryFont (dpy, SDATA (pattern));
14152 if (x_had_errors_p (dpy))
14154 /* This error is perhaps due to insufficient memory on X
14155 server. Let's just ignore it. */
14156 font = NULL;
14157 x_clear_errors (dpy);
14160 if (font
14161 && XGetFontProperty (font, XA_FONT, &value))
14163 char *name = (char *) XGetAtomName (dpy, (Atom) value);
14164 int len = strlen (name);
14165 char *tmp;
14167 /* If DXPC (a Differential X Protocol Compressor)
14168 Ver.3.7 is running, XGetAtomName will return null
14169 string. We must avoid such a name. */
14170 if (len == 0)
14171 try_XLoadQueryFont = 0;
14172 else
14174 num_fonts = 1;
14175 names = (char **) alloca (sizeof (char *));
14176 /* Some systems only allow alloca assigned to a
14177 simple var. */
14178 tmp = (char *) alloca (len + 1); names[0] = tmp;
14179 bcopy (name, names[0], len + 1);
14180 XFree (name);
14183 else
14184 try_XLoadQueryFont = 0;
14186 if (font)
14187 XFreeFont (dpy, font);
14190 if (!try_XLoadQueryFont)
14192 /* We try at least 10 fonts because XListFonts will return
14193 auto-scaled fonts at the head. */
14194 names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
14195 &num_fonts);
14196 if (x_had_errors_p (dpy))
14198 /* This error is perhaps due to insufficient memory on X
14199 server. Let's just ignore it. */
14200 names = NULL;
14201 x_clear_errors (dpy);
14205 x_uncatch_errors (dpy, count);
14206 UNBLOCK_INPUT;
14208 if (names)
14210 int i;
14212 /* Make a list of all the fonts we got back.
14213 Store that in the font cache for the display. */
14214 for (i = 0; i < num_fonts; i++)
14216 int width = 0;
14217 char *p = names[i];
14218 int average_width = -1, dashes = 0;
14220 /* Count the number of dashes in NAMES[I]. If there are
14221 14 dashes, and the field value following 12th dash
14222 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
14223 is usually too ugly to be used for editing. Let's
14224 ignore it. */
14225 while (*p)
14226 if (*p++ == '-')
14228 dashes++;
14229 if (dashes == 7) /* PIXEL_SIZE field */
14230 width = atoi (p);
14231 else if (dashes == 12) /* AVERAGE_WIDTH field */
14232 average_width = atoi (p);
14235 if (allow_scalable_fonts_p
14236 || dashes < 14 || average_width != 0)
14238 tem = build_string (names[i]);
14239 if (NILP (Fassoc (tem, list)))
14241 if (STRINGP (Vx_pixel_size_width_font_regexp)
14242 && ((fast_c_string_match_ignore_case
14243 (Vx_pixel_size_width_font_regexp, names[i]))
14244 >= 0))
14245 /* We can set the value of PIXEL_SIZE to the
14246 width of this font. */
14247 list = Fcons (Fcons (tem, make_number (width)), list);
14248 else
14249 /* For the moment, width is not known. */
14250 list = Fcons (Fcons (tem, Qnil), list);
14255 if (!try_XLoadQueryFont)
14257 BLOCK_INPUT;
14258 XFreeFontNames (names);
14259 UNBLOCK_INPUT;
14263 /* Now store the result in the cache. */
14264 XSETCDR (dpyinfo->name_list_element,
14265 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
14267 label_cached:
14268 if (NILP (list)) continue; /* Try the remaining alternatives. */
14270 newlist = second_best = Qnil;
14271 /* Make a list of the fonts that have the right width. */
14272 for (; CONSP (list); list = XCDR (list))
14274 int found_size;
14276 tem = XCAR (list);
14278 if (!CONSP (tem) || NILP (XCAR (tem)))
14279 continue;
14280 if (!size)
14282 newlist = Fcons (XCAR (tem), newlist);
14283 continue;
14286 if (!INTEGERP (XCDR (tem)))
14288 /* Since we have not yet known the size of this font, we
14289 must try slow function call XLoadQueryFont. */
14290 XFontStruct *thisinfo;
14292 BLOCK_INPUT;
14293 count = x_catch_errors (dpy);
14294 thisinfo = XLoadQueryFont (dpy,
14295 SDATA (XCAR (tem)));
14296 if (x_had_errors_p (dpy))
14298 /* This error is perhaps due to insufficient memory on X
14299 server. Let's just ignore it. */
14300 thisinfo = NULL;
14301 x_clear_errors (dpy);
14303 x_uncatch_errors (dpy, count);
14304 UNBLOCK_INPUT;
14306 if (thisinfo)
14308 XSETCDR (tem,
14309 (thisinfo->min_bounds.width == 0
14310 ? make_number (0)
14311 : make_number (thisinfo->max_bounds.width)));
14312 BLOCK_INPUT;
14313 XFreeFont (dpy, thisinfo);
14314 UNBLOCK_INPUT;
14316 else
14317 /* For unknown reason, the previous call of XListFont had
14318 returned a font which can't be opened. Record the size
14319 as 0 not to try to open it again. */
14320 XSETCDR (tem, make_number (0));
14323 found_size = XINT (XCDR (tem));
14324 if (found_size == size)
14325 newlist = Fcons (XCAR (tem), newlist);
14326 else if (found_size > 0)
14328 if (NILP (second_best))
14329 second_best = tem;
14330 else if (found_size < size)
14332 if (XINT (XCDR (second_best)) > size
14333 || XINT (XCDR (second_best)) < found_size)
14334 second_best = tem;
14336 else
14338 if (XINT (XCDR (second_best)) > size
14339 && XINT (XCDR (second_best)) > found_size)
14340 second_best = tem;
14344 if (!NILP (newlist))
14345 break;
14346 else if (!NILP (second_best))
14348 newlist = Fcons (XCAR (second_best), Qnil);
14349 break;
14353 return newlist;
14357 #if GLYPH_DEBUG
14359 /* Check that FONT is valid on frame F. It is if it can be found in F's
14360 font table. */
14362 static void
14363 x_check_font (f, font)
14364 struct frame *f;
14365 XFontStruct *font;
14367 int i;
14368 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14370 xassert (font != NULL);
14372 for (i = 0; i < dpyinfo->n_fonts; i++)
14373 if (dpyinfo->font_table[i].name
14374 && font == dpyinfo->font_table[i].font)
14375 break;
14377 xassert (i < dpyinfo->n_fonts);
14380 #endif /* GLYPH_DEBUG != 0 */
14382 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14383 Note: There are (broken) X fonts out there with invalid XFontStruct
14384 min_bounds contents. For example, handa@etl.go.jp reports that
14385 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14386 have font->min_bounds.width == 0. */
14388 static INLINE void
14389 x_font_min_bounds (font, w, h)
14390 XFontStruct *font;
14391 int *w, *h;
14393 *h = FONT_HEIGHT (font);
14394 *w = font->min_bounds.width;
14396 /* Try to handle the case where FONT->min_bounds has invalid
14397 contents. Since the only font known to have invalid min_bounds
14398 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14399 if (*w <= 0)
14400 *w = font->max_bounds.width;
14404 /* Compute the smallest character width and smallest font height over
14405 all fonts available on frame F. Set the members smallest_char_width
14406 and smallest_font_height in F's x_display_info structure to
14407 the values computed. Value is non-zero if smallest_font_height or
14408 smallest_char_width become smaller than they were before. */
14410 static int
14411 x_compute_min_glyph_bounds (f)
14412 struct frame *f;
14414 int i;
14415 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14416 XFontStruct *font;
14417 int old_width = dpyinfo->smallest_char_width;
14418 int old_height = dpyinfo->smallest_font_height;
14420 dpyinfo->smallest_font_height = 100000;
14421 dpyinfo->smallest_char_width = 100000;
14423 for (i = 0; i < dpyinfo->n_fonts; ++i)
14424 if (dpyinfo->font_table[i].name)
14426 struct font_info *fontp = dpyinfo->font_table + i;
14427 int w, h;
14429 font = (XFontStruct *) fontp->font;
14430 xassert (font != (XFontStruct *) ~0);
14431 x_font_min_bounds (font, &w, &h);
14433 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
14434 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
14437 xassert (dpyinfo->smallest_char_width > 0
14438 && dpyinfo->smallest_font_height > 0);
14440 return (dpyinfo->n_fonts == 1
14441 || dpyinfo->smallest_char_width < old_width
14442 || dpyinfo->smallest_font_height < old_height);
14446 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14447 pointer to the structure font_info while allocating it dynamically.
14448 If SIZE is 0, load any size of font.
14449 If loading is failed, return NULL. */
14451 struct font_info *
14452 x_load_font (f, fontname, size)
14453 struct frame *f;
14454 register char *fontname;
14455 int size;
14457 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14458 Lisp_Object font_names;
14459 int count;
14461 /* Get a list of all the fonts that match this name. Once we
14462 have a list of matching fonts, we compare them against the fonts
14463 we already have by comparing names. */
14464 font_names = x_list_fonts (f, build_string (fontname), size, 1);
14466 if (!NILP (font_names))
14468 Lisp_Object tail;
14469 int i;
14471 for (i = 0; i < dpyinfo->n_fonts; i++)
14472 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
14473 if (dpyinfo->font_table[i].name
14474 && (!strcmp (dpyinfo->font_table[i].name,
14475 SDATA (XCAR (tail)))
14476 || !strcmp (dpyinfo->font_table[i].full_name,
14477 SDATA (XCAR (tail)))))
14478 return (dpyinfo->font_table + i);
14481 /* Load the font and add it to the table. */
14483 char *full_name;
14484 XFontStruct *font;
14485 struct font_info *fontp;
14486 unsigned long value;
14487 int i;
14489 /* If we have found fonts by x_list_font, load one of them. If
14490 not, we still try to load a font by the name given as FONTNAME
14491 because XListFonts (called in x_list_font) of some X server has
14492 a bug of not finding a font even if the font surely exists and
14493 is loadable by XLoadQueryFont. */
14494 if (size > 0 && !NILP (font_names))
14495 fontname = (char *) SDATA (XCAR (font_names));
14497 BLOCK_INPUT;
14498 count = x_catch_errors (FRAME_X_DISPLAY (f));
14499 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14500 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14502 /* This error is perhaps due to insufficient memory on X
14503 server. Let's just ignore it. */
14504 font = NULL;
14505 x_clear_errors (FRAME_X_DISPLAY (f));
14507 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14508 UNBLOCK_INPUT;
14509 if (!font)
14510 return NULL;
14512 /* Find a free slot in the font table. */
14513 for (i = 0; i < dpyinfo->n_fonts; ++i)
14514 if (dpyinfo->font_table[i].name == NULL)
14515 break;
14517 /* If no free slot found, maybe enlarge the font table. */
14518 if (i == dpyinfo->n_fonts
14519 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14521 int sz;
14522 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14523 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14524 dpyinfo->font_table
14525 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14528 fontp = dpyinfo->font_table + i;
14529 if (i == dpyinfo->n_fonts)
14530 ++dpyinfo->n_fonts;
14532 /* Now fill in the slots of *FONTP. */
14533 BLOCK_INPUT;
14534 fontp->font = font;
14535 fontp->font_idx = i;
14536 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14537 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14539 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14540 full_name = 0;
14541 if (XGetFontProperty (font, XA_FONT, &value))
14543 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14544 char *p = name;
14545 int dashes = 0;
14547 /* Count the number of dashes in the "full name".
14548 If it is too few, this isn't really the font's full name,
14549 so don't use it.
14550 In X11R4, the fonts did not come with their canonical names
14551 stored in them. */
14552 while (*p)
14554 if (*p == '-')
14555 dashes++;
14556 p++;
14559 if (dashes >= 13)
14561 full_name = (char *) xmalloc (p - name + 1);
14562 bcopy (name, full_name, p - name + 1);
14565 XFree (name);
14568 if (full_name != 0)
14569 fontp->full_name = full_name;
14570 else
14571 fontp->full_name = fontp->name;
14573 fontp->size = font->max_bounds.width;
14574 fontp->height = FONT_HEIGHT (font);
14576 if (NILP (font_names))
14578 /* We come here because of a bug of XListFonts mentioned at
14579 the head of this block. Let's store this information in
14580 the cache for x_list_fonts. */
14581 Lisp_Object lispy_name = build_string (fontname);
14582 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14583 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14584 Qnil);
14586 XSETCDR (dpyinfo->name_list_element,
14587 Fcons (Fcons (key,
14588 Fcons (Fcons (lispy_full_name,
14589 make_number (fontp->size)),
14590 Qnil)),
14591 XCDR (dpyinfo->name_list_element)));
14592 if (full_name)
14594 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14595 Qnil);
14596 XSETCDR (dpyinfo->name_list_element,
14597 Fcons (Fcons (key,
14598 Fcons (Fcons (lispy_full_name,
14599 make_number (fontp->size)),
14600 Qnil)),
14601 XCDR (dpyinfo->name_list_element)));
14605 /* The slot `encoding' specifies how to map a character
14606 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14607 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14608 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14609 2:0xA020..0xFF7F). For the moment, we don't know which charset
14610 uses this font. So, we set information in fontp->encoding[1]
14611 which is never used by any charset. If mapping can't be
14612 decided, set FONT_ENCODING_NOT_DECIDED. */
14613 fontp->encoding[1]
14614 = (font->max_byte1 == 0
14615 /* 1-byte font */
14616 ? (font->min_char_or_byte2 < 0x80
14617 ? (font->max_char_or_byte2 < 0x80
14618 ? 0 /* 0x20..0x7F */
14619 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14620 : 1) /* 0xA0..0xFF */
14621 /* 2-byte font */
14622 : (font->min_byte1 < 0x80
14623 ? (font->max_byte1 < 0x80
14624 ? (font->min_char_or_byte2 < 0x80
14625 ? (font->max_char_or_byte2 < 0x80
14626 ? 0 /* 0x2020..0x7F7F */
14627 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14628 : 3) /* 0x20A0..0x7FFF */
14629 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14630 : (font->min_char_or_byte2 < 0x80
14631 ? (font->max_char_or_byte2 < 0x80
14632 ? 2 /* 0xA020..0xFF7F */
14633 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14634 : 1))); /* 0xA0A0..0xFFFF */
14636 fontp->baseline_offset
14637 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14638 ? (long) value : 0);
14639 fontp->relative_compose
14640 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14641 ? (long) value : 0);
14642 fontp->default_ascent
14643 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14644 ? (long) value : 0);
14646 /* Set global flag fonts_changed_p to non-zero if the font loaded
14647 has a character with a smaller width than any other character
14648 before, or if the font loaded has a smaller height than any
14649 other font loaded before. If this happens, it will make a
14650 glyph matrix reallocation necessary. */
14651 fonts_changed_p |= x_compute_min_glyph_bounds (f);
14652 UNBLOCK_INPUT;
14653 return fontp;
14658 /* Return a pointer to struct font_info of a font named FONTNAME for
14659 frame F. If no such font is loaded, return NULL. */
14661 struct font_info *
14662 x_query_font (f, fontname)
14663 struct frame *f;
14664 register char *fontname;
14666 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14667 int i;
14669 for (i = 0; i < dpyinfo->n_fonts; i++)
14670 if (dpyinfo->font_table[i].name
14671 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14672 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14673 return (dpyinfo->font_table + i);
14674 return NULL;
14678 /* Find a CCL program for a font specified by FONTP, and set the member
14679 `encoder' of the structure. */
14681 void
14682 x_find_ccl_program (fontp)
14683 struct font_info *fontp;
14685 Lisp_Object list, elt;
14687 elt = Qnil;
14688 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14690 elt = XCAR (list);
14691 if (CONSP (elt)
14692 && STRINGP (XCAR (elt))
14693 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14694 >= 0)
14695 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14696 >= 0)))
14697 break;
14700 if (! NILP (list))
14702 struct ccl_program *ccl
14703 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14705 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14706 xfree (ccl);
14707 else
14708 fontp->font_encoder = ccl;
14714 /***********************************************************************
14715 Initialization
14716 ***********************************************************************/
14718 #ifdef USE_X_TOOLKIT
14719 static XrmOptionDescRec emacs_options[] = {
14720 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14721 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14723 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14724 XrmoptionSepArg, NULL},
14725 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14727 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14728 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14729 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14730 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14731 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14732 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14733 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14735 #endif /* USE_X_TOOLKIT */
14737 static int x_initialized;
14739 #ifdef MULTI_KBOARD
14740 /* Test whether two display-name strings agree up to the dot that separates
14741 the screen number from the server number. */
14742 static int
14743 same_x_server (name1, name2)
14744 const char *name1, *name2;
14746 int seen_colon = 0;
14747 const unsigned char *system_name = SDATA (Vsystem_name);
14748 int system_name_length = strlen (system_name);
14749 int length_until_period = 0;
14751 while (system_name[length_until_period] != 0
14752 && system_name[length_until_period] != '.')
14753 length_until_period++;
14755 /* Treat `unix' like an empty host name. */
14756 if (! strncmp (name1, "unix:", 5))
14757 name1 += 4;
14758 if (! strncmp (name2, "unix:", 5))
14759 name2 += 4;
14760 /* Treat this host's name like an empty host name. */
14761 if (! strncmp (name1, system_name, system_name_length)
14762 && name1[system_name_length] == ':')
14763 name1 += system_name_length;
14764 if (! strncmp (name2, system_name, system_name_length)
14765 && name2[system_name_length] == ':')
14766 name2 += system_name_length;
14767 /* Treat this host's domainless name like an empty host name. */
14768 if (! strncmp (name1, system_name, length_until_period)
14769 && name1[length_until_period] == ':')
14770 name1 += length_until_period;
14771 if (! strncmp (name2, system_name, length_until_period)
14772 && name2[length_until_period] == ':')
14773 name2 += length_until_period;
14775 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14777 if (*name1 == ':')
14778 seen_colon++;
14779 if (seen_colon && *name1 == '.')
14780 return 1;
14782 return (seen_colon
14783 && (*name1 == '.' || *name1 == '\0')
14784 && (*name2 == '.' || *name2 == '\0'));
14786 #endif
14788 struct x_display_info *
14789 x_term_init (display_name, xrm_option, resource_name)
14790 Lisp_Object display_name;
14791 char *xrm_option;
14792 char *resource_name;
14794 int connection;
14795 Display *dpy;
14796 struct x_display_info *dpyinfo;
14797 XrmDatabase xrdb;
14799 BLOCK_INPUT;
14801 if (!x_initialized)
14803 x_initialize ();
14804 x_initialized = 1;
14807 #ifdef USE_X_TOOLKIT
14808 /* weiner@footloose.sps.mot.com reports that this causes
14809 errors with X11R5:
14810 X protocol error: BadAtom (invalid Atom parameter)
14811 on protocol request 18skiloaf.
14812 So let's not use it until R6. */
14813 #ifdef HAVE_X11XTR6
14814 XtSetLanguageProc (NULL, NULL, NULL);
14815 #endif
14818 int argc = 0;
14819 char *argv[3];
14821 argv[0] = "";
14822 argc = 1;
14823 if (xrm_option)
14825 argv[argc++] = "-xrm";
14826 argv[argc++] = xrm_option;
14828 turn_on_atimers (0);
14829 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
14830 resource_name, EMACS_CLASS,
14831 emacs_options, XtNumber (emacs_options),
14832 &argc, argv);
14833 turn_on_atimers (1);
14835 #ifdef HAVE_X11XTR6
14836 /* I think this is to compensate for XtSetLanguageProc. */
14837 fixup_locale ();
14838 #endif
14841 #else /* not USE_X_TOOLKIT */
14842 #ifdef HAVE_X11R5
14843 XSetLocaleModifiers ("");
14844 #endif
14845 dpy = XOpenDisplay (SDATA (display_name));
14846 #endif /* not USE_X_TOOLKIT */
14848 /* Detect failure. */
14849 if (dpy == 0)
14851 UNBLOCK_INPUT;
14852 return 0;
14855 /* We have definitely succeeded. Record the new connection. */
14857 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14858 bzero (dpyinfo, sizeof *dpyinfo);
14860 #ifdef MULTI_KBOARD
14862 struct x_display_info *share;
14863 Lisp_Object tail;
14865 for (share = x_display_list, tail = x_display_name_list; share;
14866 share = share->next, tail = XCDR (tail))
14867 if (same_x_server (SDATA (XCAR (XCAR (tail))),
14868 SDATA (display_name)))
14869 break;
14870 if (share)
14871 dpyinfo->kboard = share->kboard;
14872 else
14874 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14875 init_kboard (dpyinfo->kboard);
14876 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14878 char *vendor = ServerVendor (dpy);
14879 UNBLOCK_INPUT;
14880 dpyinfo->kboard->Vsystem_key_alist
14881 = call1 (Qvendor_specific_keysyms,
14882 build_string (vendor ? vendor : ""));
14883 BLOCK_INPUT;
14886 dpyinfo->kboard->next_kboard = all_kboards;
14887 all_kboards = dpyinfo->kboard;
14888 /* Don't let the initial kboard remain current longer than necessary.
14889 That would cause problems if a file loaded on startup tries to
14890 prompt in the mini-buffer. */
14891 if (current_kboard == initial_kboard)
14892 current_kboard = dpyinfo->kboard;
14894 dpyinfo->kboard->reference_count++;
14896 #endif
14898 /* Put this display on the chain. */
14899 dpyinfo->next = x_display_list;
14900 x_display_list = dpyinfo;
14902 /* Put it on x_display_name_list as well, to keep them parallel. */
14903 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14904 x_display_name_list);
14905 dpyinfo->name_list_element = XCAR (x_display_name_list);
14907 dpyinfo->display = dpy;
14909 #if 0
14910 XSetAfterFunction (x_current_display, x_trace_wire);
14911 #endif /* ! 0 */
14913 dpyinfo->x_id_name
14914 = (char *) xmalloc (SBYTES (Vinvocation_name)
14915 + SBYTES (Vsystem_name)
14916 + 2);
14917 sprintf (dpyinfo->x_id_name, "%s@%s",
14918 SDATA (Vinvocation_name), SDATA (Vsystem_name));
14920 /* Figure out which modifier bits mean what. */
14921 x_find_modifier_meanings (dpyinfo);
14923 /* Get the scroll bar cursor. */
14924 dpyinfo->vertical_scroll_bar_cursor
14925 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14927 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14928 resource_name, EMACS_CLASS);
14929 #ifdef HAVE_XRMSETDATABASE
14930 XrmSetDatabase (dpyinfo->display, xrdb);
14931 #else
14932 dpyinfo->display->db = xrdb;
14933 #endif
14934 /* Put the rdb where we can find it in a way that works on
14935 all versions. */
14936 dpyinfo->xrdb = xrdb;
14938 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14939 DefaultScreen (dpyinfo->display));
14940 select_visual (dpyinfo);
14941 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14942 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14943 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14944 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14945 dpyinfo->grabbed = 0;
14946 dpyinfo->reference_count = 0;
14947 dpyinfo->icon_bitmap_id = -1;
14948 dpyinfo->font_table = NULL;
14949 dpyinfo->n_fonts = 0;
14950 dpyinfo->font_table_size = 0;
14951 dpyinfo->bitmaps = 0;
14952 dpyinfo->bitmaps_size = 0;
14953 dpyinfo->bitmaps_last = 0;
14954 dpyinfo->scratch_cursor_gc = 0;
14955 dpyinfo->mouse_face_mouse_frame = 0;
14956 dpyinfo->mouse_face_deferred_gc = 0;
14957 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14958 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14959 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14960 dpyinfo->mouse_face_window = Qnil;
14961 dpyinfo->mouse_face_overlay = Qnil;
14962 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14963 dpyinfo->mouse_face_defer = 0;
14964 dpyinfo->mouse_face_hidden = 0;
14965 dpyinfo->x_focus_frame = 0;
14966 dpyinfo->x_focus_event_frame = 0;
14967 dpyinfo->x_highlight_frame = 0;
14968 dpyinfo->image_cache = make_image_cache ();
14970 /* See if a private colormap is requested. */
14971 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14973 if (dpyinfo->visual->class == PseudoColor)
14975 Lisp_Object value;
14976 value = display_x_get_resource (dpyinfo,
14977 build_string ("privateColormap"),
14978 build_string ("PrivateColormap"),
14979 Qnil, Qnil);
14980 if (STRINGP (value)
14981 && (!strcmp (SDATA (value), "true")
14982 || !strcmp (SDATA (value), "on")))
14983 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14986 else
14987 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14988 dpyinfo->visual, AllocNone);
14991 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14992 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14993 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14994 dpyinfo->resy = pixels * 25.4 / mm;
14995 pixels = DisplayWidth (dpyinfo->display, screen_number);
14996 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14997 dpyinfo->resx = pixels * 25.4 / mm;
15000 dpyinfo->Xatom_wm_protocols
15001 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
15002 dpyinfo->Xatom_wm_take_focus
15003 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
15004 dpyinfo->Xatom_wm_save_yourself
15005 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
15006 dpyinfo->Xatom_wm_delete_window
15007 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
15008 dpyinfo->Xatom_wm_change_state
15009 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
15010 dpyinfo->Xatom_wm_configure_denied
15011 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
15012 dpyinfo->Xatom_wm_window_moved
15013 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
15014 dpyinfo->Xatom_editres
15015 = XInternAtom (dpyinfo->display, "Editres", False);
15016 dpyinfo->Xatom_CLIPBOARD
15017 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
15018 dpyinfo->Xatom_TIMESTAMP
15019 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
15020 dpyinfo->Xatom_TEXT
15021 = XInternAtom (dpyinfo->display, "TEXT", False);
15022 dpyinfo->Xatom_COMPOUND_TEXT
15023 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
15024 dpyinfo->Xatom_UTF8_STRING
15025 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
15026 dpyinfo->Xatom_DELETE
15027 = XInternAtom (dpyinfo->display, "DELETE", False);
15028 dpyinfo->Xatom_MULTIPLE
15029 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
15030 dpyinfo->Xatom_INCR
15031 = XInternAtom (dpyinfo->display, "INCR", False);
15032 dpyinfo->Xatom_EMACS_TMP
15033 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
15034 dpyinfo->Xatom_TARGETS
15035 = XInternAtom (dpyinfo->display, "TARGETS", False);
15036 dpyinfo->Xatom_NULL
15037 = XInternAtom (dpyinfo->display, "NULL", False);
15038 dpyinfo->Xatom_ATOM_PAIR
15039 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
15040 /* For properties of font. */
15041 dpyinfo->Xatom_PIXEL_SIZE
15042 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
15043 dpyinfo->Xatom_MULE_BASELINE_OFFSET
15044 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
15045 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
15046 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
15047 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
15048 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
15050 /* Ghostscript support. */
15051 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
15052 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
15054 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
15055 False);
15057 dpyinfo->cut_buffers_initialized = 0;
15059 connection = ConnectionNumber (dpyinfo->display);
15060 dpyinfo->connection = connection;
15063 char null_bits[1];
15065 null_bits[0] = 0x00;
15067 dpyinfo->null_pixel
15068 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15069 null_bits, 1, 1, (long) 0, (long) 0,
15074 extern int gray_bitmap_width, gray_bitmap_height;
15075 extern char *gray_bitmap_bits;
15076 dpyinfo->gray
15077 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15078 gray_bitmap_bits,
15079 gray_bitmap_width, gray_bitmap_height,
15080 (unsigned long) 1, (unsigned long) 0, 1);
15083 #ifdef HAVE_X_I18N
15084 xim_initialize (dpyinfo, resource_name);
15085 #endif
15087 #ifdef subprocesses
15088 /* This is only needed for distinguishing keyboard and process input. */
15089 if (connection != 0)
15090 add_keyboard_wait_descriptor (connection);
15091 #endif
15093 #ifndef F_SETOWN_BUG
15094 #ifdef F_SETOWN
15095 #ifdef F_SETOWN_SOCK_NEG
15096 /* stdin is a socket here */
15097 fcntl (connection, F_SETOWN, -getpid ());
15098 #else /* ! defined (F_SETOWN_SOCK_NEG) */
15099 fcntl (connection, F_SETOWN, getpid ());
15100 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
15101 #endif /* ! defined (F_SETOWN) */
15102 #endif /* F_SETOWN_BUG */
15104 #ifdef SIGIO
15105 if (interrupt_input)
15106 init_sigio (connection);
15107 #endif /* ! defined (SIGIO) */
15109 #ifdef USE_LUCID
15110 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
15111 /* Make sure that we have a valid font for dialog boxes
15112 so that Xt does not crash. */
15114 Display *dpy = dpyinfo->display;
15115 XrmValue d, fr, to;
15116 Font font;
15117 int count;
15119 d.addr = (XPointer)&dpy;
15120 d.size = sizeof (Display *);
15121 fr.addr = XtDefaultFont;
15122 fr.size = sizeof (XtDefaultFont);
15123 to.size = sizeof (Font *);
15124 to.addr = (XPointer)&font;
15125 count = x_catch_errors (dpy);
15126 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
15127 abort ();
15128 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
15129 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
15130 x_uncatch_errors (dpy, count);
15132 #endif
15133 #endif
15135 /* See if we should run in synchronous mode. This is useful
15136 for debugging X code. */
15138 Lisp_Object value;
15139 value = display_x_get_resource (dpyinfo,
15140 build_string ("synchronous"),
15141 build_string ("Synchronous"),
15142 Qnil, Qnil);
15143 if (STRINGP (value)
15144 && (!strcmp (SDATA (value), "true")
15145 || !strcmp (SDATA (value), "on")))
15146 XSynchronize (dpyinfo->display, True);
15149 UNBLOCK_INPUT;
15151 return dpyinfo;
15154 /* Get rid of display DPYINFO, assuming all frames are already gone,
15155 and without sending any more commands to the X server. */
15157 void
15158 x_delete_display (dpyinfo)
15159 struct x_display_info *dpyinfo;
15161 delete_keyboard_wait_descriptor (dpyinfo->connection);
15163 /* Discard this display from x_display_name_list and x_display_list.
15164 We can't use Fdelq because that can quit. */
15165 if (! NILP (x_display_name_list)
15166 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
15167 x_display_name_list = XCDR (x_display_name_list);
15168 else
15170 Lisp_Object tail;
15172 tail = x_display_name_list;
15173 while (CONSP (tail) && CONSP (XCDR (tail)))
15175 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
15177 XSETCDR (tail, XCDR (XCDR (tail)));
15178 break;
15180 tail = XCDR (tail);
15184 if (next_noop_dpyinfo == dpyinfo)
15185 next_noop_dpyinfo = dpyinfo->next;
15187 if (x_display_list == dpyinfo)
15188 x_display_list = dpyinfo->next;
15189 else
15191 struct x_display_info *tail;
15193 for (tail = x_display_list; tail; tail = tail->next)
15194 if (tail->next == dpyinfo)
15195 tail->next = tail->next->next;
15198 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
15199 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
15200 XrmDestroyDatabase (dpyinfo->xrdb);
15201 #endif
15202 #endif
15203 #ifdef MULTI_KBOARD
15204 if (--dpyinfo->kboard->reference_count == 0)
15205 delete_kboard (dpyinfo->kboard);
15206 #endif
15207 #ifdef HAVE_X_I18N
15208 if (dpyinfo->xim)
15209 xim_close_dpy (dpyinfo);
15210 #endif
15212 xfree (dpyinfo->font_table);
15213 xfree (dpyinfo->x_id_name);
15214 xfree (dpyinfo->color_cells);
15215 xfree (dpyinfo);
15219 /* Set up use of X before we make the first connection. */
15221 static struct redisplay_interface x_redisplay_interface =
15223 x_produce_glyphs,
15224 x_write_glyphs,
15225 x_insert_glyphs,
15226 x_clear_end_of_line,
15227 x_scroll_run,
15228 x_after_update_window_line,
15229 x_update_window_begin,
15230 x_update_window_end,
15231 XTcursor_to,
15232 x_flush,
15233 x_clear_mouse_face,
15234 x_get_glyph_overhangs,
15235 x_fix_overlapping_area
15238 void
15239 x_initialize ()
15241 rif = &x_redisplay_interface;
15243 clear_frame_hook = x_clear_frame;
15244 ins_del_lines_hook = x_ins_del_lines;
15245 delete_glyphs_hook = x_delete_glyphs;
15246 ring_bell_hook = XTring_bell;
15247 reset_terminal_modes_hook = XTreset_terminal_modes;
15248 set_terminal_modes_hook = XTset_terminal_modes;
15249 update_begin_hook = x_update_begin;
15250 update_end_hook = x_update_end;
15251 set_terminal_window_hook = XTset_terminal_window;
15252 read_socket_hook = XTread_socket;
15253 frame_up_to_date_hook = XTframe_up_to_date;
15254 mouse_position_hook = XTmouse_position;
15255 frame_rehighlight_hook = XTframe_rehighlight;
15256 frame_raise_lower_hook = XTframe_raise_lower;
15257 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
15258 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
15259 redeem_scroll_bar_hook = XTredeem_scroll_bar;
15260 judge_scroll_bars_hook = XTjudge_scroll_bars;
15261 estimate_mode_line_height_hook = x_estimate_mode_line_height;
15263 scroll_region_ok = 1; /* we'll scroll partial frames */
15264 char_ins_del_ok = 1;
15265 line_ins_del_ok = 1; /* we'll just blt 'em */
15266 fast_clear_end_of_line = 1; /* X does this well */
15267 memory_below_frame = 0; /* we don't remember what scrolls
15268 off the bottom */
15269 baud_rate = 19200;
15271 x_noop_count = 0;
15272 last_tool_bar_item = -1;
15273 any_help_event_p = 0;
15275 /* Try to use interrupt input; if we can't, then start polling. */
15276 Fset_input_mode (Qt, Qnil, Qt, Qnil);
15278 #ifdef USE_X_TOOLKIT
15279 XtToolkitInitialize ();
15281 Xt_app_con = XtCreateApplicationContext ();
15283 /* Register a converter from strings to pixels, which uses
15284 Emacs' color allocation infrastructure. */
15285 XtAppSetTypeConverter (Xt_app_con,
15286 XtRString, XtRPixel, cvt_string_to_pixel,
15287 cvt_string_to_pixel_args,
15288 XtNumber (cvt_string_to_pixel_args),
15289 XtCacheByDisplay, cvt_pixel_dtor);
15291 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
15293 /* Install an asynchronous timer that processes Xt timeout events
15294 every 0.1s. This is necessary because some widget sets use
15295 timeouts internally, for example the LessTif menu bar, or the
15296 Xaw3d scroll bar. When Xt timouts aren't processed, these
15297 widgets don't behave normally. */
15299 EMACS_TIME interval;
15300 EMACS_SET_SECS_USECS (interval, 0, 100000);
15301 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
15303 #endif
15305 #ifdef USE_TOOLKIT_SCROLL_BARS
15306 xaw3d_arrow_scroll = False;
15307 xaw3d_pick_top = True;
15308 #endif
15310 /* Note that there is no real way portable across R3/R4 to get the
15311 original error handler. */
15312 XSetErrorHandler (x_error_handler);
15313 XSetIOErrorHandler (x_io_error_quitter);
15315 /* Disable Window Change signals; they are handled by X events. */
15316 #ifdef SIGWINCH
15317 signal (SIGWINCH, SIG_DFL);
15318 #endif /* SIGWINCH */
15320 signal (SIGPIPE, x_connection_signal);
15322 #ifdef HAVE_X_SM
15323 x_session_initialize ();
15324 #endif
15328 void
15329 syms_of_xterm ()
15331 staticpro (&x_error_message_string);
15332 x_error_message_string = Qnil;
15334 staticpro (&x_display_name_list);
15335 x_display_name_list = Qnil;
15337 staticpro (&last_mouse_scroll_bar);
15338 last_mouse_scroll_bar = Qnil;
15340 staticpro (&Qvendor_specific_keysyms);
15341 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
15343 staticpro (&Qutf_8);
15344 Qutf_8 = intern ("utf-8");
15345 staticpro (&Qlatin_1);
15346 Qlatin_1 = intern ("latin-1");
15348 staticpro (&last_mouse_press_frame);
15349 last_mouse_press_frame = Qnil;
15351 help_echo = Qnil;
15352 staticpro (&help_echo);
15353 help_echo_object = Qnil;
15354 staticpro (&help_echo_object);
15355 help_echo_window = Qnil;
15356 staticpro (&help_echo_window);
15357 previous_help_echo = Qnil;
15358 staticpro (&previous_help_echo);
15359 help_echo_pos = -1;
15361 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
15362 doc: /* *Non-nil means autoselect window with mouse pointer. */);
15363 mouse_autoselect_window = 0;
15365 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
15366 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
15367 For example, if a block cursor is over a tab, it will be drawn as
15368 wide as that tab on the display. */);
15369 x_stretch_cursor_p = 0;
15371 DEFVAR_BOOL ("x-use-underline-position-properties",
15372 &x_use_underline_position_properties,
15373 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15374 nil means ignore them. If you encounter fonts with bogus
15375 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15376 to 4.1, set this to nil. */);
15377 x_use_underline_position_properties = 1;
15379 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
15380 doc: /* What X toolkit scroll bars Emacs uses.
15381 A value of nil means Emacs doesn't use X toolkit scroll bars.
15382 Otherwise, value is a symbol describing the X toolkit. */);
15383 #ifdef USE_TOOLKIT_SCROLL_BARS
15384 #ifdef USE_MOTIF
15385 Vx_toolkit_scroll_bars = intern ("motif");
15386 #elif defined HAVE_XAW3D
15387 Vx_toolkit_scroll_bars = intern ("xaw3d");
15388 #else
15389 Vx_toolkit_scroll_bars = intern ("xaw");
15390 #endif
15391 #else
15392 Vx_toolkit_scroll_bars = Qnil;
15393 #endif
15395 staticpro (&last_mouse_motion_frame);
15396 last_mouse_motion_frame = Qnil;
15398 Qmodifier_value = intern ("modifier-value");
15399 Qalt = intern ("alt");
15400 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
15401 Qhyper = intern ("hyper");
15402 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
15403 Qmeta = intern ("meta");
15404 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
15405 Qsuper = intern ("super");
15406 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
15408 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
15409 doc: /* Which keys Emacs uses for the alt modifier.
15410 This should be one of the symbols `alt', `hyper', `meta', `super'.
15411 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15412 is nil, which is the same as `alt'. */);
15413 Vx_alt_keysym = Qnil;
15415 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
15416 doc: /* Which keys Emacs uses for the hyper modifier.
15417 This should be one of the symbols `alt', `hyper', `meta', `super'.
15418 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15419 default is nil, which is the same as `hyper'. */);
15420 Vx_hyper_keysym = Qnil;
15422 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
15423 doc: /* Which keys Emacs uses for the meta modifier.
15424 This should be one of the symbols `alt', `hyper', `meta', `super'.
15425 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15426 default is nil, which is the same as `meta'. */);
15427 Vx_meta_keysym = Qnil;
15429 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
15430 doc: /* Which keys Emacs uses for the super modifier.
15431 This should be one of the symbols `alt', `hyper', `meta', `super'.
15432 For example, `super' means use the Super_L and Super_R keysyms. The
15433 default is nil, which is the same as `super'. */);
15434 Vx_super_keysym = Qnil;
15436 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
15437 doc: /* Hash table of character codes indexed by X keysym codes. */);
15438 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
15439 make_float (DEFAULT_REHASH_SIZE),
15440 make_float (DEFAULT_REHASH_THRESHOLD),
15441 Qnil, Qnil, Qnil);
15444 #endif /* HAVE_X_WINDOWS */