*** empty log message ***
[emacs.git] / src / xterm.c
blob220c45e648c9ab91f21a73be2f367eab28abba15
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 */
9938 /* Define a queue to save up SelectionRequest events for later handling. */
9940 struct selection_event_queue
9942 XEvent event;
9943 struct selection_event_queue *next;
9946 static struct selection_event_queue *queue;
9948 /* Nonzero means queue up certain events--don't process them yet. */
9950 static int x_queue_selection_requests;
9952 /* Queue up an X event *EVENT, to be processed later. */
9954 static void
9955 x_queue_event (f, event)
9956 FRAME_PTR f;
9957 XEvent *event;
9959 struct selection_event_queue *queue_tmp
9960 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9962 if (queue_tmp != NULL)
9964 queue_tmp->event = *event;
9965 queue_tmp->next = queue;
9966 queue = queue_tmp;
9970 /* Take all the queued events and put them back
9971 so that they get processed afresh. */
9973 static void
9974 x_unqueue_events (display)
9975 Display *display;
9977 while (queue != NULL)
9979 struct selection_event_queue *queue_tmp = queue;
9980 XPutBackEvent (display, &queue_tmp->event);
9981 queue = queue_tmp->next;
9982 xfree ((char *)queue_tmp);
9986 /* Start queuing SelectionRequest events. */
9988 void
9989 x_start_queuing_selection_requests (display)
9990 Display *display;
9992 x_queue_selection_requests++;
9995 /* Stop queuing SelectionRequest events. */
9997 void
9998 x_stop_queuing_selection_requests (display)
9999 Display *display;
10001 x_queue_selection_requests--;
10002 x_unqueue_events (display);
10005 /* The main X event-reading loop - XTread_socket. */
10007 #if 0
10008 /* Time stamp of enter window event. This is only used by XTread_socket,
10009 but we have to put it out here, since static variables within functions
10010 sometimes don't work. */
10012 static Time enter_timestamp;
10013 #endif
10015 /* This holds the state XLookupString needs to implement dead keys
10016 and other tricks known as "compose processing". _X Window System_
10017 says that a portable program can't use this, but Stephen Gildea assures
10018 me that letting the compiler initialize it to zeros will work okay.
10020 This must be defined outside of XTread_socket, for the same reasons
10021 given for enter_timestamp, above. */
10023 static XComposeStatus compose_status;
10025 /* Record the last 100 characters stored
10026 to help debug the loss-of-chars-during-GC problem. */
10028 static int temp_index;
10029 static short temp_buffer[100];
10031 /* Set this to nonzero to fake an "X I/O error"
10032 on a particular display. */
10034 struct x_display_info *XTread_socket_fake_io_error;
10036 /* When we find no input here, we occasionally do a no-op command
10037 to verify that the X server is still running and we can still talk with it.
10038 We try all the open displays, one by one.
10039 This variable is used for cycling thru the displays. */
10041 static struct x_display_info *next_noop_dpyinfo;
10043 #define SET_SAVED_MENU_EVENT(size) \
10044 do \
10046 if (f->output_data.x->saved_menu_event == 0) \
10047 f->output_data.x->saved_menu_event \
10048 = (XEvent *) xmalloc (sizeof (XEvent)); \
10049 bcopy (&event, f->output_data.x->saved_menu_event, size); \
10050 if (numchars >= 1) \
10052 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
10053 XSETFRAME (bufp->frame_or_window, f); \
10054 bufp->arg = Qnil; \
10055 bufp++; \
10056 count++; \
10057 numchars--; \
10060 while (0)
10062 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10063 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10066 enum
10068 X_EVENT_NORMAL,
10069 X_EVENT_GOTO_OUT,
10070 X_EVENT_DROP
10073 /* Handles the XEvent EVENT on display DPYINFO.
10075 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
10076 *FINISH is zero if caller should continue reading events.
10077 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
10079 Events representing keys are stored in buffer *BUFP_R,
10080 which can hold up to *NUMCHARSP characters.
10081 We return the number of characters stored into the buffer. */
10083 static int
10084 handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
10085 struct x_display_info *dpyinfo;
10086 XEvent *eventp;
10087 /* register */ struct input_event **bufp_r;
10088 /* register */ int *numcharsp;
10089 int *finish;
10091 int count = 0;
10092 int nbytes = 0;
10093 struct frame *f;
10094 struct coding_system coding;
10095 struct input_event *bufp = *bufp_r;
10096 int numchars = *numcharsp;
10097 XEvent event = *eventp;
10099 *finish = X_EVENT_NORMAL;
10101 switch (event.type)
10103 case ClientMessage:
10105 if (event.xclient.message_type
10106 == dpyinfo->Xatom_wm_protocols
10107 && event.xclient.format == 32)
10109 if (event.xclient.data.l[0]
10110 == dpyinfo->Xatom_wm_take_focus)
10112 /* Use x_any_window_to_frame because this
10113 could be the shell widget window
10114 if the frame has no title bar. */
10115 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10116 #ifdef HAVE_X_I18N
10117 /* Not quite sure this is needed -pd */
10118 if (f && FRAME_XIC (f))
10119 XSetICFocus (FRAME_XIC (f));
10120 #endif
10121 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10122 instructs the WM to set the input focus automatically for
10123 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10124 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10125 it has set the focus. So, XSetInputFocus below is not
10126 needed.
10128 The call to XSetInputFocus below has also caused trouble. In
10129 cases where the XSetInputFocus done by the WM and the one
10130 below are temporally close (on a fast machine), the call
10131 below can generate additional FocusIn events which confuse
10132 Emacs. */
10134 /* Since we set WM_TAKE_FOCUS, we must call
10135 XSetInputFocus explicitly. But not if f is null,
10136 since that might be an event for a deleted frame. */
10137 if (f)
10139 Display *d = event.xclient.display;
10140 /* Catch and ignore errors, in case window has been
10141 iconified by a window manager such as GWM. */
10142 int count = x_catch_errors (d);
10143 XSetInputFocus (d, event.xclient.window,
10144 /* The ICCCM says this is
10145 the only valid choice. */
10146 RevertToParent,
10147 event.xclient.data.l[1]);
10148 /* This is needed to detect the error
10149 if there is an error. */
10150 XSync (d, False);
10151 x_uncatch_errors (d, count);
10153 /* Not certain about handling scroll bars here */
10154 #endif /* 0 */
10156 else if (event.xclient.data.l[0]
10157 == dpyinfo->Xatom_wm_save_yourself)
10159 /* Save state modify the WM_COMMAND property to
10160 something which can reinstate us. This notifies
10161 the session manager, who's looking for such a
10162 PropertyNotify. Can restart processing when
10163 a keyboard or mouse event arrives. */
10164 /* If we have a session manager, don't set this.
10165 KDE will then start two Emacsen, one for the
10166 session manager and one for this. */
10167 if (numchars > 0
10168 #ifdef HAVE_X_SM
10169 && ! x_session_have_connection ()
10170 #endif
10173 f = x_top_window_to_frame (dpyinfo,
10174 event.xclient.window);
10175 /* This is just so we only give real data once
10176 for a single Emacs process. */
10177 if (f == SELECTED_FRAME ())
10178 XSetCommand (FRAME_X_DISPLAY (f),
10179 event.xclient.window,
10180 initial_argv, initial_argc);
10181 else if (f)
10182 XSetCommand (FRAME_X_DISPLAY (f),
10183 event.xclient.window,
10184 0, 0);
10187 else if (event.xclient.data.l[0]
10188 == dpyinfo->Xatom_wm_delete_window)
10190 struct frame *f
10191 = x_any_window_to_frame (dpyinfo,
10192 event.xclient.window);
10194 if (f)
10196 if (numchars == 0)
10197 abort ();
10199 bufp->kind = DELETE_WINDOW_EVENT;
10200 XSETFRAME (bufp->frame_or_window, f);
10201 bufp->arg = Qnil;
10202 bufp++;
10204 count += 1;
10205 numchars -= 1;
10207 else
10208 goto OTHER; /* May be a dialog that is to be removed */
10211 else if (event.xclient.message_type
10212 == dpyinfo->Xatom_wm_configure_denied)
10215 else if (event.xclient.message_type
10216 == dpyinfo->Xatom_wm_window_moved)
10218 int new_x, new_y;
10219 struct frame *f
10220 = x_window_to_frame (dpyinfo, event.xclient.window);
10222 new_x = event.xclient.data.s[0];
10223 new_y = event.xclient.data.s[1];
10225 if (f)
10227 f->output_data.x->left_pos = new_x;
10228 f->output_data.x->top_pos = new_y;
10231 #ifdef HACK_EDITRES
10232 else if (event.xclient.message_type
10233 == dpyinfo->Xatom_editres)
10235 struct frame *f
10236 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10237 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10238 &event, NULL);
10240 #endif /* HACK_EDITRES */
10241 else if ((event.xclient.message_type
10242 == dpyinfo->Xatom_DONE)
10243 || (event.xclient.message_type
10244 == dpyinfo->Xatom_PAGE))
10246 /* Ghostview job completed. Kill it. We could
10247 reply with "Next" if we received "Page", but we
10248 currently never do because we are interested in
10249 images, only, which should have 1 page. */
10250 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10251 struct frame *f
10252 = x_window_to_frame (dpyinfo, event.xclient.window);
10253 x_kill_gs_process (pixmap, f);
10254 expose_frame (f, 0, 0, 0, 0);
10256 #ifdef USE_TOOLKIT_SCROLL_BARS
10257 /* Scroll bar callbacks send a ClientMessage from which
10258 we construct an input_event. */
10259 else if (event.xclient.message_type
10260 == dpyinfo->Xatom_Scrollbar)
10262 x_scroll_bar_to_input_event (&event, bufp);
10263 ++bufp, ++count, --numchars;
10264 goto out;
10266 #endif /* USE_TOOLKIT_SCROLL_BARS */
10267 else
10268 goto OTHER;
10270 break;
10272 case SelectionNotify:
10273 #ifdef USE_X_TOOLKIT
10274 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10275 goto OTHER;
10276 #endif /* not USE_X_TOOLKIT */
10277 x_handle_selection_notify (&event.xselection);
10278 break;
10280 case SelectionClear: /* Someone has grabbed ownership. */
10281 #ifdef USE_X_TOOLKIT
10282 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10283 goto OTHER;
10284 #endif /* USE_X_TOOLKIT */
10286 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10288 if (numchars == 0)
10289 abort ();
10291 bufp->kind = SELECTION_CLEAR_EVENT;
10292 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10293 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10294 SELECTION_EVENT_TIME (bufp) = eventp->time;
10295 bufp->frame_or_window = Qnil;
10296 bufp->arg = Qnil;
10297 bufp++;
10299 count += 1;
10300 numchars -= 1;
10302 break;
10304 case SelectionRequest: /* Someone wants our selection. */
10305 #ifdef USE_X_TOOLKIT
10306 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10307 goto OTHER;
10308 #endif /* USE_X_TOOLKIT */
10309 if (x_queue_selection_requests)
10310 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10311 &event);
10312 else
10314 XSelectionRequestEvent *eventp
10315 = (XSelectionRequestEvent *) &event;
10317 if (numchars == 0)
10318 abort ();
10320 bufp->kind = SELECTION_REQUEST_EVENT;
10321 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10322 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10323 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10324 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10325 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10326 SELECTION_EVENT_TIME (bufp) = eventp->time;
10327 bufp->frame_or_window = Qnil;
10328 bufp->arg = Qnil;
10329 bufp++;
10331 count += 1;
10332 numchars -= 1;
10334 break;
10336 case PropertyNotify:
10337 #if 0 /* This is plain wrong. In the case that we are waiting for a
10338 PropertyNotify used as an ACK in incremental selection
10339 transfer, the property will be on the receiver's window. */
10340 #if defined USE_X_TOOLKIT
10341 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10342 goto OTHER;
10343 #endif
10344 #endif
10345 x_handle_property_notify (&event.xproperty);
10346 goto OTHER;
10348 case ReparentNotify:
10349 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10350 if (f)
10352 int x, y;
10353 f->output_data.x->parent_desc = event.xreparent.parent;
10354 x_real_positions (f, &x, &y);
10355 f->output_data.x->left_pos = x;
10356 f->output_data.x->top_pos = y;
10357 goto OTHER;
10359 break;
10361 case Expose:
10362 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10363 if (f)
10365 x_check_fullscreen (f);
10367 if (f->async_visible == 0)
10369 f->async_visible = 1;
10370 f->async_iconified = 0;
10371 f->output_data.x->has_been_visible = 1;
10372 SET_FRAME_GARBAGED (f);
10374 else
10375 expose_frame (x_window_to_frame (dpyinfo,
10376 event.xexpose.window),
10377 event.xexpose.x, event.xexpose.y,
10378 event.xexpose.width, event.xexpose.height);
10380 else
10382 #ifndef USE_TOOLKIT_SCROLL_BARS
10383 struct scroll_bar *bar;
10384 #endif
10385 #if defined USE_LUCID
10386 /* Submenus of the Lucid menu bar aren't widgets
10387 themselves, so there's no way to dispatch events
10388 to them. Recognize this case separately. */
10390 Widget widget
10391 = x_window_to_menu_bar (event.xexpose.window);
10392 if (widget)
10393 xlwmenu_redisplay (widget);
10395 #endif /* USE_LUCID */
10397 #ifdef USE_TOOLKIT_SCROLL_BARS
10398 /* Dispatch event to the widget. */
10399 goto OTHER;
10400 #else /* not USE_TOOLKIT_SCROLL_BARS */
10401 bar = x_window_to_scroll_bar (event.xexpose.window);
10403 if (bar)
10404 x_scroll_bar_expose (bar, &event);
10405 #ifdef USE_X_TOOLKIT
10406 else
10407 goto OTHER;
10408 #endif /* USE_X_TOOLKIT */
10409 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10411 break;
10413 case GraphicsExpose: /* This occurs when an XCopyArea's
10414 source area was obscured or not
10415 available. */
10416 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10417 if (f)
10419 expose_frame (f,
10420 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10421 event.xgraphicsexpose.width,
10422 event.xgraphicsexpose.height);
10424 #ifdef USE_X_TOOLKIT
10425 else
10426 goto OTHER;
10427 #endif /* USE_X_TOOLKIT */
10428 break;
10430 case NoExpose: /* This occurs when an XCopyArea's
10431 source area was completely
10432 available. */
10433 break;
10435 case UnmapNotify:
10436 /* Redo the mouse-highlight after the tooltip has gone. */
10437 if (event.xmap.window == tip_window)
10439 tip_window = 0;
10440 redo_mouse_highlight ();
10443 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10444 if (f) /* F may no longer exist if
10445 the frame was deleted. */
10447 /* While a frame is unmapped, display generation is
10448 disabled; you don't want to spend time updating a
10449 display that won't ever be seen. */
10450 f->async_visible = 0;
10451 /* We can't distinguish, from the event, whether the window
10452 has become iconified or invisible. So assume, if it
10453 was previously visible, than now it is iconified.
10454 But x_make_frame_invisible clears both
10455 the visible flag and the iconified flag;
10456 and that way, we know the window is not iconified now. */
10457 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10459 f->async_iconified = 1;
10461 bufp->kind = ICONIFY_EVENT;
10462 XSETFRAME (bufp->frame_or_window, f);
10463 bufp->arg = Qnil;
10464 bufp++;
10465 count++;
10466 numchars--;
10469 goto OTHER;
10471 case MapNotify:
10472 if (event.xmap.window == tip_window)
10473 /* The tooltip has been drawn already. Avoid
10474 the SET_FRAME_GARBAGED below. */
10475 goto OTHER;
10477 /* We use x_top_window_to_frame because map events can
10478 come for sub-windows and they don't mean that the
10479 frame is visible. */
10480 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10481 if (f)
10483 /* wait_reading_process_input will notice this and update
10484 the frame's display structures.
10485 If we where iconified, we should not set garbaged,
10486 because that stops redrawing on Expose events. This looks
10487 bad if we are called from a recursive event loop
10488 (x_dispatch_event), for example when a dialog is up. */
10489 if (! f->async_iconified)
10490 SET_FRAME_GARBAGED (f);
10492 f->async_visible = 1;
10493 f->async_iconified = 0;
10494 f->output_data.x->has_been_visible = 1;
10496 if (f->iconified)
10498 bufp->kind = DEICONIFY_EVENT;
10499 XSETFRAME (bufp->frame_or_window, f);
10500 bufp->arg = Qnil;
10501 bufp++;
10502 count++;
10503 numchars--;
10505 else if (! NILP (Vframe_list)
10506 && ! NILP (XCDR (Vframe_list)))
10507 /* Force a redisplay sooner or later
10508 to update the frame titles
10509 in case this is the second frame. */
10510 record_asynch_buffer_change ();
10512 goto OTHER;
10514 case KeyPress:
10516 /* Dispatch KeyPress events when in menu. */
10517 if (popup_activated_flag)
10518 goto OTHER;
10519 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10521 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10523 dpyinfo->mouse_face_hidden = 1;
10524 clear_mouse_face (dpyinfo);
10527 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10528 if (f == 0)
10530 /* Scroll bars consume key events, but we want
10531 the keys to go to the scroll bar's frame. */
10532 Widget widget = XtWindowToWidget (dpyinfo->display,
10533 event.xkey.window);
10534 if (widget && XmIsScrollBar (widget))
10536 widget = XtParent (widget);
10537 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10540 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10542 if (f != 0)
10544 KeySym keysym, orig_keysym;
10545 /* al%imercury@uunet.uu.net says that making this 81
10546 instead of 80 fixed a bug whereby meta chars made
10547 his Emacs hang.
10549 It seems that some version of XmbLookupString has
10550 a bug of not returning XBufferOverflow in
10551 status_return even if the input is too long to
10552 fit in 81 bytes. So, we must prepare sufficient
10553 bytes for copy_buffer. 513 bytes (256 chars for
10554 two-byte character set) seems to be a fairly good
10555 approximation. -- 2000.8.10 handa@etl.go.jp */
10556 unsigned char copy_buffer[513];
10557 unsigned char *copy_bufptr = copy_buffer;
10558 int copy_bufsiz = sizeof (copy_buffer);
10559 int modifiers;
10560 Lisp_Object coding_system = Qlatin_1;
10562 event.xkey.state
10563 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10564 extra_keyboard_modifiers);
10565 modifiers = event.xkey.state;
10567 /* This will have to go some day... */
10569 /* make_lispy_event turns chars into control chars.
10570 Don't do it here because XLookupString is too eager. */
10571 event.xkey.state &= ~ControlMask;
10572 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10573 | dpyinfo->super_mod_mask
10574 | dpyinfo->hyper_mod_mask
10575 | dpyinfo->alt_mod_mask);
10577 /* In case Meta is ComposeCharacter,
10578 clear its status. According to Markus Ehrnsperger
10579 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10580 this enables ComposeCharacter to work whether or
10581 not it is combined with Meta. */
10582 if (modifiers & dpyinfo->meta_mod_mask)
10583 bzero (&compose_status, sizeof (compose_status));
10585 #ifdef HAVE_X_I18N
10586 if (FRAME_XIC (f))
10588 Status status_return;
10590 coding_system = Vlocale_coding_system;
10591 nbytes = XmbLookupString (FRAME_XIC (f),
10592 &event.xkey, copy_bufptr,
10593 copy_bufsiz, &keysym,
10594 &status_return);
10595 if (status_return == XBufferOverflow)
10597 copy_bufsiz = nbytes + 1;
10598 copy_bufptr = (char *) alloca (copy_bufsiz);
10599 nbytes = XmbLookupString (FRAME_XIC (f),
10600 &event.xkey, copy_bufptr,
10601 copy_bufsiz, &keysym,
10602 &status_return);
10604 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10605 #if 0 && defined X_HAVE_UTF8_STRING
10606 else if (status_return == XLookupKeySym)
10607 { /* Try again but with utf-8. */
10608 coding_system = Qutf_8;
10609 nbytes = Xutf8LookupString (FRAME_XIC (f),
10610 &event.xkey, copy_bufptr,
10611 copy_bufsiz, &keysym,
10612 &status_return);
10613 if (status_return == XBufferOverflow)
10615 copy_bufsiz = nbytes + 1;
10616 copy_bufptr = (char *) alloca (copy_bufsiz);
10617 nbytes = Xutf8LookupString (FRAME_XIC (f),
10618 &event.xkey,
10619 copy_bufptr,
10620 copy_bufsiz, &keysym,
10621 &status_return);
10624 #endif
10626 if (status_return == XLookupNone)
10627 break;
10628 else if (status_return == XLookupChars)
10630 keysym = NoSymbol;
10631 modifiers = 0;
10633 else if (status_return != XLookupKeySym
10634 && status_return != XLookupBoth)
10635 abort ();
10637 else
10638 nbytes = XLookupString (&event.xkey, copy_bufptr,
10639 copy_bufsiz, &keysym,
10640 &compose_status);
10641 #else
10642 nbytes = XLookupString (&event.xkey, copy_bufptr,
10643 copy_bufsiz, &keysym,
10644 &compose_status);
10645 #endif
10647 orig_keysym = keysym;
10649 if (numchars > 1)
10651 Lisp_Object c;
10653 /* First deal with keysyms which have defined
10654 translations to characters. */
10655 if (keysym >= 32 && keysym < 128)
10656 /* Avoid explicitly decoding each ASCII character. */
10658 bufp->kind = ASCII_KEYSTROKE_EVENT;
10659 bufp->code = keysym;
10660 XSETFRAME (bufp->frame_or_window, f);
10661 bufp->arg = Qnil;
10662 bufp->modifiers
10663 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10664 modifiers);
10665 bufp->timestamp = event.xkey.time;
10666 bufp++;
10667 count++;
10668 numchars--;
10670 /* Now non-ASCII. */
10671 else if (HASH_TABLE_P (Vx_keysym_table)
10672 && (NATNUMP (c = Fgethash (make_number (keysym),
10673 Vx_keysym_table,
10674 Qnil))))
10676 bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
10677 ? ASCII_KEYSTROKE_EVENT
10678 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10679 bufp->code = XFASTINT (c);
10680 XSETFRAME (bufp->frame_or_window, f);
10681 bufp->arg = Qnil;
10682 bufp->modifiers
10683 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10684 modifiers);
10685 bufp->timestamp = event.xkey.time;
10686 bufp++;
10687 count++;
10688 numchars--;
10690 /* Random non-modifier sorts of keysyms. */
10691 else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10692 || keysym == XK_Delete
10693 #ifdef XK_ISO_Left_Tab
10694 || (keysym >= XK_ISO_Left_Tab
10695 && keysym <= XK_ISO_Enter)
10696 #endif
10697 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10698 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10699 #ifdef HPUX
10700 /* This recognizes the "extended function
10701 keys". It seems there's no cleaner way.
10702 Test IsModifierKey to avoid handling
10703 mode_switch incorrectly. */
10704 || ((unsigned) (keysym) >= XK_Select
10705 && (unsigned)(keysym) < XK_KP_Space)
10706 #endif
10707 #ifdef XK_dead_circumflex
10708 || orig_keysym == XK_dead_circumflex
10709 #endif
10710 #ifdef XK_dead_grave
10711 || orig_keysym == XK_dead_grave
10712 #endif
10713 #ifdef XK_dead_tilde
10714 || orig_keysym == XK_dead_tilde
10715 #endif
10716 #ifdef XK_dead_diaeresis
10717 || orig_keysym == XK_dead_diaeresis
10718 #endif
10719 #ifdef XK_dead_macron
10720 || orig_keysym == XK_dead_macron
10721 #endif
10722 #ifdef XK_dead_degree
10723 || orig_keysym == XK_dead_degree
10724 #endif
10725 #ifdef XK_dead_acute
10726 || orig_keysym == XK_dead_acute
10727 #endif
10728 #ifdef XK_dead_cedilla
10729 || orig_keysym == XK_dead_cedilla
10730 #endif
10731 #ifdef XK_dead_breve
10732 || orig_keysym == XK_dead_breve
10733 #endif
10734 #ifdef XK_dead_ogonek
10735 || orig_keysym == XK_dead_ogonek
10736 #endif
10737 #ifdef XK_dead_caron
10738 || orig_keysym == XK_dead_caron
10739 #endif
10740 #ifdef XK_dead_doubleacute
10741 || orig_keysym == XK_dead_doubleacute
10742 #endif
10743 #ifdef XK_dead_abovedot
10744 || orig_keysym == XK_dead_abovedot
10745 #endif
10746 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10747 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10748 /* Any "vendor-specific" key is ok. */
10749 || (orig_keysym & (1 << 28))
10750 || (keysym != NoSymbol && nbytes == 0))
10751 && ! (IsModifierKey (orig_keysym)
10752 #ifndef HAVE_X11R5
10753 #ifdef XK_Mode_switch
10754 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10755 #endif
10756 #ifdef XK_Num_Lock
10757 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10758 #endif
10759 #endif /* not HAVE_X11R5 */
10760 /* The symbols from XK_ISO_Lock
10761 to XK_ISO_Last_Group_Lock
10762 don't have real modifiers but
10763 should be treated similarly to
10764 Mode_switch by Emacs. */
10765 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10766 || ((unsigned)(orig_keysym)
10767 >= XK_ISO_Lock
10768 && (unsigned)(orig_keysym)
10769 <= XK_ISO_Last_Group_Lock)
10770 #endif
10773 if (temp_index == sizeof temp_buffer / sizeof (short))
10774 temp_index = 0;
10775 temp_buffer[temp_index++] = keysym;
10776 /* make_lispy_event will convert this to a symbolic
10777 key. */
10778 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10779 bufp->code = keysym;
10780 XSETFRAME (bufp->frame_or_window, f);
10781 bufp->arg = Qnil;
10782 bufp->modifiers
10783 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10784 modifiers);
10785 bufp->timestamp = event.xkey.time;
10786 bufp++;
10787 count++;
10788 numchars--;
10790 else if (numchars > nbytes)
10791 { /* Raw bytes, not keysym. */
10792 register int i;
10793 register int c;
10794 int nchars, len;
10796 /* The input should be decoded with `coding_system'
10797 which depends on which X*LookupString function
10798 we used just above and the locale. */
10799 setup_coding_system (coding_system, &coding);
10800 coding.src_multibyte = 0;
10801 coding.dst_multibyte = 1;
10802 /* The input is converted to events, thus we can't
10803 handle composition. Anyway, there's no XIM that
10804 gives us composition information. */
10805 coding.composing = COMPOSITION_DISABLED;
10807 for (i = 0; i < nbytes; i++)
10809 if (temp_index == (sizeof temp_buffer
10810 / sizeof (short)))
10811 temp_index = 0;
10812 temp_buffer[temp_index++] = copy_bufptr[i];
10816 /* Decode the input data. */
10817 int require;
10818 unsigned char *p;
10820 require = decoding_buffer_size (&coding, nbytes);
10821 p = (unsigned char *) alloca (require);
10822 coding.mode |= CODING_MODE_LAST_BLOCK;
10823 /* We explicitely disable composition
10824 handling because key data should
10825 not contain any composition
10826 sequence. */
10827 coding.composing = COMPOSITION_DISABLED;
10828 decode_coding (&coding, copy_bufptr, p,
10829 nbytes, require);
10830 nbytes = coding.produced;
10831 nchars = coding.produced_char;
10832 copy_bufptr = p;
10835 /* Convert the input data to a sequence of
10836 character events. */
10837 for (i = 0; i < nbytes; i += len)
10839 if (nchars == nbytes)
10840 c = copy_bufptr[i], len = 1;
10841 else
10842 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10843 nbytes - i, len);
10845 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10846 ? ASCII_KEYSTROKE_EVENT
10847 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10848 bufp->code = c;
10849 XSETFRAME (bufp->frame_or_window, f);
10850 bufp->arg = Qnil;
10851 bufp->modifiers
10852 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10853 modifiers);
10854 bufp->timestamp = event.xkey.time;
10855 bufp++;
10858 count += nchars;
10859 numchars -= nchars;
10861 if (keysym == NoSymbol)
10862 break;
10864 else
10865 abort ();
10867 else
10868 abort ();
10870 #ifdef HAVE_X_I18N
10871 /* Don't dispatch this event since XtDispatchEvent calls
10872 XFilterEvent, and two calls in a row may freeze the
10873 client. */
10874 break;
10875 #else
10876 goto OTHER;
10877 #endif
10879 case KeyRelease:
10880 #ifdef HAVE_X_I18N
10881 /* Don't dispatch this event since XtDispatchEvent calls
10882 XFilterEvent, and two calls in a row may freeze the
10883 client. */
10884 break;
10885 #else
10886 goto OTHER;
10887 #endif
10889 case EnterNotify:
10891 int n;
10893 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10894 if (n > 0)
10896 bufp += n, count += n, numchars -= n;
10899 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10901 #if 0
10902 if (event.xcrossing.focus)
10904 /* Avoid nasty pop/raise loops. */
10905 if (f && (!(f->auto_raise)
10906 || !(f->auto_lower)
10907 || (event.xcrossing.time - enter_timestamp) > 500))
10909 x_new_focus_frame (dpyinfo, f);
10910 enter_timestamp = event.xcrossing.time;
10913 else if (f == dpyinfo->x_focus_frame)
10914 x_new_focus_frame (dpyinfo, 0);
10915 #endif
10917 /* EnterNotify counts as mouse movement,
10918 so update things that depend on mouse position. */
10919 if (f && !f->output_data.x->hourglass_p)
10920 note_mouse_movement (f, &event.xmotion);
10921 goto OTHER;
10924 case FocusIn:
10926 int n;
10928 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10929 if (n > 0)
10931 bufp += n, count += n, numchars -= n;
10935 goto OTHER;
10937 case LeaveNotify:
10939 int n;
10941 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10942 if (n > 0)
10944 bufp += n, count += n, numchars -= n;
10948 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10949 if (f)
10951 if (f == dpyinfo->mouse_face_mouse_frame)
10953 /* If we move outside the frame, then we're
10954 certainly no longer on any text in the frame. */
10955 clear_mouse_face (dpyinfo);
10956 dpyinfo->mouse_face_mouse_frame = 0;
10959 /* Generate a nil HELP_EVENT to cancel a help-echo.
10960 Do it only if there's something to cancel.
10961 Otherwise, the startup message is cleared when
10962 the mouse leaves the frame. */
10963 if (any_help_event_p)
10965 Lisp_Object frame;
10966 int n;
10968 XSETFRAME (frame, f);
10969 help_echo = Qnil;
10970 n = gen_help_event (bufp, numchars,
10971 Qnil, frame, Qnil, Qnil, 0);
10972 bufp += n, count += n, numchars -= n;
10976 goto OTHER;
10978 case FocusOut:
10980 int n;
10982 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10983 if (n > 0)
10985 bufp += n, count += n, numchars -= n;
10989 goto OTHER;
10991 case MotionNotify:
10993 previous_help_echo = help_echo;
10994 help_echo = help_echo_object = help_echo_window = Qnil;
10995 help_echo_pos = -1;
10997 if (dpyinfo->grabbed && last_mouse_frame
10998 && FRAME_LIVE_P (last_mouse_frame))
10999 f = last_mouse_frame;
11000 else
11001 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11003 if (dpyinfo->mouse_face_hidden)
11005 dpyinfo->mouse_face_hidden = 0;
11006 clear_mouse_face (dpyinfo);
11009 if (f)
11012 /* Generate SELECT_WINDOW_EVENTs when needed. */
11013 if (mouse_autoselect_window)
11015 Lisp_Object window;
11016 int area;
11018 window = window_from_coordinates (f,
11019 event.xmotion.x, event.xmotion.y,
11020 &area, 0);
11022 /* Window will be selected only when it is not selected now and
11023 last mouse movement event was not in it. Minibuffer window
11024 will be selected iff it is active. */
11025 if (WINDOWP(window)
11026 && !EQ (window, last_window)
11027 && !EQ (window, selected_window)
11028 && numchars > 0)
11030 bufp->kind = SELECT_WINDOW_EVENT;
11031 bufp->frame_or_window = window;
11032 bufp->arg = Qnil;
11033 ++bufp, ++count, --numchars;
11036 last_window=window;
11038 note_mouse_movement (f, &event.xmotion);
11040 else
11042 #ifndef USE_TOOLKIT_SCROLL_BARS
11043 struct scroll_bar *bar
11044 = x_window_to_scroll_bar (event.xmotion.window);
11046 if (bar)
11047 x_scroll_bar_note_movement (bar, &event);
11048 #endif /* USE_TOOLKIT_SCROLL_BARS */
11050 /* If we move outside the frame, then we're
11051 certainly no longer on any text in the frame. */
11052 clear_mouse_face (dpyinfo);
11055 /* If the contents of the global variable help_echo
11056 has changed, generate a HELP_EVENT. */
11057 if (!NILP (help_echo)
11058 || !NILP (previous_help_echo))
11060 Lisp_Object frame;
11061 int n;
11063 if (f)
11064 XSETFRAME (frame, f);
11065 else
11066 frame = Qnil;
11068 any_help_event_p = 1;
11069 n = gen_help_event (bufp, numchars, help_echo, frame,
11070 help_echo_window, help_echo_object,
11071 help_echo_pos);
11072 bufp += n, count += n, numchars -= n;
11075 goto OTHER;
11078 case ConfigureNotify:
11079 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11080 if (f)
11082 #ifndef USE_X_TOOLKIT
11083 /* If there is a pending resize for fullscreen, don't
11084 do this one, the right one will come later.
11085 The toolkit version doesn't seem to need this, but we
11086 need to reset it below. */
11087 int dont_resize =
11088 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11089 && FRAME_NEW_WIDTH (f) != 0);
11090 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11091 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11092 if (dont_resize)
11093 goto OTHER;
11095 /* In the toolkit version, change_frame_size
11096 is called by the code that handles resizing
11097 of the EmacsFrame widget. */
11099 /* Even if the number of character rows and columns has
11100 not changed, the font size may have changed, so we need
11101 to check the pixel dimensions as well. */
11102 if (columns != f->width
11103 || rows != f->height
11104 || event.xconfigure.width != f->output_data.x->pixel_width
11105 || event.xconfigure.height != f->output_data.x->pixel_height)
11107 change_frame_size (f, rows, columns, 0, 1, 0);
11108 SET_FRAME_GARBAGED (f);
11109 cancel_mouse_face (f);
11111 #endif
11113 f->output_data.x->pixel_width = event.xconfigure.width;
11114 f->output_data.x->pixel_height = event.xconfigure.height;
11116 /* What we have now is the position of Emacs's own window.
11117 Convert that to the position of the window manager window. */
11118 x_real_positions (f, &f->output_data.x->left_pos,
11119 &f->output_data.x->top_pos);
11121 x_check_fullscreen_move(f);
11122 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11123 f->output_data.x->want_fullscreen &=
11124 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11125 #ifdef HAVE_X_I18N
11126 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11127 xic_set_statusarea (f);
11128 #endif
11130 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11132 /* Since the WM decorations come below top_pos now,
11133 we must put them below top_pos in the future. */
11134 f->output_data.x->win_gravity = NorthWestGravity;
11135 x_wm_set_size_hint (f, (long) 0, 0);
11138 goto OTHER;
11140 case ButtonPress:
11141 case ButtonRelease:
11143 /* If we decide we want to generate an event to be seen
11144 by the rest of Emacs, we put it here. */
11145 struct input_event emacs_event;
11146 int tool_bar_p = 0;
11148 emacs_event.kind = NO_EVENT;
11149 bzero (&compose_status, sizeof (compose_status));
11151 if (dpyinfo->grabbed
11152 && last_mouse_frame
11153 && FRAME_LIVE_P (last_mouse_frame))
11154 f = last_mouse_frame;
11155 else
11156 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11158 if (f)
11160 /* Is this in the tool-bar? */
11161 if (WINDOWP (f->tool_bar_window)
11162 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11164 Lisp_Object window;
11165 int p, x, y;
11167 x = event.xbutton.x;
11168 y = event.xbutton.y;
11170 /* Set x and y. */
11171 window = window_from_coordinates (f, x, y, &p, 1);
11172 if (EQ (window, f->tool_bar_window))
11174 x_handle_tool_bar_click (f, &event.xbutton);
11175 tool_bar_p = 1;
11179 if (!tool_bar_p)
11180 if (!dpyinfo->x_focus_frame
11181 || f == dpyinfo->x_focus_frame)
11182 construct_mouse_click (&emacs_event, &event, f);
11184 else
11186 #ifndef USE_TOOLKIT_SCROLL_BARS
11187 struct scroll_bar *bar
11188 = x_window_to_scroll_bar (event.xbutton.window);
11190 if (bar)
11191 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11192 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11195 if (event.type == ButtonPress)
11197 dpyinfo->grabbed |= (1 << event.xbutton.button);
11198 last_mouse_frame = f;
11199 /* Ignore any mouse motion that happened
11200 before this event; any subsequent mouse-movement
11201 Emacs events should reflect only motion after
11202 the ButtonPress. */
11203 if (f != 0)
11204 f->mouse_moved = 0;
11206 if (!tool_bar_p)
11207 last_tool_bar_item = -1;
11209 else
11211 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11214 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11216 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11217 bufp++;
11218 count++;
11219 numchars--;
11222 #ifdef USE_X_TOOLKIT
11223 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11224 /* For a down-event in the menu bar,
11225 don't pass it to Xt right now.
11226 Instead, save it away
11227 and we will pass it to Xt from kbd_buffer_get_event.
11228 That way, we can run some Lisp code first. */
11229 if (f && event.type == ButtonPress
11230 /* Verify the event is really within the menu bar
11231 and not just sent to it due to grabbing. */
11232 && event.xbutton.x >= 0
11233 && event.xbutton.x < f->output_data.x->pixel_width
11234 && event.xbutton.y >= 0
11235 && event.xbutton.y < f->output_data.x->menubar_height
11236 && event.xbutton.same_screen)
11238 SET_SAVED_BUTTON_EVENT;
11239 XSETFRAME (last_mouse_press_frame, f);
11241 else if (event.type == ButtonPress)
11243 last_mouse_press_frame = Qnil;
11244 goto OTHER;
11247 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11248 but I am trying to be cautious. */
11249 else if (event.type == ButtonRelease)
11251 if (!NILP (last_mouse_press_frame))
11253 f = XFRAME (last_mouse_press_frame);
11254 if (f->output_data.x)
11255 SET_SAVED_BUTTON_EVENT;
11257 else
11258 goto OTHER;
11260 #endif /* USE_MOTIF */
11261 else
11262 goto OTHER;
11263 #endif /* USE_X_TOOLKIT */
11265 break;
11267 case CirculateNotify:
11268 goto OTHER;
11270 case CirculateRequest:
11271 goto OTHER;
11273 case VisibilityNotify:
11274 goto OTHER;
11276 case MappingNotify:
11277 /* Someone has changed the keyboard mapping - update the
11278 local cache. */
11279 switch (event.xmapping.request)
11281 case MappingModifier:
11282 x_find_modifier_meanings (dpyinfo);
11283 /* This is meant to fall through. */
11284 case MappingKeyboard:
11285 XRefreshKeyboardMapping (&event.xmapping);
11287 goto OTHER;
11289 default:
11290 OTHER:
11291 #ifdef USE_X_TOOLKIT
11292 BLOCK_INPUT;
11293 XtDispatchEvent (&event);
11294 UNBLOCK_INPUT;
11295 #endif /* USE_X_TOOLKIT */
11296 break;
11299 goto ret;
11301 out:
11302 *finish = X_EVENT_GOTO_OUT;
11304 ret:
11305 *bufp_r = bufp;
11306 *numcharsp = numchars;
11307 *eventp = event;
11309 return count;
11313 /* Handles the XEvent EVENT on display DISPLAY.
11314 This is used for event loops outside the normal event handling,
11315 i.e. looping while a popup menu or a dialog is posted. */
11316 void
11317 x_dispatch_event (event, display)
11318 XEvent *event;
11319 Display *display;
11321 struct x_display_info *dpyinfo;
11322 struct input_event bufp[10];
11323 struct input_event *bufpp = bufp;
11324 int numchars = 10;
11325 int finish;
11327 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
11328 if (dpyinfo->display == display)
11329 break;
11331 if (dpyinfo)
11333 int i, events;
11334 events = handle_one_xevent (dpyinfo,
11335 event,
11336 &bufpp,
11337 &numchars,
11338 &finish);
11339 for (i = 0; i < events; ++i)
11340 kbd_buffer_store_event (&bufp[i]);
11345 /* Read events coming from the X server.
11346 This routine is called by the SIGIO handler.
11347 We return as soon as there are no more events to be read.
11349 Events representing keys are stored in buffer BUFP,
11350 which can hold up to NUMCHARS characters.
11351 We return the number of characters stored into the buffer,
11352 thus pretending to be `read'.
11354 EXPECTED is nonzero if the caller knows input is available. */
11356 static int
11357 XTread_socket (sd, bufp, numchars, expected)
11358 register int sd;
11359 /* register */ struct input_event *bufp;
11360 /* register */ int numchars;
11361 int expected;
11363 int count = 0;
11364 int nbytes = 0;
11365 XEvent event;
11366 int event_found = 0;
11367 struct x_display_info *dpyinfo;
11369 if (interrupt_input_blocked)
11371 interrupt_input_pending = 1;
11372 return -1;
11375 interrupt_input_pending = 0;
11376 BLOCK_INPUT;
11378 /* So people can tell when we have read the available input. */
11379 input_signal_count++;
11381 if (numchars <= 0)
11382 abort (); /* Don't think this happens. */
11384 ++handling_signal;
11386 /* Find the display we are supposed to read input for.
11387 It's the one communicating on descriptor SD. */
11388 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
11390 #if 0 /* This ought to be unnecessary; let's verify it. */
11391 #ifdef FIOSNBIO
11392 /* If available, Xlib uses FIOSNBIO to make the socket
11393 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
11394 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
11395 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
11396 fcntl (dpyinfo->connection, F_SETFL, 0);
11397 #endif /* ! defined (FIOSNBIO) */
11398 #endif
11400 #if 0 /* This code can't be made to work, with multiple displays,
11401 and appears not to be used on any system any more.
11402 Also keyboard.c doesn't turn O_NDELAY on and off
11403 for X connections. */
11404 #ifndef SIGIO
11405 #ifndef HAVE_SELECT
11406 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
11408 extern int read_alarm_should_throw;
11409 read_alarm_should_throw = 1;
11410 XPeekEvent (dpyinfo->display, &event);
11411 read_alarm_should_throw = 0;
11413 #endif /* HAVE_SELECT */
11414 #endif /* SIGIO */
11415 #endif
11417 /* For debugging, this gives a way to fake an I/O error. */
11418 if (dpyinfo == XTread_socket_fake_io_error)
11420 XTread_socket_fake_io_error = 0;
11421 x_io_error_quitter (dpyinfo->display);
11424 #ifdef HAVE_X_SM
11425 BLOCK_INPUT;
11426 count += x_session_check_input (bufp, &numchars);
11427 UNBLOCK_INPUT;
11428 #endif
11430 while (XPending (dpyinfo->display))
11432 int finish;
11434 XNextEvent (dpyinfo->display, &event);
11436 #ifdef HAVE_X_I18N
11438 /* Filter events for the current X input method.
11439 XFilterEvent returns non-zero if the input method has
11440 consumed the event. We pass the frame's X window to
11441 XFilterEvent because that's the one for which the IC
11442 was created. */
11443 struct frame *f1 = x_any_window_to_frame (dpyinfo,
11444 event.xclient.window);
11445 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
11446 break;
11448 #endif
11449 event_found = 1;
11451 count += handle_one_xevent (dpyinfo,
11452 &event,
11453 &bufp,
11454 &numchars,
11455 &finish);
11457 if (finish == X_EVENT_GOTO_OUT)
11458 goto out;
11462 out:;
11464 /* On some systems, an X bug causes Emacs to get no more events
11465 when the window is destroyed. Detect that. (1994.) */
11466 if (! event_found)
11468 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11469 One XNOOP in 100 loops will make Emacs terminate.
11470 B. Bretthauer, 1994 */
11471 x_noop_count++;
11472 if (x_noop_count >= 100)
11474 x_noop_count=0;
11476 if (next_noop_dpyinfo == 0)
11477 next_noop_dpyinfo = x_display_list;
11479 XNoOp (next_noop_dpyinfo->display);
11481 /* Each time we get here, cycle through the displays now open. */
11482 next_noop_dpyinfo = next_noop_dpyinfo->next;
11486 /* If the focus was just given to an auto-raising frame,
11487 raise it now. */
11488 /* ??? This ought to be able to handle more than one such frame. */
11489 if (pending_autoraise_frame)
11491 x_raise_frame (pending_autoraise_frame);
11492 pending_autoraise_frame = 0;
11495 UNBLOCK_INPUT;
11496 --handling_signal;
11497 return count;
11503 /***********************************************************************
11504 Text Cursor
11505 ***********************************************************************/
11507 /* Notice when the text cursor of window W has been completely
11508 overwritten by a drawing operation that outputs glyphs in AREA
11509 starting at X0 and ending at X1 in the line starting at Y0 and
11510 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11511 the rest of the line after X0 has been written. Y coordinates
11512 are window-relative. */
11514 static void
11515 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
11516 struct window *w;
11517 enum glyph_row_area area;
11518 int x0, y0, x1, y1;
11520 if (area == TEXT_AREA && w->phys_cursor_on_p)
11522 int cx0 = w->phys_cursor.x;
11523 int cx1 = cx0 + w->phys_cursor_width;
11524 int cy0 = w->phys_cursor.y;
11525 int cy1 = cy0 + w->phys_cursor_height;
11527 if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
11529 /* The cursor image will be completely removed from the
11530 screen if the output area intersects the cursor area in
11531 y-direction. When we draw in [y0 y1[, and some part of
11532 the cursor is at y < y0, that part must have been drawn
11533 before. When scrolling, the cursor is erased before
11534 actually scrolling, so we don't come here. When not
11535 scrolling, the rows above the old cursor row must have
11536 changed, and in this case these rows must have written
11537 over the cursor image.
11539 Likewise if part of the cursor is below y1, with the
11540 exception of the cursor being in the first blank row at
11541 the buffer and window end because update_text_area
11542 doesn't draw that row. (Except when it does, but
11543 that's handled in update_text_area.) */
11545 if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
11546 && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
11547 w->phys_cursor_on_p = 0;
11553 /* Set clipping for output in glyph row ROW. W is the window in which
11554 we operate. GC is the graphics context to set clipping in.
11555 WHOLE_LINE_P non-zero means include the areas used for truncation
11556 mark display and alike in the clipping rectangle.
11558 ROW may be a text row or, e.g., a mode line. Text rows must be
11559 clipped to the interior of the window dedicated to text display,
11560 mode lines must be clipped to the whole window. */
11562 static void
11563 x_clip_to_row (w, row, gc, whole_line_p)
11564 struct window *w;
11565 struct glyph_row *row;
11566 GC gc;
11567 int whole_line_p;
11569 struct frame *f = XFRAME (WINDOW_FRAME (w));
11570 XRectangle clip_rect;
11571 int window_x, window_y, window_width, window_height;
11573 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11575 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11576 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11577 clip_rect.y = max (clip_rect.y, window_y);
11578 clip_rect.width = window_width;
11579 clip_rect.height = row->visible_height;
11581 /* If clipping to the whole line, including trunc marks, extend
11582 the rectangle to the left and increase its width. */
11583 if (whole_line_p)
11585 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11586 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11589 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11593 /* Draw a hollow box cursor on window W in glyph row ROW. */
11595 static void
11596 x_draw_hollow_cursor (w, row)
11597 struct window *w;
11598 struct glyph_row *row;
11600 struct frame *f = XFRAME (WINDOW_FRAME (w));
11601 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11602 Display *dpy = FRAME_X_DISPLAY (f);
11603 int x, y, wd, h;
11604 XGCValues xgcv;
11605 struct glyph *cursor_glyph;
11606 GC gc;
11608 /* Compute frame-relative coordinates from window-relative
11609 coordinates. */
11610 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11611 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11612 + row->ascent - w->phys_cursor_ascent);
11613 h = row->height - 1;
11615 /* Get the glyph the cursor is on. If we can't tell because
11616 the current matrix is invalid or such, give up. */
11617 cursor_glyph = get_phys_cursor_glyph (w);
11618 if (cursor_glyph == NULL)
11619 return;
11621 /* Compute the width of the rectangle to draw. If on a stretch
11622 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11623 rectangle as wide as the glyph, but use a canonical character
11624 width instead. */
11625 wd = cursor_glyph->pixel_width - 1;
11626 if (cursor_glyph->type == STRETCH_GLYPH
11627 && !x_stretch_cursor_p)
11628 wd = min (CANON_X_UNIT (f), wd);
11629 w->phys_cursor_width = wd;
11631 /* The foreground of cursor_gc is typically the same as the normal
11632 background color, which can cause the cursor box to be invisible. */
11633 xgcv.foreground = f->output_data.x->cursor_pixel;
11634 if (dpyinfo->scratch_cursor_gc)
11635 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11636 else
11637 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11638 GCForeground, &xgcv);
11639 gc = dpyinfo->scratch_cursor_gc;
11641 /* Set clipping, draw the rectangle, and reset clipping again. */
11642 x_clip_to_row (w, row, gc, 0);
11643 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11644 XSetClipMask (dpy, gc, None);
11648 /* Draw a bar cursor on window W in glyph row ROW.
11650 Implementation note: One would like to draw a bar cursor with an
11651 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11652 Unfortunately, I didn't find a font yet that has this property set.
11653 --gerd. */
11655 static void
11656 x_draw_bar_cursor (w, row, width, kind)
11657 struct window *w;
11658 struct glyph_row *row;
11659 int width;
11660 enum text_cursor_kinds kind;
11662 struct frame *f = XFRAME (w->frame);
11663 struct glyph *cursor_glyph;
11665 /* If cursor is out of bounds, don't draw garbage. This can happen
11666 in mini-buffer windows when switching between echo area glyphs
11667 and mini-buffer. */
11668 cursor_glyph = get_phys_cursor_glyph (w);
11669 if (cursor_glyph == NULL)
11670 return;
11672 /* If on an image, draw like a normal cursor. That's usually better
11673 visible than drawing a bar, esp. if the image is large so that
11674 the bar might not be in the window. */
11675 if (cursor_glyph->type == IMAGE_GLYPH)
11677 struct glyph_row *row;
11678 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11679 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11681 else
11683 Display *dpy = FRAME_X_DISPLAY (f);
11684 Window window = FRAME_X_WINDOW (f);
11685 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11686 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11687 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11688 XGCValues xgcv;
11690 /* If the glyph's background equals the color we normally draw
11691 the bar cursor in, the bar cursor in its normal color is
11692 invisible. Use the glyph's foreground color instead in this
11693 case, on the assumption that the glyph's colors are chosen so
11694 that the glyph is legible. */
11695 if (face->background == f->output_data.x->cursor_pixel)
11696 xgcv.background = xgcv.foreground = face->foreground;
11697 else
11698 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11699 xgcv.graphics_exposures = 0;
11701 if (gc)
11702 XChangeGC (dpy, gc, mask, &xgcv);
11703 else
11705 gc = XCreateGC (dpy, window, mask, &xgcv);
11706 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11709 if (width < 0)
11710 width = FRAME_CURSOR_WIDTH (f);
11711 width = min (cursor_glyph->pixel_width, width);
11713 w->phys_cursor_width = width;
11714 x_clip_to_row (w, row, gc, 0);
11716 if (kind == BAR_CURSOR)
11717 XFillRectangle (dpy, window, gc,
11718 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11719 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11720 width, row->height);
11721 else
11722 XFillRectangle (dpy, window, gc,
11723 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11724 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
11725 row->height - width),
11726 cursor_glyph->pixel_width,
11727 width);
11729 XSetClipMask (dpy, gc, None);
11734 /* Clear the cursor of window W to background color, and mark the
11735 cursor as not shown. This is used when the text where the cursor
11736 is is about to be rewritten. */
11738 static void
11739 x_clear_cursor (w)
11740 struct window *w;
11742 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11743 x_update_window_cursor (w, 0);
11747 /* Draw the cursor glyph of window W in glyph row ROW. See the
11748 comment of x_draw_glyphs for the meaning of HL. */
11750 static void
11751 x_draw_phys_cursor_glyph (w, row, hl)
11752 struct window *w;
11753 struct glyph_row *row;
11754 enum draw_glyphs_face hl;
11756 /* If cursor hpos is out of bounds, don't draw garbage. This can
11757 happen in mini-buffer windows when switching between echo area
11758 glyphs and mini-buffer. */
11759 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11761 int on_p = w->phys_cursor_on_p;
11762 int x1;
11764 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11765 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11766 hl, 0);
11767 w->phys_cursor_on_p = on_p;
11769 if (hl == DRAW_CURSOR)
11770 w->phys_cursor_width = x1 - w->phys_cursor.x;
11772 /* When we erase the cursor, and ROW is overlapped by other
11773 rows, make sure that these overlapping parts of other rows
11774 are redrawn. */
11775 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11777 if (row > w->current_matrix->rows
11778 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11779 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11781 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11782 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11783 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11789 /* Erase the image of a cursor of window W from the screen. */
11791 static void
11792 x_erase_phys_cursor (w)
11793 struct window *w;
11795 struct frame *f = XFRAME (w->frame);
11796 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11797 int hpos = w->phys_cursor.hpos;
11798 int vpos = w->phys_cursor.vpos;
11799 int mouse_face_here_p = 0;
11800 struct glyph_matrix *active_glyphs = w->current_matrix;
11801 struct glyph_row *cursor_row;
11802 struct glyph *cursor_glyph;
11803 enum draw_glyphs_face hl;
11805 /* No cursor displayed or row invalidated => nothing to do on the
11806 screen. */
11807 if (w->phys_cursor_type == NO_CURSOR)
11808 goto mark_cursor_off;
11810 /* VPOS >= active_glyphs->nrows means that window has been resized.
11811 Don't bother to erase the cursor. */
11812 if (vpos >= active_glyphs->nrows)
11813 goto mark_cursor_off;
11815 /* If row containing cursor is marked invalid, there is nothing we
11816 can do. */
11817 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11818 if (!cursor_row->enabled_p)
11819 goto mark_cursor_off;
11821 /* If row is completely invisible, don't attempt to delete a cursor which
11822 isn't there. This can happen if cursor is at top of a window, and
11823 we switch to a buffer with a header line in that window. */
11824 if (cursor_row->visible_height <= 0)
11825 goto mark_cursor_off;
11827 /* This can happen when the new row is shorter than the old one.
11828 In this case, either x_draw_glyphs or clear_end_of_line
11829 should have cleared the cursor. Note that we wouldn't be
11830 able to erase the cursor in this case because we don't have a
11831 cursor glyph at hand. */
11832 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11833 goto mark_cursor_off;
11835 /* If the cursor is in the mouse face area, redisplay that when
11836 we clear the cursor. */
11837 if (! NILP (dpyinfo->mouse_face_window)
11838 && w == XWINDOW (dpyinfo->mouse_face_window)
11839 && (vpos > dpyinfo->mouse_face_beg_row
11840 || (vpos == dpyinfo->mouse_face_beg_row
11841 && hpos >= dpyinfo->mouse_face_beg_col))
11842 && (vpos < dpyinfo->mouse_face_end_row
11843 || (vpos == dpyinfo->mouse_face_end_row
11844 && hpos < dpyinfo->mouse_face_end_col))
11845 /* Don't redraw the cursor's spot in mouse face if it is at the
11846 end of a line (on a newline). The cursor appears there, but
11847 mouse highlighting does not. */
11848 && cursor_row->used[TEXT_AREA] > hpos)
11849 mouse_face_here_p = 1;
11851 /* Maybe clear the display under the cursor. */
11852 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11854 int x;
11855 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11857 cursor_glyph = get_phys_cursor_glyph (w);
11858 if (cursor_glyph == NULL)
11859 goto mark_cursor_off;
11861 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11863 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11865 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11866 cursor_row->y)),
11867 cursor_glyph->pixel_width,
11868 cursor_row->visible_height,
11869 False);
11872 /* Erase the cursor by redrawing the character underneath it. */
11873 if (mouse_face_here_p)
11874 hl = DRAW_MOUSE_FACE;
11875 else
11876 hl = DRAW_NORMAL_TEXT;
11877 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11879 mark_cursor_off:
11880 w->phys_cursor_on_p = 0;
11881 w->phys_cursor_type = NO_CURSOR;
11885 /* Non-zero if physical cursor of window W is within mouse face. */
11887 static int
11888 cursor_in_mouse_face_p (w)
11889 struct window *w;
11891 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11892 int in_mouse_face = 0;
11894 if (WINDOWP (dpyinfo->mouse_face_window)
11895 && XWINDOW (dpyinfo->mouse_face_window) == w)
11897 int hpos = w->phys_cursor.hpos;
11898 int vpos = w->phys_cursor.vpos;
11900 if (vpos >= dpyinfo->mouse_face_beg_row
11901 && vpos <= dpyinfo->mouse_face_end_row
11902 && (vpos > dpyinfo->mouse_face_beg_row
11903 || hpos >= dpyinfo->mouse_face_beg_col)
11904 && (vpos < dpyinfo->mouse_face_end_row
11905 || hpos < dpyinfo->mouse_face_end_col
11906 || dpyinfo->mouse_face_past_end))
11907 in_mouse_face = 1;
11910 return in_mouse_face;
11914 /* Display or clear cursor of window W. If ON is zero, clear the
11915 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11916 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11918 void
11919 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11920 struct window *w;
11921 int on, hpos, vpos, x, y;
11923 struct frame *f = XFRAME (w->frame);
11924 int new_cursor_type;
11925 int new_cursor_width;
11926 int active_cursor;
11927 struct glyph_matrix *current_glyphs;
11928 struct glyph_row *glyph_row;
11929 struct glyph *glyph;
11931 /* This is pointless on invisible frames, and dangerous on garbaged
11932 windows and frames; in the latter case, the frame or window may
11933 be in the midst of changing its size, and x and y may be off the
11934 window. */
11935 if (! FRAME_VISIBLE_P (f)
11936 || FRAME_GARBAGED_P (f)
11937 || vpos >= w->current_matrix->nrows
11938 || hpos >= w->current_matrix->matrix_w)
11939 return;
11941 /* If cursor is off and we want it off, return quickly. */
11942 if (!on && !w->phys_cursor_on_p)
11943 return;
11945 current_glyphs = w->current_matrix;
11946 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11947 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11949 /* If cursor row is not enabled, we don't really know where to
11950 display the cursor. */
11951 if (!glyph_row->enabled_p)
11953 w->phys_cursor_on_p = 0;
11954 return;
11957 xassert (interrupt_input_blocked);
11959 /* Set new_cursor_type to the cursor we want to be displayed. */
11960 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
11962 /* If cursor is currently being shown and we don't want it to be or
11963 it is in the wrong place, or the cursor type is not what we want,
11964 erase it. */
11965 if (w->phys_cursor_on_p
11966 && (!on
11967 || w->phys_cursor.x != x
11968 || w->phys_cursor.y != y
11969 || new_cursor_type != w->phys_cursor_type
11970 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
11971 && new_cursor_width != w->phys_cursor_width)))
11972 x_erase_phys_cursor (w);
11974 /* Don't check phys_cursor_on_p here because that flag is only set
11975 to zero in some cases where we know that the cursor has been
11976 completely erased, to avoid the extra work of erasing the cursor
11977 twice. In other words, phys_cursor_on_p can be 1 and the cursor
11978 still not be visible, or it has only been partly erased. */
11979 if (on)
11981 w->phys_cursor_ascent = glyph_row->ascent;
11982 w->phys_cursor_height = glyph_row->height;
11984 /* Set phys_cursor_.* before x_draw_.* is called because some
11985 of them may need the information. */
11986 w->phys_cursor.x = x;
11987 w->phys_cursor.y = glyph_row->y;
11988 w->phys_cursor.hpos = hpos;
11989 w->phys_cursor.vpos = vpos;
11990 w->phys_cursor_type = new_cursor_type;
11991 w->phys_cursor_on_p = 1;
11993 switch (new_cursor_type)
11995 case HOLLOW_BOX_CURSOR:
11996 x_draw_hollow_cursor (w, glyph_row);
11997 break;
11999 case FILLED_BOX_CURSOR:
12000 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
12001 break;
12003 case BAR_CURSOR:
12004 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
12005 break;
12007 case HBAR_CURSOR:
12008 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
12009 break;
12011 case NO_CURSOR:
12012 w->phys_cursor_width = 0;
12013 break;
12015 default:
12016 abort ();
12019 #ifdef HAVE_X_I18N
12020 if (w == XWINDOW (f->selected_window))
12021 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
12022 xic_set_preeditarea (w, x, y);
12023 #endif
12026 #ifndef XFlush
12027 if (updating_frame != f)
12028 XFlush (FRAME_X_DISPLAY (f));
12029 #endif
12033 /* Display the cursor on window W, or clear it. X and Y are window
12034 relative pixel coordinates. HPOS and VPOS are glyph matrix
12035 positions. If W is not the selected window, display a hollow
12036 cursor. ON non-zero means display the cursor at X, Y which
12037 correspond to HPOS, VPOS, otherwise it is cleared. */
12039 void
12040 x_display_cursor (w, on, hpos, vpos, x, y)
12041 struct window *w;
12042 int on, hpos, vpos, x, y;
12044 BLOCK_INPUT;
12045 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
12046 UNBLOCK_INPUT;
12050 /* Display the cursor on window W, or clear it, according to ON_P.
12051 Don't change the cursor's position. */
12053 void
12054 x_update_cursor (f, on_p)
12055 struct frame *f;
12056 int on_p;
12058 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
12062 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
12063 in the window tree rooted at W. */
12065 static void
12066 x_update_cursor_in_window_tree (w, on_p)
12067 struct window *w;
12068 int on_p;
12070 while (w)
12072 if (!NILP (w->hchild))
12073 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
12074 else if (!NILP (w->vchild))
12075 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
12076 else
12077 x_update_window_cursor (w, on_p);
12079 w = NILP (w->next) ? 0 : XWINDOW (w->next);
12084 /* Switch the display of W's cursor on or off, according to the value
12085 of ON. */
12087 static void
12088 x_update_window_cursor (w, on)
12089 struct window *w;
12090 int on;
12092 /* Don't update cursor in windows whose frame is in the process
12093 of being deleted. */
12094 if (w->current_matrix)
12096 BLOCK_INPUT;
12097 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
12098 w->phys_cursor.x, w->phys_cursor.y);
12099 UNBLOCK_INPUT;
12106 /* Icons. */
12108 /* Make the x-window of frame F use the gnu icon bitmap. */
12111 x_bitmap_icon (f, file)
12112 struct frame *f;
12113 Lisp_Object file;
12115 int bitmap_id;
12117 if (FRAME_X_WINDOW (f) == 0)
12118 return 1;
12120 /* Free up our existing icon bitmap if any. */
12121 if (f->output_data.x->icon_bitmap > 0)
12122 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12123 f->output_data.x->icon_bitmap = 0;
12125 if (STRINGP (file))
12126 bitmap_id = x_create_bitmap_from_file (f, file);
12127 else
12129 /* Create the GNU bitmap if necessary. */
12130 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
12131 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
12132 = x_create_bitmap_from_data (f, gnu_bits,
12133 gnu_width, gnu_height);
12135 /* The first time we create the GNU bitmap,
12136 this increments the ref-count one extra time.
12137 As a result, the GNU bitmap is never freed.
12138 That way, we don't have to worry about allocating it again. */
12139 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
12141 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
12144 x_wm_set_icon_pixmap (f, bitmap_id);
12145 f->output_data.x->icon_bitmap = bitmap_id;
12147 return 0;
12151 /* Make the x-window of frame F use a rectangle with text.
12152 Use ICON_NAME as the text. */
12155 x_text_icon (f, icon_name)
12156 struct frame *f;
12157 char *icon_name;
12159 if (FRAME_X_WINDOW (f) == 0)
12160 return 1;
12162 #ifdef HAVE_X11R4
12164 XTextProperty text;
12165 text.value = (unsigned char *) icon_name;
12166 text.encoding = XA_STRING;
12167 text.format = 8;
12168 text.nitems = strlen (icon_name);
12169 #ifdef USE_X_TOOLKIT
12170 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12171 &text);
12172 #else /* not USE_X_TOOLKIT */
12173 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
12174 #endif /* not USE_X_TOOLKIT */
12176 #else /* not HAVE_X11R4 */
12177 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
12178 #endif /* not HAVE_X11R4 */
12180 if (f->output_data.x->icon_bitmap > 0)
12181 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12182 f->output_data.x->icon_bitmap = 0;
12183 x_wm_set_icon_pixmap (f, 0);
12185 return 0;
12188 #define X_ERROR_MESSAGE_SIZE 200
12190 /* If non-nil, this should be a string.
12191 It means catch X errors and store the error message in this string. */
12193 static Lisp_Object x_error_message_string;
12195 /* An X error handler which stores the error message in
12196 x_error_message_string. This is called from x_error_handler if
12197 x_catch_errors is in effect. */
12199 static void
12200 x_error_catcher (display, error)
12201 Display *display;
12202 XErrorEvent *error;
12204 XGetErrorText (display, error->error_code,
12205 SDATA (x_error_message_string),
12206 X_ERROR_MESSAGE_SIZE);
12209 /* Begin trapping X errors for display DPY. Actually we trap X errors
12210 for all displays, but DPY should be the display you are actually
12211 operating on.
12213 After calling this function, X protocol errors no longer cause
12214 Emacs to exit; instead, they are recorded in the string
12215 stored in x_error_message_string.
12217 Calling x_check_errors signals an Emacs error if an X error has
12218 occurred since the last call to x_catch_errors or x_check_errors.
12220 Calling x_uncatch_errors resumes the normal error handling. */
12222 void x_check_errors ();
12223 static Lisp_Object x_catch_errors_unwind ();
12226 x_catch_errors (dpy)
12227 Display *dpy;
12229 int count = SPECPDL_INDEX ();
12231 /* Make sure any errors from previous requests have been dealt with. */
12232 XSync (dpy, False);
12234 record_unwind_protect (x_catch_errors_unwind,
12235 Fcons (make_save_value (dpy, 0),
12236 x_error_message_string));
12238 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
12239 SSET (x_error_message_string, 0, 0);
12241 return count;
12244 /* Unbind the binding that we made to check for X errors. */
12246 static Lisp_Object
12247 x_catch_errors_unwind (old_val)
12248 Lisp_Object old_val;
12250 Lisp_Object first;
12252 first = XCAR (old_val);
12254 XSync (XSAVE_VALUE (first)->pointer, False);
12256 x_error_message_string = XCDR (old_val);
12257 return Qnil;
12260 /* If any X protocol errors have arrived since the last call to
12261 x_catch_errors or x_check_errors, signal an Emacs error using
12262 sprintf (a buffer, FORMAT, the x error message text) as the text. */
12264 void
12265 x_check_errors (dpy, format)
12266 Display *dpy;
12267 char *format;
12269 /* Make sure to catch any errors incurred so far. */
12270 XSync (dpy, False);
12272 if (SREF (x_error_message_string, 0))
12273 error (format, SDATA (x_error_message_string));
12276 /* Nonzero if we had any X protocol errors
12277 since we did x_catch_errors on DPY. */
12280 x_had_errors_p (dpy)
12281 Display *dpy;
12283 /* Make sure to catch any errors incurred so far. */
12284 XSync (dpy, False);
12286 return SREF (x_error_message_string, 0) != 0;
12289 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
12291 void
12292 x_clear_errors (dpy)
12293 Display *dpy;
12295 SSET (x_error_message_string, 0, 0);
12298 /* Stop catching X protocol errors and let them make Emacs die.
12299 DPY should be the display that was passed to x_catch_errors.
12300 COUNT should be the value that was returned by
12301 the corresponding call to x_catch_errors. */
12303 void
12304 x_uncatch_errors (dpy, count)
12305 Display *dpy;
12306 int count;
12308 unbind_to (count, Qnil);
12311 #if 0
12312 static unsigned int x_wire_count;
12313 x_trace_wire ()
12315 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
12317 #endif /* ! 0 */
12320 /* Handle SIGPIPE, which can happen when the connection to a server
12321 simply goes away. SIGPIPE is handled by x_connection_signal.
12322 Don't need to do anything, because the write which caused the
12323 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12324 which will do the appropriate cleanup for us. */
12326 static SIGTYPE
12327 x_connection_signal (signalnum) /* If we don't have an argument, */
12328 int signalnum; /* some compilers complain in signal calls. */
12330 #ifdef USG
12331 /* USG systems forget handlers when they are used;
12332 must reestablish each time */
12333 signal (signalnum, x_connection_signal);
12334 #endif /* USG */
12338 /************************************************************************
12339 Handling X errors
12340 ************************************************************************/
12342 /* Error message passed to x_connection_closed. */
12344 static char *error_msg;
12346 /* Function installed as fatal_error_signal_hook in
12347 x_connection_closed. Print the X error message, and exit normally,
12348 instead of dumping core when XtCloseDisplay fails. */
12350 static void
12351 x_fatal_error_signal ()
12353 fprintf (stderr, "%s\n", error_msg);
12354 exit (70);
12357 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12358 the text of an error message that lead to the connection loss. */
12360 static SIGTYPE
12361 x_connection_closed (dpy, error_message)
12362 Display *dpy;
12363 char *error_message;
12365 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
12366 Lisp_Object frame, tail;
12367 int count;
12369 error_msg = (char *) alloca (strlen (error_message) + 1);
12370 strcpy (error_msg, error_message);
12371 handling_signal = 0;
12373 /* Prevent being called recursively because of an error condition
12374 below. Otherwise, we might end up with printing ``can't find per
12375 display information'' in the recursive call instead of printing
12376 the original message here. */
12377 count = x_catch_errors (dpy);
12379 /* We have to close the display to inform Xt that it doesn't
12380 exist anymore. If we don't, Xt will continue to wait for
12381 events from the display. As a consequence, a sequence of
12383 M-x make-frame-on-display RET :1 RET
12384 ...kill the new frame, so that we get an IO error...
12385 M-x make-frame-on-display RET :1 RET
12387 will indefinitely wait in Xt for events for display `:1', opened
12388 in the first class to make-frame-on-display.
12390 Closing the display is reported to lead to a bus error on
12391 OpenWindows in certain situations. I suspect that is a bug
12392 in OpenWindows. I don't know how to cicumvent it here. */
12394 #ifdef USE_X_TOOLKIT
12395 /* If DPYINFO is null, this means we didn't open the display
12396 in the first place, so don't try to close it. */
12397 if (dpyinfo)
12399 extern void (*fatal_error_signal_hook) P_ ((void));
12400 fatal_error_signal_hook = x_fatal_error_signal;
12401 XtCloseDisplay (dpy);
12402 fatal_error_signal_hook = NULL;
12404 #endif
12406 /* Indicate that this display is dead. */
12407 if (dpyinfo)
12408 dpyinfo->display = 0;
12410 /* First delete frames whose mini-buffers are on frames
12411 that are on the dead display. */
12412 FOR_EACH_FRAME (tail, frame)
12414 Lisp_Object minibuf_frame;
12415 minibuf_frame
12416 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
12417 if (FRAME_X_P (XFRAME (frame))
12418 && FRAME_X_P (XFRAME (minibuf_frame))
12419 && ! EQ (frame, minibuf_frame)
12420 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
12421 Fdelete_frame (frame, Qt);
12424 /* Now delete all remaining frames on the dead display.
12425 We are now sure none of these is used as the mini-buffer
12426 for another frame that we need to delete. */
12427 FOR_EACH_FRAME (tail, frame)
12428 if (FRAME_X_P (XFRAME (frame))
12429 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12431 /* Set this to t so that Fdelete_frame won't get confused
12432 trying to find a replacement. */
12433 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12434 Fdelete_frame (frame, Qt);
12437 if (dpyinfo)
12438 x_delete_display (dpyinfo);
12440 x_uncatch_errors (dpy, count);
12442 if (x_display_list == 0)
12444 fprintf (stderr, "%s\n", error_msg);
12445 shut_down_emacs (0, 0, Qnil);
12446 exit (70);
12449 /* Ordinary stack unwind doesn't deal with these. */
12450 #ifdef SIGIO
12451 sigunblock (sigmask (SIGIO));
12452 #endif
12453 sigunblock (sigmask (SIGALRM));
12454 TOTALLY_UNBLOCK_INPUT;
12456 clear_waiting_for_input ();
12457 error ("%s", error_msg);
12461 /* This is the usual handler for X protocol errors.
12462 It kills all frames on the display that we got the error for.
12463 If that was the only one, it prints an error message and kills Emacs. */
12465 static void
12466 x_error_quitter (display, error)
12467 Display *display;
12468 XErrorEvent *error;
12470 char buf[256], buf1[356];
12472 /* Note that there is no real way portable across R3/R4 to get the
12473 original error handler. */
12475 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12476 sprintf (buf1, "X protocol error: %s on protocol request %d",
12477 buf, error->request_code);
12478 x_connection_closed (display, buf1);
12482 /* This is the first-level handler for X protocol errors.
12483 It calls x_error_quitter or x_error_catcher. */
12485 static int
12486 x_error_handler (display, error)
12487 Display *display;
12488 XErrorEvent *error;
12490 if (! NILP (x_error_message_string))
12491 x_error_catcher (display, error);
12492 else
12493 x_error_quitter (display, error);
12494 return 0;
12497 /* This is the handler for X IO errors, always.
12498 It kills all frames on the display that we lost touch with.
12499 If that was the only one, it prints an error message and kills Emacs. */
12501 static int
12502 x_io_error_quitter (display)
12503 Display *display;
12505 char buf[256];
12507 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12508 x_connection_closed (display, buf);
12509 return 0;
12512 /* Changing the font of the frame. */
12514 /* Give frame F the font named FONTNAME as its default font, and
12515 return the full name of that font. FONTNAME may be a wildcard
12516 pattern; in that case, we choose some font that fits the pattern.
12517 The return value shows which font we chose. */
12519 Lisp_Object
12520 x_new_font (f, fontname)
12521 struct frame *f;
12522 register char *fontname;
12524 struct font_info *fontp
12525 = FS_LOAD_FONT (f, 0, fontname, -1);
12527 if (!fontp)
12528 return Qnil;
12530 f->output_data.x->font = (XFontStruct *) (fontp->font);
12531 f->output_data.x->baseline_offset = fontp->baseline_offset;
12532 f->output_data.x->fontset = -1;
12534 x_compute_fringe_widths (f, 1);
12536 /* Compute the scroll bar width in character columns. */
12537 if (f->scroll_bar_pixel_width > 0)
12539 int wid = FONT_WIDTH (f->output_data.x->font);
12540 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12542 else
12544 int wid = FONT_WIDTH (f->output_data.x->font);
12545 f->scroll_bar_cols = (14 + wid - 1) / wid;
12548 /* Now make the frame display the given font. */
12549 if (FRAME_X_WINDOW (f) != 0)
12551 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12552 f->output_data.x->font->fid);
12553 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12554 f->output_data.x->font->fid);
12555 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12556 f->output_data.x->font->fid);
12558 frame_update_line_height (f);
12560 /* Don't change the size of a tip frame; there's no point in
12561 doing it because it's done in Fx_show_tip, and it leads to
12562 problems because the tip frame has no widget. */
12563 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12564 x_set_window_size (f, 0, f->width, f->height);
12566 else
12567 /* If we are setting a new frame's font for the first time,
12568 there are no faces yet, so this font's height is the line height. */
12569 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12571 return build_string (fontp->full_name);
12574 /* Give frame F the fontset named FONTSETNAME as its default font, and
12575 return the full name of that fontset. FONTSETNAME may be a wildcard
12576 pattern; in that case, we choose some fontset that fits the pattern.
12577 The return value shows which fontset we chose. */
12579 Lisp_Object
12580 x_new_fontset (f, fontsetname)
12581 struct frame *f;
12582 char *fontsetname;
12584 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12585 Lisp_Object result;
12587 if (fontset < 0)
12588 return Qnil;
12590 if (f->output_data.x->fontset == fontset)
12591 /* This fontset is already set in frame F. There's nothing more
12592 to do. */
12593 return fontset_name (fontset);
12595 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
12597 if (!STRINGP (result))
12598 /* Can't load ASCII font. */
12599 return Qnil;
12601 /* Since x_new_font doesn't update any fontset information, do it now. */
12602 f->output_data.x->fontset = fontset;
12604 #ifdef HAVE_X_I18N
12605 if (FRAME_XIC (f)
12606 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12607 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
12608 #endif
12610 return build_string (fontsetname);
12613 /* Compute actual fringe widths */
12615 void
12616 x_compute_fringe_widths (f, redraw)
12617 struct frame *f;
12618 int redraw;
12620 int o_left = f->output_data.x->left_fringe_width;
12621 int o_right = f->output_data.x->right_fringe_width;
12622 int o_cols = f->output_data.x->fringe_cols;
12624 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12625 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12626 int left_fringe_width, right_fringe_width;
12628 if (!NILP (left_fringe))
12629 left_fringe = Fcdr (left_fringe);
12630 if (!NILP (right_fringe))
12631 right_fringe = Fcdr (right_fringe);
12633 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12634 XINT (left_fringe));
12635 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12636 XINT (right_fringe));
12638 if (left_fringe_width || right_fringe_width)
12640 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12641 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12642 int conf_wid = left_wid + right_wid;
12643 int font_wid = FONT_WIDTH (f->output_data.x->font);
12644 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12645 int real_wid = cols * font_wid;
12646 if (left_wid && right_wid)
12648 if (left_fringe_width < 0)
12650 /* Left fringe width is fixed, adjust right fringe if necessary */
12651 f->output_data.x->left_fringe_width = left_wid;
12652 f->output_data.x->right_fringe_width = real_wid - left_wid;
12654 else if (right_fringe_width < 0)
12656 /* Right fringe width is fixed, adjust left fringe if necessary */
12657 f->output_data.x->left_fringe_width = real_wid - right_wid;
12658 f->output_data.x->right_fringe_width = right_wid;
12660 else
12662 /* Adjust both fringes with an equal amount.
12663 Note that we are doing integer arithmetic here, so don't
12664 lose a pixel if the total width is an odd number. */
12665 int fill = real_wid - conf_wid;
12666 f->output_data.x->left_fringe_width = left_wid + fill/2;
12667 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12670 else if (left_fringe_width)
12672 f->output_data.x->left_fringe_width = real_wid;
12673 f->output_data.x->right_fringe_width = 0;
12675 else
12677 f->output_data.x->left_fringe_width = 0;
12678 f->output_data.x->right_fringe_width = real_wid;
12680 f->output_data.x->fringe_cols = cols;
12681 f->output_data.x->fringes_extra = real_wid;
12683 else
12685 f->output_data.x->left_fringe_width = 0;
12686 f->output_data.x->right_fringe_width = 0;
12687 f->output_data.x->fringe_cols = 0;
12688 f->output_data.x->fringes_extra = 0;
12691 if (redraw && FRAME_VISIBLE_P (f))
12692 if (o_left != f->output_data.x->left_fringe_width ||
12693 o_right != f->output_data.x->right_fringe_width ||
12694 o_cols != f->output_data.x->fringe_cols)
12695 redraw_frame (f);
12698 /***********************************************************************
12699 X Input Methods
12700 ***********************************************************************/
12702 #ifdef HAVE_X_I18N
12704 #ifdef HAVE_X11R6
12706 /* XIM destroy callback function, which is called whenever the
12707 connection to input method XIM dies. CLIENT_DATA contains a
12708 pointer to the x_display_info structure corresponding to XIM. */
12710 static void
12711 xim_destroy_callback (xim, client_data, call_data)
12712 XIM xim;
12713 XPointer client_data;
12714 XPointer call_data;
12716 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12717 Lisp_Object frame, tail;
12719 BLOCK_INPUT;
12721 /* No need to call XDestroyIC.. */
12722 FOR_EACH_FRAME (tail, frame)
12724 struct frame *f = XFRAME (frame);
12725 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12727 FRAME_XIC (f) = NULL;
12728 if (FRAME_XIC_FONTSET (f))
12730 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12731 FRAME_XIC_FONTSET (f) = NULL;
12736 /* No need to call XCloseIM. */
12737 dpyinfo->xim = NULL;
12738 XFree (dpyinfo->xim_styles);
12739 UNBLOCK_INPUT;
12742 #endif /* HAVE_X11R6 */
12744 #ifdef HAVE_X11R6
12745 /* This isn't prototyped in OSF 5.0 or 5.1a. */
12746 extern char *XSetIMValues P_ ((XIM, ...));
12747 #endif
12749 /* Open the connection to the XIM server on display DPYINFO.
12750 RESOURCE_NAME is the resource name Emacs uses. */
12752 static void
12753 xim_open_dpy (dpyinfo, resource_name)
12754 struct x_display_info *dpyinfo;
12755 char *resource_name;
12757 #ifdef USE_XIM
12758 XIM xim;
12760 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12761 dpyinfo->xim = xim;
12763 if (xim)
12765 #ifdef HAVE_X11R6
12766 XIMCallback destroy;
12767 #endif
12769 /* Get supported styles and XIM values. */
12770 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12772 #ifdef HAVE_X11R6
12773 destroy.callback = xim_destroy_callback;
12774 destroy.client_data = (XPointer)dpyinfo;
12775 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12776 #endif
12779 #else /* not USE_XIM */
12780 dpyinfo->xim = NULL;
12781 #endif /* not USE_XIM */
12785 #ifdef HAVE_X11R6_XIM
12787 struct xim_inst_t
12789 struct x_display_info *dpyinfo;
12790 char *resource_name;
12793 /* XIM instantiate callback function, which is called whenever an XIM
12794 server is available. DISPLAY is teh display of the XIM.
12795 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12796 when the callback was registered. */
12798 static void
12799 xim_instantiate_callback (display, client_data, call_data)
12800 Display *display;
12801 XPointer client_data;
12802 XPointer call_data;
12804 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12805 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12807 /* We don't support multiple XIM connections. */
12808 if (dpyinfo->xim)
12809 return;
12811 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12813 /* Create XIC for the existing frames on the same display, as long
12814 as they have no XIC. */
12815 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12817 Lisp_Object tail, frame;
12819 BLOCK_INPUT;
12820 FOR_EACH_FRAME (tail, frame)
12822 struct frame *f = XFRAME (frame);
12824 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12825 if (FRAME_XIC (f) == NULL)
12827 create_frame_xic (f);
12828 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12829 xic_set_statusarea (f);
12830 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12832 struct window *w = XWINDOW (f->selected_window);
12833 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12838 UNBLOCK_INPUT;
12842 #endif /* HAVE_X11R6_XIM */
12845 /* Open a connection to the XIM server on display DPYINFO.
12846 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12847 connection only at the first time. On X11R6, open the connection
12848 in the XIM instantiate callback function. */
12850 static void
12851 xim_initialize (dpyinfo, resource_name)
12852 struct x_display_info *dpyinfo;
12853 char *resource_name;
12855 #ifdef USE_XIM
12856 #ifdef HAVE_X11R6_XIM
12857 struct xim_inst_t *xim_inst;
12858 int len;
12860 dpyinfo->xim = NULL;
12861 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12862 xim_inst->dpyinfo = dpyinfo;
12863 len = strlen (resource_name);
12864 xim_inst->resource_name = (char *) xmalloc (len + 1);
12865 bcopy (resource_name, xim_inst->resource_name, len + 1);
12866 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12867 resource_name, EMACS_CLASS,
12868 xim_instantiate_callback,
12869 /* Fixme: This is XPointer in
12870 XFree86 but (XPointer *) on
12871 Tru64, at least. */
12872 (XPointer) xim_inst);
12873 #else /* not HAVE_X11R6_XIM */
12874 dpyinfo->xim = NULL;
12875 xim_open_dpy (dpyinfo, resource_name);
12876 #endif /* not HAVE_X11R6_XIM */
12878 #else /* not USE_XIM */
12879 dpyinfo->xim = NULL;
12880 #endif /* not USE_XIM */
12884 /* Close the connection to the XIM server on display DPYINFO. */
12886 static void
12887 xim_close_dpy (dpyinfo)
12888 struct x_display_info *dpyinfo;
12890 #ifdef USE_XIM
12891 #ifdef HAVE_X11R6_XIM
12892 if (dpyinfo->display)
12893 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12894 NULL, EMACS_CLASS,
12895 xim_instantiate_callback, NULL);
12896 #endif /* not HAVE_X11R6_XIM */
12897 if (dpyinfo->display)
12898 XCloseIM (dpyinfo->xim);
12899 dpyinfo->xim = NULL;
12900 XFree (dpyinfo->xim_styles);
12901 #endif /* USE_XIM */
12904 #endif /* not HAVE_X11R6_XIM */
12908 /* Calculate the absolute position in frame F
12909 from its current recorded position values and gravity. */
12911 void
12912 x_calc_absolute_position (f)
12913 struct frame *f;
12915 Window child;
12916 int win_x = 0, win_y = 0;
12917 int flags = f->output_data.x->size_hint_flags;
12918 int this_window;
12920 /* We have nothing to do if the current position
12921 is already for the top-left corner. */
12922 if (! ((flags & XNegative) || (flags & YNegative)))
12923 return;
12925 #ifdef USE_X_TOOLKIT
12926 this_window = XtWindow (f->output_data.x->widget);
12927 #else
12928 this_window = FRAME_X_WINDOW (f);
12929 #endif
12931 /* Find the position of the outside upper-left corner of
12932 the inner window, with respect to the outer window.
12933 But do this only if we will need the results. */
12934 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12936 int count;
12938 BLOCK_INPUT;
12939 count = x_catch_errors (FRAME_X_DISPLAY (f));
12940 while (1)
12942 x_clear_errors (FRAME_X_DISPLAY (f));
12943 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12945 /* From-window, to-window. */
12946 this_window,
12947 f->output_data.x->parent_desc,
12949 /* From-position, to-position. */
12950 0, 0, &win_x, &win_y,
12952 /* Child of win. */
12953 &child);
12954 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12956 Window newroot, newparent = 0xdeadbeef;
12957 Window *newchildren;
12958 unsigned int nchildren;
12960 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12961 &newparent, &newchildren, &nchildren))
12962 break;
12964 XFree ((char *) newchildren);
12966 f->output_data.x->parent_desc = newparent;
12968 else
12969 break;
12972 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12973 UNBLOCK_INPUT;
12976 /* Treat negative positions as relative to the leftmost bottommost
12977 position that fits on the screen. */
12978 if (flags & XNegative)
12979 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12980 - 2 * f->output_data.x->border_width - win_x
12981 - PIXEL_WIDTH (f)
12982 + f->output_data.x->left_pos);
12985 int height = PIXEL_HEIGHT (f);
12987 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12988 /* Something is fishy here. When using Motif, starting Emacs with
12989 `-g -0-0', the frame appears too low by a few pixels.
12991 This seems to be so because initially, while Emacs is starting,
12992 the column widget's height and the frame's pixel height are
12993 different. The column widget's height is the right one. In
12994 later invocations, when Emacs is up, the frame's pixel height
12995 is right, though.
12997 It's not obvious where the initial small difference comes from.
12998 2000-12-01, gerd. */
13000 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
13001 #endif
13003 if (flags & YNegative)
13004 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
13005 - 2 * f->output_data.x->border_width
13006 - win_y
13007 - height
13008 + f->output_data.x->top_pos);
13011 /* The left_pos and top_pos
13012 are now relative to the top and left screen edges,
13013 so the flags should correspond. */
13014 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
13017 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
13018 to really change the position, and 0 when calling from
13019 x_make_frame_visible (in that case, XOFF and YOFF are the current
13020 position values). It is -1 when calling from x_set_frame_parameters,
13021 which means, do adjust for borders but don't change the gravity. */
13023 void
13024 x_set_offset (f, xoff, yoff, change_gravity)
13025 struct frame *f;
13026 register int xoff, yoff;
13027 int change_gravity;
13029 int modified_top, modified_left;
13031 if (change_gravity > 0)
13033 f->output_data.x->top_pos = yoff;
13034 f->output_data.x->left_pos = xoff;
13035 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
13036 if (xoff < 0)
13037 f->output_data.x->size_hint_flags |= XNegative;
13038 if (yoff < 0)
13039 f->output_data.x->size_hint_flags |= YNegative;
13040 f->output_data.x->win_gravity = NorthWestGravity;
13042 x_calc_absolute_position (f);
13044 BLOCK_INPUT;
13045 x_wm_set_size_hint (f, (long) 0, 0);
13047 modified_left = f->output_data.x->left_pos;
13048 modified_top = f->output_data.x->top_pos;
13049 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
13050 this seems to be unnecessary and incorrect. rms, 4/17/97. */
13051 /* It is a mystery why we need to add the border_width here
13052 when the frame is already visible, but experiment says we do. */
13053 if (change_gravity != 0)
13055 modified_left += f->output_data.x->border_width;
13056 modified_top += f->output_data.x->border_width;
13058 #endif
13060 #ifdef USE_X_TOOLKIT
13061 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
13062 modified_left, modified_top);
13063 #else /* not USE_X_TOOLKIT */
13064 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13065 modified_left, modified_top);
13066 #endif /* not USE_X_TOOLKIT */
13067 UNBLOCK_INPUT;
13070 /* Check if we need to resize the frame due to a fullscreen request.
13071 If so needed, resize the frame. */
13072 static void
13073 x_check_fullscreen (f)
13074 struct frame *f;
13076 if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
13078 int width, height, ign;
13080 x_real_positions (f, &f->output_data.x->left_pos,
13081 &f->output_data.x->top_pos);
13083 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
13085 /* We do not need to move the window, it shall be taken care of
13086 when setting WM manager hints.
13087 If the frame is visible already, the position is checked by
13088 x_check_fullscreen_move. */
13089 if (f->width != width || f->height != height)
13091 change_frame_size (f, height, width, 0, 1, 0);
13092 SET_FRAME_GARBAGED (f);
13093 cancel_mouse_face (f);
13095 /* Wait for the change of frame size to occur */
13096 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
13102 /* If frame parameters are set after the frame is mapped, we need to move
13103 the window. This is done in xfns.c.
13104 Some window managers moves the window to the right position, some
13105 moves the outer window manager window to the specified position.
13106 Here we check that we are in the right spot. If not, make a second
13107 move, assuming we are dealing with the second kind of window manager. */
13108 static void
13109 x_check_fullscreen_move (f)
13110 struct frame *f;
13112 if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
13114 int expect_top = f->output_data.x->top_pos;
13115 int expect_left = f->output_data.x->left_pos;
13117 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13118 expect_top = 0;
13119 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13120 expect_left = 0;
13122 if (expect_top != f->output_data.x->top_pos
13123 || expect_left != f->output_data.x->left_pos)
13124 x_set_offset (f, expect_left, expect_top, 1);
13126 /* Just do this once */
13127 f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
13132 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
13133 wanted positions of the WM window (not emacs window).
13134 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
13135 window (FRAME_X_WINDOW).
13137 void
13138 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
13139 struct frame *f;
13140 int *width;
13141 int *height;
13142 int *top_pos;
13143 int *left_pos;
13145 int newwidth = f->width, newheight = f->height;
13147 *top_pos = f->output_data.x->top_pos;
13148 *left_pos = f->output_data.x->left_pos;
13150 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13152 int ph;
13154 ph = FRAME_X_DISPLAY_INFO (f)->height;
13155 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13156 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
13157 - f->output_data.x->y_pixels_diff;
13158 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13159 *top_pos = 0;
13162 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13164 int pw;
13166 pw = FRAME_X_DISPLAY_INFO (f)->width;
13167 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13168 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
13169 - f->output_data.x->x_pixels_diff;
13170 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13171 *left_pos = 0;
13174 *width = newwidth;
13175 *height = newheight;
13179 /* Change the size of frame F's X window to COLS/ROWS in the case F
13180 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
13181 top-left-corner window gravity for this size change and subsequent
13182 size changes. Otherwise we leave the window gravity unchanged. */
13184 static void
13185 x_set_window_size_1 (f, change_gravity, cols, rows)
13186 struct frame *f;
13187 int change_gravity;
13188 int cols, rows;
13190 int pixelwidth, pixelheight;
13192 check_frame_size (f, &rows, &cols);
13193 f->output_data.x->vertical_scroll_bar_extra
13194 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
13196 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
13197 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
13198 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
13200 x_compute_fringe_widths (f, 0);
13202 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
13203 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
13205 f->output_data.x->win_gravity = NorthWestGravity;
13206 x_wm_set_size_hint (f, (long) 0, 0);
13208 XSync (FRAME_X_DISPLAY (f), False);
13209 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13210 pixelwidth, pixelheight);
13212 /* Now, strictly speaking, we can't be sure that this is accurate,
13213 but the window manager will get around to dealing with the size
13214 change request eventually, and we'll hear how it went when the
13215 ConfigureNotify event gets here.
13217 We could just not bother storing any of this information here,
13218 and let the ConfigureNotify event set everything up, but that
13219 might be kind of confusing to the Lisp code, since size changes
13220 wouldn't be reported in the frame parameters until some random
13221 point in the future when the ConfigureNotify event arrives.
13223 We pass 1 for DELAY since we can't run Lisp code inside of
13224 a BLOCK_INPUT. */
13225 change_frame_size (f, rows, cols, 0, 1, 0);
13226 PIXEL_WIDTH (f) = pixelwidth;
13227 PIXEL_HEIGHT (f) = pixelheight;
13229 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
13230 receive in the ConfigureNotify event; if we get what we asked
13231 for, then the event won't cause the screen to become garbaged, so
13232 we have to make sure to do it here. */
13233 SET_FRAME_GARBAGED (f);
13235 XFlush (FRAME_X_DISPLAY (f));
13239 /* Call this to change the size of frame F's x-window.
13240 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
13241 for this size change and subsequent size changes.
13242 Otherwise we leave the window gravity unchanged. */
13244 void
13245 x_set_window_size (f, change_gravity, cols, rows)
13246 struct frame *f;
13247 int change_gravity;
13248 int cols, rows;
13250 BLOCK_INPUT;
13252 #ifdef USE_X_TOOLKIT
13254 if (f->output_data.x->widget != NULL)
13256 /* The x and y position of the widget is clobbered by the
13257 call to XtSetValues within EmacsFrameSetCharSize.
13258 This is a real kludge, but I don't understand Xt so I can't
13259 figure out a correct fix. Can anyone else tell me? -- rms. */
13260 int xpos = f->output_data.x->widget->core.x;
13261 int ypos = f->output_data.x->widget->core.y;
13262 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
13263 f->output_data.x->widget->core.x = xpos;
13264 f->output_data.x->widget->core.y = ypos;
13266 else
13267 x_set_window_size_1 (f, change_gravity, cols, rows);
13269 #else /* not USE_X_TOOLKIT */
13271 x_set_window_size_1 (f, change_gravity, cols, rows);
13273 #endif /* not USE_X_TOOLKIT */
13275 /* If cursor was outside the new size, mark it as off. */
13276 mark_window_cursors_off (XWINDOW (f->root_window));
13278 /* Clear out any recollection of where the mouse highlighting was,
13279 since it might be in a place that's outside the new frame size.
13280 Actually checking whether it is outside is a pain in the neck,
13281 so don't try--just let the highlighting be done afresh with new size. */
13282 cancel_mouse_face (f);
13284 UNBLOCK_INPUT;
13287 /* Mouse warping. */
13289 void
13290 x_set_mouse_position (f, x, y)
13291 struct frame *f;
13292 int x, y;
13294 int pix_x, pix_y;
13296 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
13297 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
13299 if (pix_x < 0) pix_x = 0;
13300 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
13302 if (pix_y < 0) pix_y = 0;
13303 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
13305 BLOCK_INPUT;
13307 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13308 0, 0, 0, 0, pix_x, pix_y);
13309 UNBLOCK_INPUT;
13312 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13314 void
13315 x_set_mouse_pixel_position (f, pix_x, pix_y)
13316 struct frame *f;
13317 int pix_x, pix_y;
13319 BLOCK_INPUT;
13321 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13322 0, 0, 0, 0, pix_x, pix_y);
13323 UNBLOCK_INPUT;
13326 /* focus shifting, raising and lowering. */
13328 void
13329 x_focus_on_frame (f)
13330 struct frame *f;
13332 #if 0 /* This proves to be unpleasant. */
13333 x_raise_frame (f);
13334 #endif
13335 #if 0
13336 /* I don't think that the ICCCM allows programs to do things like this
13337 without the interaction of the window manager. Whatever you end up
13338 doing with this code, do it to x_unfocus_frame too. */
13339 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13340 RevertToPointerRoot, CurrentTime);
13341 #endif /* ! 0 */
13344 void
13345 x_unfocus_frame (f)
13346 struct frame *f;
13348 #if 0
13349 /* Look at the remarks in x_focus_on_frame. */
13350 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
13351 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
13352 RevertToPointerRoot, CurrentTime);
13353 #endif /* ! 0 */
13356 /* Raise frame F. */
13358 void
13359 x_raise_frame (f)
13360 struct frame *f;
13362 if (f->async_visible)
13364 BLOCK_INPUT;
13365 #ifdef USE_X_TOOLKIT
13366 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13367 #else /* not USE_X_TOOLKIT */
13368 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13369 #endif /* not USE_X_TOOLKIT */
13370 XFlush (FRAME_X_DISPLAY (f));
13371 UNBLOCK_INPUT;
13375 /* Lower frame F. */
13377 void
13378 x_lower_frame (f)
13379 struct frame *f;
13381 if (f->async_visible)
13383 BLOCK_INPUT;
13384 #ifdef USE_X_TOOLKIT
13385 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13386 #else /* not USE_X_TOOLKIT */
13387 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13388 #endif /* not USE_X_TOOLKIT */
13389 XFlush (FRAME_X_DISPLAY (f));
13390 UNBLOCK_INPUT;
13394 static void
13395 XTframe_raise_lower (f, raise_flag)
13396 FRAME_PTR f;
13397 int raise_flag;
13399 if (raise_flag)
13400 x_raise_frame (f);
13401 else
13402 x_lower_frame (f);
13405 /* Change of visibility. */
13407 /* This tries to wait until the frame is really visible.
13408 However, if the window manager asks the user where to position
13409 the frame, this will return before the user finishes doing that.
13410 The frame will not actually be visible at that time,
13411 but it will become visible later when the window manager
13412 finishes with it. */
13414 void
13415 x_make_frame_visible (f)
13416 struct frame *f;
13418 Lisp_Object type;
13419 int original_top, original_left;
13420 int retry_count = 2;
13422 retry:
13424 BLOCK_INPUT;
13426 type = x_icon_type (f);
13427 if (!NILP (type))
13428 x_bitmap_icon (f, type);
13430 if (! FRAME_VISIBLE_P (f))
13432 /* We test FRAME_GARBAGED_P here to make sure we don't
13433 call x_set_offset a second time
13434 if we get to x_make_frame_visible a second time
13435 before the window gets really visible. */
13436 if (! FRAME_ICONIFIED_P (f)
13437 && ! f->output_data.x->asked_for_visible)
13438 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13440 f->output_data.x->asked_for_visible = 1;
13442 if (! EQ (Vx_no_window_manager, Qt))
13443 x_wm_set_window_state (f, NormalState);
13444 #ifdef USE_X_TOOLKIT
13445 /* This was XtPopup, but that did nothing for an iconified frame. */
13446 XtMapWidget (f->output_data.x->widget);
13447 #else /* not USE_X_TOOLKIT */
13448 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13449 #endif /* not USE_X_TOOLKIT */
13450 #if 0 /* This seems to bring back scroll bars in the wrong places
13451 if the window configuration has changed. They seem
13452 to come back ok without this. */
13453 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
13454 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13455 #endif
13458 XFlush (FRAME_X_DISPLAY (f));
13460 /* Synchronize to ensure Emacs knows the frame is visible
13461 before we do anything else. We do this loop with input not blocked
13462 so that incoming events are handled. */
13464 Lisp_Object frame;
13465 int count;
13466 /* This must be before UNBLOCK_INPUT
13467 since events that arrive in response to the actions above
13468 will set it when they are handled. */
13469 int previously_visible = f->output_data.x->has_been_visible;
13471 original_left = f->output_data.x->left_pos;
13472 original_top = f->output_data.x->top_pos;
13474 /* This must come after we set COUNT. */
13475 UNBLOCK_INPUT;
13477 /* We unblock here so that arriving X events are processed. */
13479 /* Now move the window back to where it was "supposed to be".
13480 But don't do it if the gravity is negative.
13481 When the gravity is negative, this uses a position
13482 that is 3 pixels too low. Perhaps that's really the border width.
13484 Don't do this if the window has never been visible before,
13485 because the window manager may choose the position
13486 and we don't want to override it. */
13488 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
13489 && f->output_data.x->win_gravity == NorthWestGravity
13490 && previously_visible)
13492 Drawable rootw;
13493 int x, y;
13494 unsigned int width, height, border, depth;
13496 BLOCK_INPUT;
13498 /* On some window managers (such as FVWM) moving an existing
13499 window, even to the same place, causes the window manager
13500 to introduce an offset. This can cause the window to move
13501 to an unexpected location. Check the geometry (a little
13502 slow here) and then verify that the window is in the right
13503 place. If the window is not in the right place, move it
13504 there, and take the potential window manager hit. */
13505 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13506 &rootw, &x, &y, &width, &height, &border, &depth);
13508 if (original_left != x || original_top != y)
13509 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13510 original_left, original_top);
13512 UNBLOCK_INPUT;
13515 XSETFRAME (frame, f);
13517 /* Wait until the frame is visible. Process X events until a
13518 MapNotify event has been seen, or until we think we won't get a
13519 MapNotify at all.. */
13520 for (count = input_signal_count + 10;
13521 input_signal_count < count && !FRAME_VISIBLE_P (f);)
13523 /* Force processing of queued events. */
13524 x_sync (f);
13526 /* Machines that do polling rather than SIGIO have been
13527 observed to go into a busy-wait here. So we'll fake an
13528 alarm signal to let the handler know that there's something
13529 to be read. We used to raise a real alarm, but it seems
13530 that the handler isn't always enabled here. This is
13531 probably a bug. */
13532 if (input_polling_used ())
13534 /* It could be confusing if a real alarm arrives while
13535 processing the fake one. Turn it off and let the
13536 handler reset it. */
13537 extern void poll_for_input_1 P_ ((void));
13538 int old_poll_suppress_count = poll_suppress_count;
13539 poll_suppress_count = 1;
13540 poll_for_input_1 ();
13541 poll_suppress_count = old_poll_suppress_count;
13544 /* See if a MapNotify event has been processed. */
13545 FRAME_SAMPLE_VISIBILITY (f);
13548 /* 2000-09-28: In
13550 (let ((f (selected-frame)))
13551 (iconify-frame f)
13552 (raise-frame f))
13554 the frame is not raised with various window managers on
13555 FreeBSD, Linux and Solaris. It turns out that, for some
13556 unknown reason, the call to XtMapWidget is completely ignored.
13557 Mapping the widget a second time works. */
13559 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13560 goto retry;
13564 /* Change from mapped state to withdrawn state. */
13566 /* Make the frame visible (mapped and not iconified). */
13568 void
13569 x_make_frame_invisible (f)
13570 struct frame *f;
13572 Window window;
13574 #ifdef USE_X_TOOLKIT
13575 /* Use the frame's outermost window, not the one we normally draw on. */
13576 window = XtWindow (f->output_data.x->widget);
13577 #else /* not USE_X_TOOLKIT */
13578 window = FRAME_X_WINDOW (f);
13579 #endif /* not USE_X_TOOLKIT */
13581 /* Don't keep the highlight on an invisible frame. */
13582 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13583 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13585 #if 0/* This might add unreliability; I don't trust it -- rms. */
13586 if (! f->async_visible && ! f->async_iconified)
13587 return;
13588 #endif
13590 BLOCK_INPUT;
13592 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13593 that the current position of the window is user-specified, rather than
13594 program-specified, so that when the window is mapped again, it will be
13595 placed at the same location, without forcing the user to position it
13596 by hand again (they have already done that once for this window.) */
13597 x_wm_set_size_hint (f, (long) 0, 1);
13599 #ifdef HAVE_X11R4
13601 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13602 DefaultScreen (FRAME_X_DISPLAY (f))))
13604 UNBLOCK_INPUT_RESIGNAL;
13605 error ("Can't notify window manager of window withdrawal");
13607 #else /* ! defined (HAVE_X11R4) */
13609 /* Tell the window manager what we're going to do. */
13610 if (! EQ (Vx_no_window_manager, Qt))
13612 XEvent unmap;
13614 unmap.xunmap.type = UnmapNotify;
13615 unmap.xunmap.window = window;
13616 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13617 unmap.xunmap.from_configure = False;
13618 if (! XSendEvent (FRAME_X_DISPLAY (f),
13619 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13620 False,
13621 SubstructureRedirectMaskSubstructureNotifyMask,
13622 &unmap))
13624 UNBLOCK_INPUT_RESIGNAL;
13625 error ("Can't notify window manager of withdrawal");
13629 /* Unmap the window ourselves. Cheeky! */
13630 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13631 #endif /* ! defined (HAVE_X11R4) */
13633 /* We can't distinguish this from iconification
13634 just by the event that we get from the server.
13635 So we can't win using the usual strategy of letting
13636 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13637 and synchronize with the server to make sure we agree. */
13638 f->visible = 0;
13639 FRAME_ICONIFIED_P (f) = 0;
13640 f->async_visible = 0;
13641 f->async_iconified = 0;
13643 x_sync (f);
13645 UNBLOCK_INPUT;
13648 /* Change window state from mapped to iconified. */
13650 void
13651 x_iconify_frame (f)
13652 struct frame *f;
13654 int result;
13655 Lisp_Object type;
13657 /* Don't keep the highlight on an invisible frame. */
13658 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13659 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13661 if (f->async_iconified)
13662 return;
13664 BLOCK_INPUT;
13666 FRAME_SAMPLE_VISIBILITY (f);
13668 type = x_icon_type (f);
13669 if (!NILP (type))
13670 x_bitmap_icon (f, type);
13672 #ifdef USE_X_TOOLKIT
13674 if (! FRAME_VISIBLE_P (f))
13676 if (! EQ (Vx_no_window_manager, Qt))
13677 x_wm_set_window_state (f, IconicState);
13678 /* This was XtPopup, but that did nothing for an iconified frame. */
13679 XtMapWidget (f->output_data.x->widget);
13680 /* The server won't give us any event to indicate
13681 that an invisible frame was changed to an icon,
13682 so we have to record it here. */
13683 f->iconified = 1;
13684 f->visible = 1;
13685 f->async_iconified = 1;
13686 f->async_visible = 0;
13687 UNBLOCK_INPUT;
13688 return;
13691 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13692 XtWindow (f->output_data.x->widget),
13693 DefaultScreen (FRAME_X_DISPLAY (f)));
13694 UNBLOCK_INPUT;
13696 if (!result)
13697 error ("Can't notify window manager of iconification");
13699 f->async_iconified = 1;
13700 f->async_visible = 0;
13703 BLOCK_INPUT;
13704 XFlush (FRAME_X_DISPLAY (f));
13705 UNBLOCK_INPUT;
13706 #else /* not USE_X_TOOLKIT */
13708 /* Make sure the X server knows where the window should be positioned,
13709 in case the user deiconifies with the window manager. */
13710 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13711 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13713 /* Since we don't know which revision of X we're running, we'll use both
13714 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13716 /* X11R4: send a ClientMessage to the window manager using the
13717 WM_CHANGE_STATE type. */
13719 XEvent message;
13721 message.xclient.window = FRAME_X_WINDOW (f);
13722 message.xclient.type = ClientMessage;
13723 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13724 message.xclient.format = 32;
13725 message.xclient.data.l[0] = IconicState;
13727 if (! XSendEvent (FRAME_X_DISPLAY (f),
13728 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13729 False,
13730 SubstructureRedirectMask | SubstructureNotifyMask,
13731 &message))
13733 UNBLOCK_INPUT_RESIGNAL;
13734 error ("Can't notify window manager of iconification");
13738 /* X11R3: set the initial_state field of the window manager hints to
13739 IconicState. */
13740 x_wm_set_window_state (f, IconicState);
13742 if (!FRAME_VISIBLE_P (f))
13744 /* If the frame was withdrawn, before, we must map it. */
13745 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13748 f->async_iconified = 1;
13749 f->async_visible = 0;
13751 XFlush (FRAME_X_DISPLAY (f));
13752 UNBLOCK_INPUT;
13753 #endif /* not USE_X_TOOLKIT */
13757 /* Free X resources of frame F. */
13759 void
13760 x_free_frame_resources (f)
13761 struct frame *f;
13763 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13764 Lisp_Object bar;
13765 struct scroll_bar *b;
13767 BLOCK_INPUT;
13769 /* If a display connection is dead, don't try sending more
13770 commands to the X server. */
13771 if (dpyinfo->display)
13773 if (f->output_data.x->icon_desc)
13774 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13776 #ifdef USE_X_TOOLKIT
13777 /* Explicitly destroy the scroll bars of the frame. Without
13778 this, we get "BadDrawable" errors from the toolkit later on,
13779 presumably from expose events generated for the disappearing
13780 toolkit scroll bars. */
13781 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13783 b = XSCROLL_BAR (bar);
13784 x_scroll_bar_remove (b);
13786 #endif
13788 #ifdef HAVE_X_I18N
13789 if (FRAME_XIC (f))
13790 free_frame_xic (f);
13791 #endif
13793 #ifdef USE_X_TOOLKIT
13794 if (f->output_data.x->widget)
13796 XtDestroyWidget (f->output_data.x->widget);
13797 f->output_data.x->widget = NULL;
13799 /* Tooltips don't have widgets, only a simple X window, even if
13800 we are using a toolkit. */
13801 else if (FRAME_X_WINDOW (f))
13802 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13804 free_frame_menubar (f);
13805 #else /* !USE_X_TOOLKIT */
13806 if (FRAME_X_WINDOW (f))
13807 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13808 #endif /* !USE_X_TOOLKIT */
13810 unload_color (f, f->output_data.x->foreground_pixel);
13811 unload_color (f, f->output_data.x->background_pixel);
13812 unload_color (f, f->output_data.x->cursor_pixel);
13813 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13814 unload_color (f, f->output_data.x->border_pixel);
13815 unload_color (f, f->output_data.x->mouse_pixel);
13817 if (f->output_data.x->scroll_bar_background_pixel != -1)
13818 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13819 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13820 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13821 #ifdef USE_TOOLKIT_SCROLL_BARS
13822 /* Scrollbar shadow colors. */
13823 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13824 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13825 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13826 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13827 #endif /* USE_TOOLKIT_SCROLL_BARS */
13828 if (f->output_data.x->white_relief.allocated_p)
13829 unload_color (f, f->output_data.x->white_relief.pixel);
13830 if (f->output_data.x->black_relief.allocated_p)
13831 unload_color (f, f->output_data.x->black_relief.pixel);
13833 if (FRAME_FACE_CACHE (f))
13834 free_frame_faces (f);
13836 x_free_gcs (f);
13837 XFlush (FRAME_X_DISPLAY (f));
13840 if (f->output_data.x->saved_menu_event)
13841 xfree (f->output_data.x->saved_menu_event);
13843 xfree (f->output_data.x);
13844 f->output_data.x = NULL;
13846 if (f == dpyinfo->x_focus_frame)
13847 dpyinfo->x_focus_frame = 0;
13848 if (f == dpyinfo->x_focus_event_frame)
13849 dpyinfo->x_focus_event_frame = 0;
13850 if (f == dpyinfo->x_highlight_frame)
13851 dpyinfo->x_highlight_frame = 0;
13853 if (f == dpyinfo->mouse_face_mouse_frame)
13855 dpyinfo->mouse_face_beg_row
13856 = dpyinfo->mouse_face_beg_col = -1;
13857 dpyinfo->mouse_face_end_row
13858 = dpyinfo->mouse_face_end_col = -1;
13859 dpyinfo->mouse_face_window = Qnil;
13860 dpyinfo->mouse_face_deferred_gc = 0;
13861 dpyinfo->mouse_face_mouse_frame = 0;
13864 UNBLOCK_INPUT;
13868 /* Destroy the X window of frame F. */
13870 void
13871 x_destroy_window (f)
13872 struct frame *f;
13874 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13876 /* If a display connection is dead, don't try sending more
13877 commands to the X server. */
13878 if (dpyinfo->display != 0)
13879 x_free_frame_resources (f);
13881 dpyinfo->reference_count--;
13885 /* Setting window manager hints. */
13887 /* Set the normal size hints for the window manager, for frame F.
13888 FLAGS is the flags word to use--or 0 meaning preserve the flags
13889 that the window now has.
13890 If USER_POSITION is nonzero, we set the USPosition
13891 flag (this is useful when FLAGS is 0). */
13893 void
13894 x_wm_set_size_hint (f, flags, user_position)
13895 struct frame *f;
13896 long flags;
13897 int user_position;
13899 XSizeHints size_hints;
13901 #ifdef USE_X_TOOLKIT
13902 Arg al[2];
13903 int ac = 0;
13904 Dimension widget_width, widget_height;
13905 Window window = XtWindow (f->output_data.x->widget);
13906 #else /* not USE_X_TOOLKIT */
13907 Window window = FRAME_X_WINDOW (f);
13908 #endif /* not USE_X_TOOLKIT */
13910 /* Setting PMaxSize caused various problems. */
13911 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13913 size_hints.x = f->output_data.x->left_pos;
13914 size_hints.y = f->output_data.x->top_pos;
13916 #ifdef USE_X_TOOLKIT
13917 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13918 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13919 XtGetValues (f->output_data.x->widget, al, ac);
13920 size_hints.height = widget_height;
13921 size_hints.width = widget_width;
13922 #else /* not USE_X_TOOLKIT */
13923 size_hints.height = PIXEL_HEIGHT (f);
13924 size_hints.width = PIXEL_WIDTH (f);
13925 #endif /* not USE_X_TOOLKIT */
13927 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13928 size_hints.height_inc = f->output_data.x->line_height;
13929 size_hints.max_width
13930 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13931 size_hints.max_height
13932 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13934 /* Calculate the base and minimum sizes.
13936 (When we use the X toolkit, we don't do it here.
13937 Instead we copy the values that the widgets are using, below.) */
13938 #ifndef USE_X_TOOLKIT
13940 int base_width, base_height;
13941 int min_rows = 0, min_cols = 0;
13943 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13944 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13946 check_frame_size (f, &min_rows, &min_cols);
13948 /* The window manager uses the base width hints to calculate the
13949 current number of rows and columns in the frame while
13950 resizing; min_width and min_height aren't useful for this
13951 purpose, since they might not give the dimensions for a
13952 zero-row, zero-column frame.
13954 We use the base_width and base_height members if we have
13955 them; otherwise, we set the min_width and min_height members
13956 to the size for a zero x zero frame. */
13958 #ifdef HAVE_X11R4
13959 size_hints.flags |= PBaseSize;
13960 size_hints.base_width = base_width;
13961 size_hints.base_height = base_height;
13962 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13963 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13964 #else
13965 size_hints.min_width = base_width;
13966 size_hints.min_height = base_height;
13967 #endif
13970 /* If we don't need the old flags, we don't need the old hint at all. */
13971 if (flags)
13973 size_hints.flags |= flags;
13974 goto no_read;
13976 #endif /* not USE_X_TOOLKIT */
13979 XSizeHints hints; /* Sometimes I hate X Windows... */
13980 long supplied_return;
13981 int value;
13983 #ifdef HAVE_X11R4
13984 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13985 &supplied_return);
13986 #else
13987 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13988 #endif
13990 #ifdef USE_X_TOOLKIT
13991 size_hints.base_height = hints.base_height;
13992 size_hints.base_width = hints.base_width;
13993 size_hints.min_height = hints.min_height;
13994 size_hints.min_width = hints.min_width;
13995 #endif
13997 if (flags)
13998 size_hints.flags |= flags;
13999 else
14001 if (value == 0)
14002 hints.flags = 0;
14003 if (hints.flags & PSize)
14004 size_hints.flags |= PSize;
14005 if (hints.flags & PPosition)
14006 size_hints.flags |= PPosition;
14007 if (hints.flags & USPosition)
14008 size_hints.flags |= USPosition;
14009 if (hints.flags & USSize)
14010 size_hints.flags |= USSize;
14014 #ifndef USE_X_TOOLKIT
14015 no_read:
14016 #endif
14018 #ifdef PWinGravity
14019 size_hints.win_gravity = f->output_data.x->win_gravity;
14020 size_hints.flags |= PWinGravity;
14022 if (user_position)
14024 size_hints.flags &= ~ PPosition;
14025 size_hints.flags |= USPosition;
14027 #endif /* PWinGravity */
14029 #ifdef HAVE_X11R4
14030 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
14031 #else
14032 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
14033 #endif
14036 /* Used for IconicState or NormalState */
14038 void
14039 x_wm_set_window_state (f, state)
14040 struct frame *f;
14041 int state;
14043 #ifdef USE_X_TOOLKIT
14044 Arg al[1];
14046 XtSetArg (al[0], XtNinitialState, state);
14047 XtSetValues (f->output_data.x->widget, al, 1);
14048 #else /* not USE_X_TOOLKIT */
14049 Window window = FRAME_X_WINDOW (f);
14051 f->output_data.x->wm_hints.flags |= StateHint;
14052 f->output_data.x->wm_hints.initial_state = state;
14054 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14055 #endif /* not USE_X_TOOLKIT */
14058 void
14059 x_wm_set_icon_pixmap (f, pixmap_id)
14060 struct frame *f;
14061 int pixmap_id;
14063 Pixmap icon_pixmap;
14065 #ifndef USE_X_TOOLKIT
14066 Window window = FRAME_X_WINDOW (f);
14067 #endif
14069 if (pixmap_id > 0)
14071 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
14072 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
14074 else
14076 /* It seems there is no way to turn off use of an icon pixmap.
14077 The following line does it, only if no icon has yet been created,
14078 for some window managers. But with mwm it crashes.
14079 Some people say it should clear the IconPixmapHint bit in this case,
14080 but that doesn't work, and the X consortium said it isn't the
14081 right thing at all. Since there is no way to win,
14082 best to explicitly give up. */
14083 #if 0
14084 f->output_data.x->wm_hints.icon_pixmap = None;
14085 #else
14086 return;
14087 #endif
14090 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
14093 Arg al[1];
14094 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
14095 XtSetValues (f->output_data.x->widget, al, 1);
14098 #else /* not USE_X_TOOLKIT */
14100 f->output_data.x->wm_hints.flags |= IconPixmapHint;
14101 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14103 #endif /* not USE_X_TOOLKIT */
14106 void
14107 x_wm_set_icon_position (f, icon_x, icon_y)
14108 struct frame *f;
14109 int icon_x, icon_y;
14111 #ifdef USE_X_TOOLKIT
14112 Window window = XtWindow (f->output_data.x->widget);
14113 #else
14114 Window window = FRAME_X_WINDOW (f);
14115 #endif
14117 f->output_data.x->wm_hints.flags |= IconPositionHint;
14118 f->output_data.x->wm_hints.icon_x = icon_x;
14119 f->output_data.x->wm_hints.icon_y = icon_y;
14121 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14125 /***********************************************************************
14126 Fonts
14127 ***********************************************************************/
14129 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
14131 struct font_info *
14132 x_get_font_info (f, font_idx)
14133 FRAME_PTR f;
14134 int font_idx;
14136 return (FRAME_X_FONT_TABLE (f) + font_idx);
14140 /* Return a list of names of available fonts matching PATTERN on frame F.
14142 If SIZE is > 0, it is the size (maximum bounds width) of fonts
14143 to be listed.
14145 SIZE < 0 means include scalable fonts.
14147 Frame F null means we have not yet created any frame on X, and
14148 consult the first display in x_display_list. MAXNAMES sets a limit
14149 on how many fonts to match. */
14151 Lisp_Object
14152 x_list_fonts (f, pattern, size, maxnames)
14153 struct frame *f;
14154 Lisp_Object pattern;
14155 int size;
14156 int maxnames;
14158 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
14159 Lisp_Object tem, second_best;
14160 struct x_display_info *dpyinfo
14161 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
14162 Display *dpy = dpyinfo->display;
14163 int try_XLoadQueryFont = 0;
14164 int count;
14165 int allow_scalable_fonts_p = 0;
14167 if (size < 0)
14169 allow_scalable_fonts_p = 1;
14170 size = 0;
14173 patterns = Fassoc (pattern, Valternate_fontname_alist);
14174 if (NILP (patterns))
14175 patterns = Fcons (pattern, Qnil);
14177 if (maxnames == 1 && !size)
14178 /* We can return any single font matching PATTERN. */
14179 try_XLoadQueryFont = 1;
14181 for (; CONSP (patterns); patterns = XCDR (patterns))
14183 int num_fonts;
14184 char **names = NULL;
14186 pattern = XCAR (patterns);
14187 /* See if we cached the result for this particular query.
14188 The cache is an alist of the form:
14189 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
14190 tem = XCDR (dpyinfo->name_list_element);
14191 key = Fcons (Fcons (pattern, make_number (maxnames)),
14192 allow_scalable_fonts_p ? Qt : Qnil);
14193 list = Fassoc (key, tem);
14194 if (!NILP (list))
14196 list = Fcdr_safe (list);
14197 /* We have a cashed list. Don't have to get the list again. */
14198 goto label_cached;
14201 /* At first, put PATTERN in the cache. */
14203 BLOCK_INPUT;
14204 count = x_catch_errors (dpy);
14206 if (try_XLoadQueryFont)
14208 XFontStruct *font;
14209 unsigned long value;
14211 font = XLoadQueryFont (dpy, SDATA (pattern));
14212 if (x_had_errors_p (dpy))
14214 /* This error is perhaps due to insufficient memory on X
14215 server. Let's just ignore it. */
14216 font = NULL;
14217 x_clear_errors (dpy);
14220 if (font
14221 && XGetFontProperty (font, XA_FONT, &value))
14223 char *name = (char *) XGetAtomName (dpy, (Atom) value);
14224 int len = strlen (name);
14225 char *tmp;
14227 /* If DXPC (a Differential X Protocol Compressor)
14228 Ver.3.7 is running, XGetAtomName will return null
14229 string. We must avoid such a name. */
14230 if (len == 0)
14231 try_XLoadQueryFont = 0;
14232 else
14234 num_fonts = 1;
14235 names = (char **) alloca (sizeof (char *));
14236 /* Some systems only allow alloca assigned to a
14237 simple var. */
14238 tmp = (char *) alloca (len + 1); names[0] = tmp;
14239 bcopy (name, names[0], len + 1);
14240 XFree (name);
14243 else
14244 try_XLoadQueryFont = 0;
14246 if (font)
14247 XFreeFont (dpy, font);
14250 if (!try_XLoadQueryFont)
14252 /* We try at least 10 fonts because XListFonts will return
14253 auto-scaled fonts at the head. */
14254 names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
14255 &num_fonts);
14256 if (x_had_errors_p (dpy))
14258 /* This error is perhaps due to insufficient memory on X
14259 server. Let's just ignore it. */
14260 names = NULL;
14261 x_clear_errors (dpy);
14265 x_uncatch_errors (dpy, count);
14266 UNBLOCK_INPUT;
14268 if (names)
14270 int i;
14272 /* Make a list of all the fonts we got back.
14273 Store that in the font cache for the display. */
14274 for (i = 0; i < num_fonts; i++)
14276 int width = 0;
14277 char *p = names[i];
14278 int average_width = -1, dashes = 0;
14280 /* Count the number of dashes in NAMES[I]. If there are
14281 14 dashes, and the field value following 12th dash
14282 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
14283 is usually too ugly to be used for editing. Let's
14284 ignore it. */
14285 while (*p)
14286 if (*p++ == '-')
14288 dashes++;
14289 if (dashes == 7) /* PIXEL_SIZE field */
14290 width = atoi (p);
14291 else if (dashes == 12) /* AVERAGE_WIDTH field */
14292 average_width = atoi (p);
14295 if (allow_scalable_fonts_p
14296 || dashes < 14 || average_width != 0)
14298 tem = build_string (names[i]);
14299 if (NILP (Fassoc (tem, list)))
14301 if (STRINGP (Vx_pixel_size_width_font_regexp)
14302 && ((fast_c_string_match_ignore_case
14303 (Vx_pixel_size_width_font_regexp, names[i]))
14304 >= 0))
14305 /* We can set the value of PIXEL_SIZE to the
14306 width of this font. */
14307 list = Fcons (Fcons (tem, make_number (width)), list);
14308 else
14309 /* For the moment, width is not known. */
14310 list = Fcons (Fcons (tem, Qnil), list);
14315 if (!try_XLoadQueryFont)
14317 BLOCK_INPUT;
14318 XFreeFontNames (names);
14319 UNBLOCK_INPUT;
14323 /* Now store the result in the cache. */
14324 XSETCDR (dpyinfo->name_list_element,
14325 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
14327 label_cached:
14328 if (NILP (list)) continue; /* Try the remaining alternatives. */
14330 newlist = second_best = Qnil;
14331 /* Make a list of the fonts that have the right width. */
14332 for (; CONSP (list); list = XCDR (list))
14334 int found_size;
14336 tem = XCAR (list);
14338 if (!CONSP (tem) || NILP (XCAR (tem)))
14339 continue;
14340 if (!size)
14342 newlist = Fcons (XCAR (tem), newlist);
14343 continue;
14346 if (!INTEGERP (XCDR (tem)))
14348 /* Since we have not yet known the size of this font, we
14349 must try slow function call XLoadQueryFont. */
14350 XFontStruct *thisinfo;
14352 BLOCK_INPUT;
14353 count = x_catch_errors (dpy);
14354 thisinfo = XLoadQueryFont (dpy,
14355 SDATA (XCAR (tem)));
14356 if (x_had_errors_p (dpy))
14358 /* This error is perhaps due to insufficient memory on X
14359 server. Let's just ignore it. */
14360 thisinfo = NULL;
14361 x_clear_errors (dpy);
14363 x_uncatch_errors (dpy, count);
14364 UNBLOCK_INPUT;
14366 if (thisinfo)
14368 XSETCDR (tem,
14369 (thisinfo->min_bounds.width == 0
14370 ? make_number (0)
14371 : make_number (thisinfo->max_bounds.width)));
14372 BLOCK_INPUT;
14373 XFreeFont (dpy, thisinfo);
14374 UNBLOCK_INPUT;
14376 else
14377 /* For unknown reason, the previous call of XListFont had
14378 returned a font which can't be opened. Record the size
14379 as 0 not to try to open it again. */
14380 XSETCDR (tem, make_number (0));
14383 found_size = XINT (XCDR (tem));
14384 if (found_size == size)
14385 newlist = Fcons (XCAR (tem), newlist);
14386 else if (found_size > 0)
14388 if (NILP (second_best))
14389 second_best = tem;
14390 else if (found_size < size)
14392 if (XINT (XCDR (second_best)) > size
14393 || XINT (XCDR (second_best)) < found_size)
14394 second_best = tem;
14396 else
14398 if (XINT (XCDR (second_best)) > size
14399 && XINT (XCDR (second_best)) > found_size)
14400 second_best = tem;
14404 if (!NILP (newlist))
14405 break;
14406 else if (!NILP (second_best))
14408 newlist = Fcons (XCAR (second_best), Qnil);
14409 break;
14413 return newlist;
14417 #if GLYPH_DEBUG
14419 /* Check that FONT is valid on frame F. It is if it can be found in F's
14420 font table. */
14422 static void
14423 x_check_font (f, font)
14424 struct frame *f;
14425 XFontStruct *font;
14427 int i;
14428 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14430 xassert (font != NULL);
14432 for (i = 0; i < dpyinfo->n_fonts; i++)
14433 if (dpyinfo->font_table[i].name
14434 && font == dpyinfo->font_table[i].font)
14435 break;
14437 xassert (i < dpyinfo->n_fonts);
14440 #endif /* GLYPH_DEBUG != 0 */
14442 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14443 Note: There are (broken) X fonts out there with invalid XFontStruct
14444 min_bounds contents. For example, handa@etl.go.jp reports that
14445 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14446 have font->min_bounds.width == 0. */
14448 static INLINE void
14449 x_font_min_bounds (font, w, h)
14450 XFontStruct *font;
14451 int *w, *h;
14453 *h = FONT_HEIGHT (font);
14454 *w = font->min_bounds.width;
14456 /* Try to handle the case where FONT->min_bounds has invalid
14457 contents. Since the only font known to have invalid min_bounds
14458 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14459 if (*w <= 0)
14460 *w = font->max_bounds.width;
14464 /* Compute the smallest character width and smallest font height over
14465 all fonts available on frame F. Set the members smallest_char_width
14466 and smallest_font_height in F's x_display_info structure to
14467 the values computed. Value is non-zero if smallest_font_height or
14468 smallest_char_width become smaller than they were before. */
14470 static int
14471 x_compute_min_glyph_bounds (f)
14472 struct frame *f;
14474 int i;
14475 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14476 XFontStruct *font;
14477 int old_width = dpyinfo->smallest_char_width;
14478 int old_height = dpyinfo->smallest_font_height;
14480 dpyinfo->smallest_font_height = 100000;
14481 dpyinfo->smallest_char_width = 100000;
14483 for (i = 0; i < dpyinfo->n_fonts; ++i)
14484 if (dpyinfo->font_table[i].name)
14486 struct font_info *fontp = dpyinfo->font_table + i;
14487 int w, h;
14489 font = (XFontStruct *) fontp->font;
14490 xassert (font != (XFontStruct *) ~0);
14491 x_font_min_bounds (font, &w, &h);
14493 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
14494 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
14497 xassert (dpyinfo->smallest_char_width > 0
14498 && dpyinfo->smallest_font_height > 0);
14500 return (dpyinfo->n_fonts == 1
14501 || dpyinfo->smallest_char_width < old_width
14502 || dpyinfo->smallest_font_height < old_height);
14506 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14507 pointer to the structure font_info while allocating it dynamically.
14508 If SIZE is 0, load any size of font.
14509 If loading is failed, return NULL. */
14511 struct font_info *
14512 x_load_font (f, fontname, size)
14513 struct frame *f;
14514 register char *fontname;
14515 int size;
14517 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14518 Lisp_Object font_names;
14519 int count;
14521 /* Get a list of all the fonts that match this name. Once we
14522 have a list of matching fonts, we compare them against the fonts
14523 we already have by comparing names. */
14524 font_names = x_list_fonts (f, build_string (fontname), size, 1);
14526 if (!NILP (font_names))
14528 Lisp_Object tail;
14529 int i;
14531 for (i = 0; i < dpyinfo->n_fonts; i++)
14532 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
14533 if (dpyinfo->font_table[i].name
14534 && (!strcmp (dpyinfo->font_table[i].name,
14535 SDATA (XCAR (tail)))
14536 || !strcmp (dpyinfo->font_table[i].full_name,
14537 SDATA (XCAR (tail)))))
14538 return (dpyinfo->font_table + i);
14541 /* Load the font and add it to the table. */
14543 char *full_name;
14544 XFontStruct *font;
14545 struct font_info *fontp;
14546 unsigned long value;
14547 int i;
14549 /* If we have found fonts by x_list_font, load one of them. If
14550 not, we still try to load a font by the name given as FONTNAME
14551 because XListFonts (called in x_list_font) of some X server has
14552 a bug of not finding a font even if the font surely exists and
14553 is loadable by XLoadQueryFont. */
14554 if (size > 0 && !NILP (font_names))
14555 fontname = (char *) SDATA (XCAR (font_names));
14557 BLOCK_INPUT;
14558 count = x_catch_errors (FRAME_X_DISPLAY (f));
14559 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14560 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14562 /* This error is perhaps due to insufficient memory on X
14563 server. Let's just ignore it. */
14564 font = NULL;
14565 x_clear_errors (FRAME_X_DISPLAY (f));
14567 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14568 UNBLOCK_INPUT;
14569 if (!font)
14570 return NULL;
14572 /* Find a free slot in the font table. */
14573 for (i = 0; i < dpyinfo->n_fonts; ++i)
14574 if (dpyinfo->font_table[i].name == NULL)
14575 break;
14577 /* If no free slot found, maybe enlarge the font table. */
14578 if (i == dpyinfo->n_fonts
14579 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14581 int sz;
14582 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14583 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14584 dpyinfo->font_table
14585 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14588 fontp = dpyinfo->font_table + i;
14589 if (i == dpyinfo->n_fonts)
14590 ++dpyinfo->n_fonts;
14592 /* Now fill in the slots of *FONTP. */
14593 BLOCK_INPUT;
14594 fontp->font = font;
14595 fontp->font_idx = i;
14596 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14597 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14599 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14600 full_name = 0;
14601 if (XGetFontProperty (font, XA_FONT, &value))
14603 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14604 char *p = name;
14605 int dashes = 0;
14607 /* Count the number of dashes in the "full name".
14608 If it is too few, this isn't really the font's full name,
14609 so don't use it.
14610 In X11R4, the fonts did not come with their canonical names
14611 stored in them. */
14612 while (*p)
14614 if (*p == '-')
14615 dashes++;
14616 p++;
14619 if (dashes >= 13)
14621 full_name = (char *) xmalloc (p - name + 1);
14622 bcopy (name, full_name, p - name + 1);
14625 XFree (name);
14628 if (full_name != 0)
14629 fontp->full_name = full_name;
14630 else
14631 fontp->full_name = fontp->name;
14633 fontp->size = font->max_bounds.width;
14634 fontp->height = FONT_HEIGHT (font);
14636 if (NILP (font_names))
14638 /* We come here because of a bug of XListFonts mentioned at
14639 the head of this block. Let's store this information in
14640 the cache for x_list_fonts. */
14641 Lisp_Object lispy_name = build_string (fontname);
14642 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14643 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14644 Qnil);
14646 XSETCDR (dpyinfo->name_list_element,
14647 Fcons (Fcons (key,
14648 Fcons (Fcons (lispy_full_name,
14649 make_number (fontp->size)),
14650 Qnil)),
14651 XCDR (dpyinfo->name_list_element)));
14652 if (full_name)
14654 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14655 Qnil);
14656 XSETCDR (dpyinfo->name_list_element,
14657 Fcons (Fcons (key,
14658 Fcons (Fcons (lispy_full_name,
14659 make_number (fontp->size)),
14660 Qnil)),
14661 XCDR (dpyinfo->name_list_element)));
14665 /* The slot `encoding' specifies how to map a character
14666 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14667 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14668 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14669 2:0xA020..0xFF7F). For the moment, we don't know which charset
14670 uses this font. So, we set information in fontp->encoding[1]
14671 which is never used by any charset. If mapping can't be
14672 decided, set FONT_ENCODING_NOT_DECIDED. */
14673 fontp->encoding[1]
14674 = (font->max_byte1 == 0
14675 /* 1-byte font */
14676 ? (font->min_char_or_byte2 < 0x80
14677 ? (font->max_char_or_byte2 < 0x80
14678 ? 0 /* 0x20..0x7F */
14679 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14680 : 1) /* 0xA0..0xFF */
14681 /* 2-byte font */
14682 : (font->min_byte1 < 0x80
14683 ? (font->max_byte1 < 0x80
14684 ? (font->min_char_or_byte2 < 0x80
14685 ? (font->max_char_or_byte2 < 0x80
14686 ? 0 /* 0x2020..0x7F7F */
14687 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14688 : 3) /* 0x20A0..0x7FFF */
14689 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14690 : (font->min_char_or_byte2 < 0x80
14691 ? (font->max_char_or_byte2 < 0x80
14692 ? 2 /* 0xA020..0xFF7F */
14693 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14694 : 1))); /* 0xA0A0..0xFFFF */
14696 fontp->baseline_offset
14697 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14698 ? (long) value : 0);
14699 fontp->relative_compose
14700 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14701 ? (long) value : 0);
14702 fontp->default_ascent
14703 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14704 ? (long) value : 0);
14706 /* Set global flag fonts_changed_p to non-zero if the font loaded
14707 has a character with a smaller width than any other character
14708 before, or if the font loaded has a smaller height than any
14709 other font loaded before. If this happens, it will make a
14710 glyph matrix reallocation necessary. */
14711 fonts_changed_p |= x_compute_min_glyph_bounds (f);
14712 UNBLOCK_INPUT;
14713 return fontp;
14718 /* Return a pointer to struct font_info of a font named FONTNAME for
14719 frame F. If no such font is loaded, return NULL. */
14721 struct font_info *
14722 x_query_font (f, fontname)
14723 struct frame *f;
14724 register char *fontname;
14726 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14727 int i;
14729 for (i = 0; i < dpyinfo->n_fonts; i++)
14730 if (dpyinfo->font_table[i].name
14731 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14732 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14733 return (dpyinfo->font_table + i);
14734 return NULL;
14738 /* Find a CCL program for a font specified by FONTP, and set the member
14739 `encoder' of the structure. */
14741 void
14742 x_find_ccl_program (fontp)
14743 struct font_info *fontp;
14745 Lisp_Object list, elt;
14747 elt = Qnil;
14748 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14750 elt = XCAR (list);
14751 if (CONSP (elt)
14752 && STRINGP (XCAR (elt))
14753 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14754 >= 0)
14755 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14756 >= 0)))
14757 break;
14760 if (! NILP (list))
14762 struct ccl_program *ccl
14763 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14765 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14766 xfree (ccl);
14767 else
14768 fontp->font_encoder = ccl;
14774 /***********************************************************************
14775 Initialization
14776 ***********************************************************************/
14778 #ifdef USE_X_TOOLKIT
14779 static XrmOptionDescRec emacs_options[] = {
14780 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14781 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14783 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14784 XrmoptionSepArg, NULL},
14785 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14787 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14788 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14789 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14790 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14791 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14792 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14793 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14795 #endif /* USE_X_TOOLKIT */
14797 static int x_initialized;
14799 #ifdef MULTI_KBOARD
14800 /* Test whether two display-name strings agree up to the dot that separates
14801 the screen number from the server number. */
14802 static int
14803 same_x_server (name1, name2)
14804 const char *name1, *name2;
14806 int seen_colon = 0;
14807 const unsigned char *system_name = SDATA (Vsystem_name);
14808 int system_name_length = strlen (system_name);
14809 int length_until_period = 0;
14811 while (system_name[length_until_period] != 0
14812 && system_name[length_until_period] != '.')
14813 length_until_period++;
14815 /* Treat `unix' like an empty host name. */
14816 if (! strncmp (name1, "unix:", 5))
14817 name1 += 4;
14818 if (! strncmp (name2, "unix:", 5))
14819 name2 += 4;
14820 /* Treat this host's name like an empty host name. */
14821 if (! strncmp (name1, system_name, system_name_length)
14822 && name1[system_name_length] == ':')
14823 name1 += system_name_length;
14824 if (! strncmp (name2, system_name, system_name_length)
14825 && name2[system_name_length] == ':')
14826 name2 += system_name_length;
14827 /* Treat this host's domainless name like an empty host name. */
14828 if (! strncmp (name1, system_name, length_until_period)
14829 && name1[length_until_period] == ':')
14830 name1 += length_until_period;
14831 if (! strncmp (name2, system_name, length_until_period)
14832 && name2[length_until_period] == ':')
14833 name2 += length_until_period;
14835 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14837 if (*name1 == ':')
14838 seen_colon++;
14839 if (seen_colon && *name1 == '.')
14840 return 1;
14842 return (seen_colon
14843 && (*name1 == '.' || *name1 == '\0')
14844 && (*name2 == '.' || *name2 == '\0'));
14846 #endif
14848 struct x_display_info *
14849 x_term_init (display_name, xrm_option, resource_name)
14850 Lisp_Object display_name;
14851 char *xrm_option;
14852 char *resource_name;
14854 int connection;
14855 Display *dpy;
14856 struct x_display_info *dpyinfo;
14857 XrmDatabase xrdb;
14859 BLOCK_INPUT;
14861 if (!x_initialized)
14863 x_initialize ();
14864 x_initialized = 1;
14867 #ifdef USE_X_TOOLKIT
14868 /* weiner@footloose.sps.mot.com reports that this causes
14869 errors with X11R5:
14870 X protocol error: BadAtom (invalid Atom parameter)
14871 on protocol request 18skiloaf.
14872 So let's not use it until R6. */
14873 #ifdef HAVE_X11XTR6
14874 XtSetLanguageProc (NULL, NULL, NULL);
14875 #endif
14878 int argc = 0;
14879 char *argv[3];
14881 argv[0] = "";
14882 argc = 1;
14883 if (xrm_option)
14885 argv[argc++] = "-xrm";
14886 argv[argc++] = xrm_option;
14888 turn_on_atimers (0);
14889 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
14890 resource_name, EMACS_CLASS,
14891 emacs_options, XtNumber (emacs_options),
14892 &argc, argv);
14893 turn_on_atimers (1);
14895 #ifdef HAVE_X11XTR6
14896 /* I think this is to compensate for XtSetLanguageProc. */
14897 fixup_locale ();
14898 #endif
14901 #else /* not USE_X_TOOLKIT */
14902 #ifdef HAVE_X11R5
14903 XSetLocaleModifiers ("");
14904 #endif
14905 dpy = XOpenDisplay (SDATA (display_name));
14906 #endif /* not USE_X_TOOLKIT */
14908 /* Detect failure. */
14909 if (dpy == 0)
14911 UNBLOCK_INPUT;
14912 return 0;
14915 /* We have definitely succeeded. Record the new connection. */
14917 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14918 bzero (dpyinfo, sizeof *dpyinfo);
14920 #ifdef MULTI_KBOARD
14922 struct x_display_info *share;
14923 Lisp_Object tail;
14925 for (share = x_display_list, tail = x_display_name_list; share;
14926 share = share->next, tail = XCDR (tail))
14927 if (same_x_server (SDATA (XCAR (XCAR (tail))),
14928 SDATA (display_name)))
14929 break;
14930 if (share)
14931 dpyinfo->kboard = share->kboard;
14932 else
14934 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14935 init_kboard (dpyinfo->kboard);
14936 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14938 char *vendor = ServerVendor (dpy);
14939 UNBLOCK_INPUT;
14940 dpyinfo->kboard->Vsystem_key_alist
14941 = call1 (Qvendor_specific_keysyms,
14942 build_string (vendor ? vendor : ""));
14943 BLOCK_INPUT;
14946 dpyinfo->kboard->next_kboard = all_kboards;
14947 all_kboards = dpyinfo->kboard;
14948 /* Don't let the initial kboard remain current longer than necessary.
14949 That would cause problems if a file loaded on startup tries to
14950 prompt in the mini-buffer. */
14951 if (current_kboard == initial_kboard)
14952 current_kboard = dpyinfo->kboard;
14954 dpyinfo->kboard->reference_count++;
14956 #endif
14958 /* Put this display on the chain. */
14959 dpyinfo->next = x_display_list;
14960 x_display_list = dpyinfo;
14962 /* Put it on x_display_name_list as well, to keep them parallel. */
14963 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14964 x_display_name_list);
14965 dpyinfo->name_list_element = XCAR (x_display_name_list);
14967 dpyinfo->display = dpy;
14969 #if 0
14970 XSetAfterFunction (x_current_display, x_trace_wire);
14971 #endif /* ! 0 */
14973 dpyinfo->x_id_name
14974 = (char *) xmalloc (SBYTES (Vinvocation_name)
14975 + SBYTES (Vsystem_name)
14976 + 2);
14977 sprintf (dpyinfo->x_id_name, "%s@%s",
14978 SDATA (Vinvocation_name), SDATA (Vsystem_name));
14980 /* Figure out which modifier bits mean what. */
14981 x_find_modifier_meanings (dpyinfo);
14983 /* Get the scroll bar cursor. */
14984 dpyinfo->vertical_scroll_bar_cursor
14985 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14987 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14988 resource_name, EMACS_CLASS);
14989 #ifdef HAVE_XRMSETDATABASE
14990 XrmSetDatabase (dpyinfo->display, xrdb);
14991 #else
14992 dpyinfo->display->db = xrdb;
14993 #endif
14994 /* Put the rdb where we can find it in a way that works on
14995 all versions. */
14996 dpyinfo->xrdb = xrdb;
14998 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14999 DefaultScreen (dpyinfo->display));
15000 select_visual (dpyinfo);
15001 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
15002 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
15003 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
15004 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
15005 dpyinfo->grabbed = 0;
15006 dpyinfo->reference_count = 0;
15007 dpyinfo->icon_bitmap_id = -1;
15008 dpyinfo->font_table = NULL;
15009 dpyinfo->n_fonts = 0;
15010 dpyinfo->font_table_size = 0;
15011 dpyinfo->bitmaps = 0;
15012 dpyinfo->bitmaps_size = 0;
15013 dpyinfo->bitmaps_last = 0;
15014 dpyinfo->scratch_cursor_gc = 0;
15015 dpyinfo->mouse_face_mouse_frame = 0;
15016 dpyinfo->mouse_face_deferred_gc = 0;
15017 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
15018 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
15019 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
15020 dpyinfo->mouse_face_window = Qnil;
15021 dpyinfo->mouse_face_overlay = Qnil;
15022 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
15023 dpyinfo->mouse_face_defer = 0;
15024 dpyinfo->mouse_face_hidden = 0;
15025 dpyinfo->x_focus_frame = 0;
15026 dpyinfo->x_focus_event_frame = 0;
15027 dpyinfo->x_highlight_frame = 0;
15028 dpyinfo->image_cache = make_image_cache ();
15030 /* See if a private colormap is requested. */
15031 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
15033 if (dpyinfo->visual->class == PseudoColor)
15035 Lisp_Object value;
15036 value = display_x_get_resource (dpyinfo,
15037 build_string ("privateColormap"),
15038 build_string ("PrivateColormap"),
15039 Qnil, Qnil);
15040 if (STRINGP (value)
15041 && (!strcmp (SDATA (value), "true")
15042 || !strcmp (SDATA (value), "on")))
15043 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
15046 else
15047 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
15048 dpyinfo->visual, AllocNone);
15051 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
15052 double pixels = DisplayHeight (dpyinfo->display, screen_number);
15053 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
15054 dpyinfo->resy = pixels * 25.4 / mm;
15055 pixels = DisplayWidth (dpyinfo->display, screen_number);
15056 mm = DisplayWidthMM (dpyinfo->display, screen_number);
15057 dpyinfo->resx = pixels * 25.4 / mm;
15060 dpyinfo->Xatom_wm_protocols
15061 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
15062 dpyinfo->Xatom_wm_take_focus
15063 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
15064 dpyinfo->Xatom_wm_save_yourself
15065 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
15066 dpyinfo->Xatom_wm_delete_window
15067 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
15068 dpyinfo->Xatom_wm_change_state
15069 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
15070 dpyinfo->Xatom_wm_configure_denied
15071 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
15072 dpyinfo->Xatom_wm_window_moved
15073 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
15074 dpyinfo->Xatom_editres
15075 = XInternAtom (dpyinfo->display, "Editres", False);
15076 dpyinfo->Xatom_CLIPBOARD
15077 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
15078 dpyinfo->Xatom_TIMESTAMP
15079 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
15080 dpyinfo->Xatom_TEXT
15081 = XInternAtom (dpyinfo->display, "TEXT", False);
15082 dpyinfo->Xatom_COMPOUND_TEXT
15083 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
15084 dpyinfo->Xatom_UTF8_STRING
15085 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
15086 dpyinfo->Xatom_DELETE
15087 = XInternAtom (dpyinfo->display, "DELETE", False);
15088 dpyinfo->Xatom_MULTIPLE
15089 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
15090 dpyinfo->Xatom_INCR
15091 = XInternAtom (dpyinfo->display, "INCR", False);
15092 dpyinfo->Xatom_EMACS_TMP
15093 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
15094 dpyinfo->Xatom_TARGETS
15095 = XInternAtom (dpyinfo->display, "TARGETS", False);
15096 dpyinfo->Xatom_NULL
15097 = XInternAtom (dpyinfo->display, "NULL", False);
15098 dpyinfo->Xatom_ATOM_PAIR
15099 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
15100 /* For properties of font. */
15101 dpyinfo->Xatom_PIXEL_SIZE
15102 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
15103 dpyinfo->Xatom_MULE_BASELINE_OFFSET
15104 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
15105 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
15106 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
15107 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
15108 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
15110 /* Ghostscript support. */
15111 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
15112 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
15114 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
15115 False);
15117 dpyinfo->cut_buffers_initialized = 0;
15119 connection = ConnectionNumber (dpyinfo->display);
15120 dpyinfo->connection = connection;
15123 char null_bits[1];
15125 null_bits[0] = 0x00;
15127 dpyinfo->null_pixel
15128 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15129 null_bits, 1, 1, (long) 0, (long) 0,
15134 extern int gray_bitmap_width, gray_bitmap_height;
15135 extern char *gray_bitmap_bits;
15136 dpyinfo->gray
15137 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15138 gray_bitmap_bits,
15139 gray_bitmap_width, gray_bitmap_height,
15140 (unsigned long) 1, (unsigned long) 0, 1);
15143 #ifdef HAVE_X_I18N
15144 xim_initialize (dpyinfo, resource_name);
15145 #endif
15147 #ifdef subprocesses
15148 /* This is only needed for distinguishing keyboard and process input. */
15149 if (connection != 0)
15150 add_keyboard_wait_descriptor (connection);
15151 #endif
15153 #ifndef F_SETOWN_BUG
15154 #ifdef F_SETOWN
15155 #ifdef F_SETOWN_SOCK_NEG
15156 /* stdin is a socket here */
15157 fcntl (connection, F_SETOWN, -getpid ());
15158 #else /* ! defined (F_SETOWN_SOCK_NEG) */
15159 fcntl (connection, F_SETOWN, getpid ());
15160 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
15161 #endif /* ! defined (F_SETOWN) */
15162 #endif /* F_SETOWN_BUG */
15164 #ifdef SIGIO
15165 if (interrupt_input)
15166 init_sigio (connection);
15167 #endif /* ! defined (SIGIO) */
15169 #ifdef USE_LUCID
15170 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
15171 /* Make sure that we have a valid font for dialog boxes
15172 so that Xt does not crash. */
15174 Display *dpy = dpyinfo->display;
15175 XrmValue d, fr, to;
15176 Font font;
15177 int count;
15179 d.addr = (XPointer)&dpy;
15180 d.size = sizeof (Display *);
15181 fr.addr = XtDefaultFont;
15182 fr.size = sizeof (XtDefaultFont);
15183 to.size = sizeof (Font *);
15184 to.addr = (XPointer)&font;
15185 count = x_catch_errors (dpy);
15186 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
15187 abort ();
15188 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
15189 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
15190 x_uncatch_errors (dpy, count);
15192 #endif
15193 #endif
15195 /* See if we should run in synchronous mode. This is useful
15196 for debugging X code. */
15198 Lisp_Object value;
15199 value = display_x_get_resource (dpyinfo,
15200 build_string ("synchronous"),
15201 build_string ("Synchronous"),
15202 Qnil, Qnil);
15203 if (STRINGP (value)
15204 && (!strcmp (SDATA (value), "true")
15205 || !strcmp (SDATA (value), "on")))
15206 XSynchronize (dpyinfo->display, True);
15209 UNBLOCK_INPUT;
15211 return dpyinfo;
15214 /* Get rid of display DPYINFO, assuming all frames are already gone,
15215 and without sending any more commands to the X server. */
15217 void
15218 x_delete_display (dpyinfo)
15219 struct x_display_info *dpyinfo;
15221 delete_keyboard_wait_descriptor (dpyinfo->connection);
15223 /* Discard this display from x_display_name_list and x_display_list.
15224 We can't use Fdelq because that can quit. */
15225 if (! NILP (x_display_name_list)
15226 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
15227 x_display_name_list = XCDR (x_display_name_list);
15228 else
15230 Lisp_Object tail;
15232 tail = x_display_name_list;
15233 while (CONSP (tail) && CONSP (XCDR (tail)))
15235 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
15237 XSETCDR (tail, XCDR (XCDR (tail)));
15238 break;
15240 tail = XCDR (tail);
15244 if (next_noop_dpyinfo == dpyinfo)
15245 next_noop_dpyinfo = dpyinfo->next;
15247 if (x_display_list == dpyinfo)
15248 x_display_list = dpyinfo->next;
15249 else
15251 struct x_display_info *tail;
15253 for (tail = x_display_list; tail; tail = tail->next)
15254 if (tail->next == dpyinfo)
15255 tail->next = tail->next->next;
15258 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
15259 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
15260 XrmDestroyDatabase (dpyinfo->xrdb);
15261 #endif
15262 #endif
15263 #ifdef MULTI_KBOARD
15264 if (--dpyinfo->kboard->reference_count == 0)
15265 delete_kboard (dpyinfo->kboard);
15266 #endif
15267 #ifdef HAVE_X_I18N
15268 if (dpyinfo->xim)
15269 xim_close_dpy (dpyinfo);
15270 #endif
15272 xfree (dpyinfo->font_table);
15273 xfree (dpyinfo->x_id_name);
15274 xfree (dpyinfo->color_cells);
15275 xfree (dpyinfo);
15279 /* Set up use of X before we make the first connection. */
15281 static struct redisplay_interface x_redisplay_interface =
15283 x_produce_glyphs,
15284 x_write_glyphs,
15285 x_insert_glyphs,
15286 x_clear_end_of_line,
15287 x_scroll_run,
15288 x_after_update_window_line,
15289 x_update_window_begin,
15290 x_update_window_end,
15291 XTcursor_to,
15292 x_flush,
15293 x_clear_mouse_face,
15294 x_get_glyph_overhangs,
15295 x_fix_overlapping_area
15298 void
15299 x_initialize ()
15301 rif = &x_redisplay_interface;
15303 clear_frame_hook = x_clear_frame;
15304 ins_del_lines_hook = x_ins_del_lines;
15305 delete_glyphs_hook = x_delete_glyphs;
15306 ring_bell_hook = XTring_bell;
15307 reset_terminal_modes_hook = XTreset_terminal_modes;
15308 set_terminal_modes_hook = XTset_terminal_modes;
15309 update_begin_hook = x_update_begin;
15310 update_end_hook = x_update_end;
15311 set_terminal_window_hook = XTset_terminal_window;
15312 read_socket_hook = XTread_socket;
15313 frame_up_to_date_hook = XTframe_up_to_date;
15314 mouse_position_hook = XTmouse_position;
15315 frame_rehighlight_hook = XTframe_rehighlight;
15316 frame_raise_lower_hook = XTframe_raise_lower;
15317 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
15318 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
15319 redeem_scroll_bar_hook = XTredeem_scroll_bar;
15320 judge_scroll_bars_hook = XTjudge_scroll_bars;
15321 estimate_mode_line_height_hook = x_estimate_mode_line_height;
15323 scroll_region_ok = 1; /* we'll scroll partial frames */
15324 char_ins_del_ok = 1;
15325 line_ins_del_ok = 1; /* we'll just blt 'em */
15326 fast_clear_end_of_line = 1; /* X does this well */
15327 memory_below_frame = 0; /* we don't remember what scrolls
15328 off the bottom */
15329 baud_rate = 19200;
15331 x_noop_count = 0;
15332 last_tool_bar_item = -1;
15333 any_help_event_p = 0;
15335 /* Try to use interrupt input; if we can't, then start polling. */
15336 Fset_input_mode (Qt, Qnil, Qt, Qnil);
15338 #ifdef USE_X_TOOLKIT
15339 XtToolkitInitialize ();
15341 Xt_app_con = XtCreateApplicationContext ();
15343 /* Register a converter from strings to pixels, which uses
15344 Emacs' color allocation infrastructure. */
15345 XtAppSetTypeConverter (Xt_app_con,
15346 XtRString, XtRPixel, cvt_string_to_pixel,
15347 cvt_string_to_pixel_args,
15348 XtNumber (cvt_string_to_pixel_args),
15349 XtCacheByDisplay, cvt_pixel_dtor);
15351 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
15353 /* Install an asynchronous timer that processes Xt timeout events
15354 every 0.1s. This is necessary because some widget sets use
15355 timeouts internally, for example the LessTif menu bar, or the
15356 Xaw3d scroll bar. When Xt timouts aren't processed, these
15357 widgets don't behave normally. */
15359 EMACS_TIME interval;
15360 EMACS_SET_SECS_USECS (interval, 0, 100000);
15361 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
15363 #endif
15365 #ifdef USE_TOOLKIT_SCROLL_BARS
15366 xaw3d_arrow_scroll = False;
15367 xaw3d_pick_top = True;
15368 #endif
15370 /* Note that there is no real way portable across R3/R4 to get the
15371 original error handler. */
15372 XSetErrorHandler (x_error_handler);
15373 XSetIOErrorHandler (x_io_error_quitter);
15375 /* Disable Window Change signals; they are handled by X events. */
15376 #ifdef SIGWINCH
15377 signal (SIGWINCH, SIG_DFL);
15378 #endif /* SIGWINCH */
15380 signal (SIGPIPE, x_connection_signal);
15382 #ifdef HAVE_X_SM
15383 x_session_initialize ();
15384 #endif
15388 void
15389 syms_of_xterm ()
15391 staticpro (&x_error_message_string);
15392 x_error_message_string = Qnil;
15394 staticpro (&x_display_name_list);
15395 x_display_name_list = Qnil;
15397 staticpro (&last_mouse_scroll_bar);
15398 last_mouse_scroll_bar = Qnil;
15400 staticpro (&Qvendor_specific_keysyms);
15401 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
15403 staticpro (&Qutf_8);
15404 Qutf_8 = intern ("utf-8");
15405 staticpro (&Qlatin_1);
15406 Qlatin_1 = intern ("latin-1");
15408 staticpro (&last_mouse_press_frame);
15409 last_mouse_press_frame = Qnil;
15411 help_echo = Qnil;
15412 staticpro (&help_echo);
15413 help_echo_object = Qnil;
15414 staticpro (&help_echo_object);
15415 help_echo_window = Qnil;
15416 staticpro (&help_echo_window);
15417 previous_help_echo = Qnil;
15418 staticpro (&previous_help_echo);
15419 help_echo_pos = -1;
15421 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
15422 doc: /* *Non-nil means autoselect window with mouse pointer. */);
15423 mouse_autoselect_window = 0;
15425 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
15426 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
15427 For example, if a block cursor is over a tab, it will be drawn as
15428 wide as that tab on the display. */);
15429 x_stretch_cursor_p = 0;
15431 DEFVAR_BOOL ("x-use-underline-position-properties",
15432 &x_use_underline_position_properties,
15433 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15434 nil means ignore them. If you encounter fonts with bogus
15435 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15436 to 4.1, set this to nil. */);
15437 x_use_underline_position_properties = 1;
15439 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
15440 doc: /* What X toolkit scroll bars Emacs uses.
15441 A value of nil means Emacs doesn't use X toolkit scroll bars.
15442 Otherwise, value is a symbol describing the X toolkit. */);
15443 #ifdef USE_TOOLKIT_SCROLL_BARS
15444 #ifdef USE_MOTIF
15445 Vx_toolkit_scroll_bars = intern ("motif");
15446 #elif defined HAVE_XAW3D
15447 Vx_toolkit_scroll_bars = intern ("xaw3d");
15448 #else
15449 Vx_toolkit_scroll_bars = intern ("xaw");
15450 #endif
15451 #else
15452 Vx_toolkit_scroll_bars = Qnil;
15453 #endif
15455 staticpro (&last_mouse_motion_frame);
15456 last_mouse_motion_frame = Qnil;
15458 Qmodifier_value = intern ("modifier-value");
15459 Qalt = intern ("alt");
15460 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
15461 Qhyper = intern ("hyper");
15462 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
15463 Qmeta = intern ("meta");
15464 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
15465 Qsuper = intern ("super");
15466 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
15468 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
15469 doc: /* Which keys Emacs uses for the alt modifier.
15470 This should be one of the symbols `alt', `hyper', `meta', `super'.
15471 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15472 is nil, which is the same as `alt'. */);
15473 Vx_alt_keysym = Qnil;
15475 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
15476 doc: /* Which keys Emacs uses for the hyper modifier.
15477 This should be one of the symbols `alt', `hyper', `meta', `super'.
15478 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15479 default is nil, which is the same as `hyper'. */);
15480 Vx_hyper_keysym = Qnil;
15482 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
15483 doc: /* Which keys Emacs uses for the meta modifier.
15484 This should be one of the symbols `alt', `hyper', `meta', `super'.
15485 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15486 default is nil, which is the same as `meta'. */);
15487 Vx_meta_keysym = Qnil;
15489 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
15490 doc: /* Which keys Emacs uses for the super modifier.
15491 This should be one of the symbols `alt', `hyper', `meta', `super'.
15492 For example, `super' means use the Super_L and Super_R keysyms. The
15493 default is nil, which is the same as `super'. */);
15494 Vx_super_keysym = Qnil;
15496 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
15497 doc: /* Hash table of character codes indexed by X keysym codes. */);
15498 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
15499 make_float (DEFAULT_REHASH_SIZE),
15500 make_float (DEFAULT_REHASH_THRESHOLD),
15501 Qnil, Qnil, Qnil);
15504 #endif /* HAVE_X_WINDOWS */