(struct face): Member `charset' deleted.
[emacs.git] / src / xterm.c
blob821866e638c5a24d14cd50339d2296b2e27a6dba
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
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 "character.h"
72 #include "coding.h"
73 #include "ccl.h"
74 #include "frame.h"
75 #include "dispextern.h"
76 #include "fontset.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #include "gnu.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "keyboard.h"
85 #include "intervals.h"
86 #include "process.h"
87 #include "atimer.h"
88 #include "keymap.h"
90 #ifdef USE_X_TOOLKIT
91 #include <X11/Shell.h>
92 #endif
94 #ifdef HAVE_SYS_TIME_H
95 #include <sys/time.h>
96 #endif
97 #ifdef HAVE_UNISTD_H
98 #include <unistd.h>
99 #endif
101 #ifdef USE_LUCID
102 extern int xlwmenu_window_p P_ ((Widget w, Window window));
103 extern void xlwmenu_redisplay P_ ((Widget));
104 #endif
106 #ifdef USE_X_TOOLKIT
108 extern void free_frame_menubar P_ ((struct frame *));
109 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
110 int));
112 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
113 #define HACK_EDITRES
114 extern void _XEditResCheckMessages ();
115 #endif /* not NO_EDITRES */
117 /* Include toolkit specific headers for the scroll bar widget. */
119 #ifdef USE_TOOLKIT_SCROLL_BARS
120 #if defined USE_MOTIF
121 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
122 #include <Xm/ScrollBar.h>
123 #else /* !USE_MOTIF i.e. use Xaw */
125 #ifdef HAVE_XAW3D
126 #include <X11/Xaw3d/Simple.h>
127 #include <X11/Xaw3d/Scrollbar.h>
128 #define ARROW_SCROLLBAR
129 #include <X11/Xaw3d/ScrollbarP.h>
130 #else /* !HAVE_XAW3D */
131 #include <X11/Xaw/Simple.h>
132 #include <X11/Xaw/Scrollbar.h>
133 #endif /* !HAVE_XAW3D */
134 #ifndef XtNpickTop
135 #define XtNpickTop "pickTop"
136 #endif /* !XtNpickTop */
137 #endif /* !USE_MOTIF */
138 #endif /* USE_TOOLKIT_SCROLL_BARS */
140 #endif /* USE_X_TOOLKIT */
142 #ifndef USE_X_TOOLKIT
143 #define x_any_window_to_frame x_window_to_frame
144 #define x_top_window_to_frame x_window_to_frame
145 #endif
147 #ifdef USE_X_TOOLKIT
148 #include "widget.h"
149 #ifndef XtNinitialState
150 #define XtNinitialState "initialState"
151 #endif
152 #endif
154 #ifdef HAVE_X11R6
155 /* This isn't prototyped in OSF 5.0 or or XFree 4.1. */
156 extern char * XSetIMValues P_ ((XIM, ...));
157 #endif
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
164 /* Fringe bitmaps. */
166 enum fringe_bitmap_type
168 NO_FRINGE_BITMAP,
169 LEFT_TRUNCATION_BITMAP,
170 RIGHT_TRUNCATION_BITMAP,
171 OVERLAY_ARROW_BITMAP,
172 CONTINUED_LINE_BITMAP,
173 CONTINUATION_LINE_BITMAP,
174 ZV_LINE_BITMAP
177 /* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
180 #define zv_width 8
181 #define zv_height 72
182 #define zv_period 3
183 static unsigned char zv_bits[] = {
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
186 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
187 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
188 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
189 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
190 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
191 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
193 /* An arrow like this: `<-'. */
195 #define left_width 8
196 #define left_height 8
197 static unsigned char left_bits[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
200 /* Right truncation arrow bitmap `->'. */
202 #define right_width 8
203 #define right_height 8
204 static unsigned char right_bits[] = {
205 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
207 /* Marker for continued lines. */
209 #define continued_width 8
210 #define continued_height 8
211 static unsigned char continued_bits[] = {
212 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
214 /* Marker for continuation lines. */
216 #define continuation_width 8
217 #define continuation_height 8
218 static unsigned char continuation_bits[] = {
219 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
221 /* Overlay arrow bitmap. */
223 #if 0
224 /* A bomb. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
229 #else
230 /* A triangular arrow. */
231 #define ov_width 8
232 #define ov_height 8
233 static unsigned char ov_bits[] = {
234 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
236 #endif
238 extern Lisp_Object Qhelp_echo;
241 /* Non-nil means Emacs uses toolkit scroll bars. */
243 Lisp_Object Vx_toolkit_scroll_bars;
245 /* If a string, XTread_socket generates an event to display that string.
246 (The display is done in read_char.) */
248 static Lisp_Object help_echo;
249 static Lisp_Object help_echo_window;
250 static Lisp_Object help_echo_object;
251 static int help_echo_pos;
253 /* Temporary variable for XTread_socket. */
255 static Lisp_Object previous_help_echo;
257 /* Non-zero means that a HELP_EVENT has been generated since Emacs
258 start. */
260 static int any_help_event_p;
262 /* Non-zero means autoselect window with the mouse cursor. */
264 int x_autoselect_window_p;
266 /* Non-zero means draw block and hollow cursor as wide as the glyph
267 under it. For example, if a block cursor is over a tab, it will be
268 drawn as wide as that tab on the display. */
270 int x_stretch_cursor_p;
272 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
274 int x_use_underline_position_properties;
276 /* This is a chain of structures for all the X displays currently in
277 use. */
279 struct x_display_info *x_display_list;
281 /* This is a list of cons cells, each of the form (NAME
282 . FONT-LIST-CACHE), one for each element of x_display_list and in
283 the same order. NAME is the name of the frame. FONT-LIST-CACHE
284 records previous values returned by x-list-fonts. */
286 Lisp_Object x_display_name_list;
288 /* Frame being updated by update_frame. This is declared in term.c.
289 This is set by update_begin and looked at by all the XT functions.
290 It is zero while not inside an update. In that case, the XT
291 functions assume that `selected_frame' is the frame to apply to. */
293 extern struct frame *updating_frame;
295 /* This is a frame waiting to be auto-raised, within XTread_socket. */
297 struct frame *pending_autoraise_frame;
299 #ifdef USE_X_TOOLKIT
300 /* The application context for Xt use. */
301 XtAppContext Xt_app_con;
302 static String Xt_default_resources[] = {0};
303 #endif /* USE_X_TOOLKIT */
305 /* Nominal cursor position -- where to draw output.
306 HPOS and VPOS are window relative glyph matrix coordinates.
307 X and Y are window relative pixel coordinates. */
309 struct cursor_pos output_cursor;
311 /* Non-zero means user is interacting with a toolkit scroll bar. */
313 static int toolkit_scroll_bar_interaction;
315 /* Mouse movement.
317 Formerly, we used PointerMotionHintMask (in standard_event_mask)
318 so that we would have to call XQueryPointer after each MotionNotify
319 event to ask for another such event. However, this made mouse tracking
320 slow, and there was a bug that made it eventually stop.
322 Simply asking for MotionNotify all the time seems to work better.
324 In order to avoid asking for motion events and then throwing most
325 of them away or busy-polling the server for mouse positions, we ask
326 the server for pointer motion hints. This means that we get only
327 one event per group of mouse movements. "Groups" are delimited by
328 other kinds of events (focus changes and button clicks, for
329 example), or by XQueryPointer calls; when one of these happens, we
330 get another MotionNotify event the next time the mouse moves. This
331 is at least as efficient as getting motion events when mouse
332 tracking is on, and I suspect only negligibly worse when tracking
333 is off. */
335 /* Where the mouse was last time we reported a mouse event. */
337 FRAME_PTR last_mouse_frame;
338 static XRectangle last_mouse_glyph;
339 static Lisp_Object last_mouse_press_frame;
341 /* The scroll bar in which the last X motion event occurred.
343 If the last X motion event occurred in a scroll bar, we set this so
344 XTmouse_position can know whether to report a scroll bar motion or
345 an ordinary motion.
347 If the last X motion event didn't occur in a scroll bar, we set
348 this to Qnil, to tell XTmouse_position to return an ordinary motion
349 event. */
351 static Lisp_Object last_mouse_scroll_bar;
353 /* This is a hack. We would really prefer that XTmouse_position would
354 return the time associated with the position it returns, but there
355 doesn't seem to be any way to wrest the time-stamp from the server
356 along with the position query. So, we just keep track of the time
357 of the last movement we received, and return that in hopes that
358 it's somewhat accurate. */
360 static Time last_mouse_movement_time;
362 /* Incremented by XTread_socket whenever it really tries to read
363 events. */
365 #ifdef __STDC__
366 static int volatile input_signal_count;
367 #else
368 static int input_signal_count;
369 #endif
371 /* Used locally within XTread_socket. */
373 static int x_noop_count;
375 /* Initial values of argv and argc. */
377 extern char **initial_argv;
378 extern int initial_argc;
380 extern Lisp_Object Vcommand_line_args, Vsystem_name;
382 /* Tells if a window manager is present or not. */
384 extern Lisp_Object Vx_no_window_manager;
386 extern Lisp_Object Qface, Qmouse_face;
388 extern int errno;
390 /* A mask of extra modifier bits to put into every keyboard char. */
392 extern int extra_keyboard_modifiers;
394 /* The keysyms to use for the various modifiers. */
396 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
397 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
399 static Lisp_Object Qvendor_specific_keysyms;
401 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
402 extern Lisp_Object x_icon_type P_ ((struct frame *));
405 /* Enumeration for overriding/changing the face to use for drawing
406 glyphs in x_draw_glyphs. */
408 enum draw_glyphs_face
410 DRAW_NORMAL_TEXT,
411 DRAW_INVERSE_VIDEO,
412 DRAW_CURSOR,
413 DRAW_MOUSE_FACE,
414 DRAW_IMAGE_RAISED,
415 DRAW_IMAGE_SUNKEN
418 static int cursor_in_mouse_face_p P_ ((struct window *));
419 static int clear_mouse_face P_ ((struct x_display_info *));
420 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
421 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
422 static const XColor *x_color_cells P_ ((Display *, int *));
423 static void x_update_window_end P_ ((struct window *, int, int));
424 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
425 void x_delete_display P_ ((struct x_display_info *));
426 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
427 unsigned));
428 static int fast_find_position P_ ((struct window *, int, int *, int *,
429 int *, int *, Lisp_Object));
430 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
431 int *, int *, int *, int *, int));
432 static void set_output_cursor P_ ((struct cursor_pos *));
433 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
434 int *, int *, int *, int));
435 static void note_mode_line_highlight P_ ((struct window *, 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 void XTframe_rehighlight P_ ((struct frame *));
471 static void x_frame_rehighlight P_ ((struct x_display_info *));
472 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
473 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
474 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
475 XRectangle *));
476 static void expose_frame P_ ((struct frame *, int, int, int, int));
477 static int expose_window_tree P_ ((struct window *, XRectangle *));
478 static int expose_window P_ ((struct window *, XRectangle *));
479 static void expose_area P_ ((struct window *, struct glyph_row *,
480 XRectangle *, enum glyph_row_area));
481 static int expose_line P_ ((struct window *, struct glyph_row *,
482 XRectangle *));
483 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
484 static void x_update_window_cursor P_ ((struct window *, int));
485 static void x_erase_phys_cursor P_ ((struct window *));
486 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
487 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
488 enum fringe_bitmap_type, int left_p));
490 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
491 GC, int));
492 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
493 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
494 static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
495 int, int, int, int));
496 static void x_flush P_ ((struct frame *f));
497 static void x_update_begin P_ ((struct frame *));
498 static void x_update_window_begin P_ ((struct window *));
499 static void x_draw_vertical_border P_ ((struct window *));
500 static void x_after_update_window_line P_ ((struct glyph_row *));
501 static INLINE void take_vertical_position_into_account P_ ((struct it *));
502 static void x_produce_stretch_glyph P_ ((struct it *));
503 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
504 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
505 enum scroll_bar_part *,
506 Lisp_Object *, Lisp_Object *,
507 unsigned long *));
508 static void x_check_fullscreen P_ ((struct frame *));
509 static void x_check_fullscreen_move P_ ((struct frame *));
511 /* Flush display of frame F, or of all frames if F is null. */
513 static void
514 x_flush (f)
515 struct frame *f;
517 BLOCK_INPUT;
518 if (f == NULL)
520 Lisp_Object rest, frame;
521 FOR_EACH_FRAME (rest, frame)
522 x_flush (XFRAME (frame));
524 else if (FRAME_X_P (f))
525 XFlush (FRAME_X_DISPLAY (f));
526 UNBLOCK_INPUT;
530 /* Remove calls to XFlush by defining XFlush to an empty replacement.
531 Calls to XFlush should be unnecessary because the X output buffer
532 is flushed automatically as needed by calls to XPending,
533 XNextEvent, or XWindowEvent according to the XFlush man page.
534 XTread_socket calls XPending. Removing XFlush improves
535 performance. */
537 #define XFlush(DISPLAY) (void) 0
540 /***********************************************************************
541 Debugging
542 ***********************************************************************/
544 #if 0
546 /* This is a function useful for recording debugging information about
547 the sequence of occurrences in this file. */
549 struct record
551 char *locus;
552 int type;
555 struct record event_record[100];
557 int event_record_index;
559 record_event (locus, type)
560 char *locus;
561 int type;
563 if (event_record_index == sizeof (event_record) / sizeof (struct record))
564 event_record_index = 0;
566 event_record[event_record_index].locus = locus;
567 event_record[event_record_index].type = type;
568 event_record_index++;
571 #endif /* 0 */
575 /* Return the struct x_display_info corresponding to DPY. */
577 struct x_display_info *
578 x_display_info_for_display (dpy)
579 Display *dpy;
581 struct x_display_info *dpyinfo;
583 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
584 if (dpyinfo->display == dpy)
585 return dpyinfo;
587 return 0;
592 /***********************************************************************
593 Starting and ending an update
594 ***********************************************************************/
596 /* Start an update of frame F. This function is installed as a hook
597 for update_begin, i.e. it is called when update_begin is called.
598 This function is called prior to calls to x_update_window_begin for
599 each window being updated. Currently, there is nothing to do here
600 because all interesting stuff is done on a window basis. */
602 static void
603 x_update_begin (f)
604 struct frame *f;
606 /* Nothing to do. */
610 /* Start update of window W. Set the global variable updated_window
611 to the window being updated and set output_cursor to the cursor
612 position of W. */
614 static void
615 x_update_window_begin (w)
616 struct window *w;
618 struct frame *f = XFRAME (WINDOW_FRAME (w));
619 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
621 updated_window = w;
622 set_output_cursor (&w->cursor);
624 BLOCK_INPUT;
626 if (f == display_info->mouse_face_mouse_frame)
628 /* Don't do highlighting for mouse motion during the update. */
629 display_info->mouse_face_defer = 1;
631 /* If F needs to be redrawn, simply forget about any prior mouse
632 highlighting. */
633 if (FRAME_GARBAGED_P (f))
634 display_info->mouse_face_window = Qnil;
636 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
637 their mouse_face_p flag set, which means that they are always
638 unequal to rows in a desired matrix which never have that
639 flag set. So, rows containing mouse-face glyphs are never
640 scrolled, and we don't have to switch the mouse highlight off
641 here to prevent it from being scrolled. */
643 /* Can we tell that this update does not affect the window
644 where the mouse highlight is? If so, no need to turn off.
645 Likewise, don't do anything if the frame is garbaged;
646 in that case, the frame's current matrix that we would use
647 is all wrong, and we will redisplay that line anyway. */
648 if (!NILP (display_info->mouse_face_window)
649 && w == XWINDOW (display_info->mouse_face_window))
651 int i;
653 for (i = 0; i < w->desired_matrix->nrows; ++i)
654 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
655 break;
657 if (i < w->desired_matrix->nrows)
658 clear_mouse_face (display_info);
660 #endif /* 0 */
663 UNBLOCK_INPUT;
667 /* Draw a vertical window border to the right of window W if W doesn't
668 have vertical scroll bars. */
670 static void
671 x_draw_vertical_border (w)
672 struct window *w;
674 struct frame *f = XFRAME (WINDOW_FRAME (w));
676 /* Redraw borders between horizontally adjacent windows. Don't
677 do it for frames with vertical scroll bars because either the
678 right scroll bar of a window, or the left scroll bar of its
679 neighbor will suffice as a border. */
680 if (!WINDOW_RIGHTMOST_P (w)
681 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
683 int x0, x1, y0, y1;
685 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
686 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
687 y1 -= 1;
689 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
690 f->output_data.x->normal_gc, x1, y0, x1, y1);
695 /* End update of window W (which is equal to updated_window).
697 Draw vertical borders between horizontally adjacent windows, and
698 display W's cursor if CURSOR_ON_P is non-zero.
700 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
701 glyphs in mouse-face were overwritten. In that case we have to
702 make sure that the mouse-highlight is properly redrawn.
704 W may be a menu bar pseudo-window in case we don't have X toolkit
705 support. Such windows don't have a cursor, so don't display it
706 here. */
708 static void
709 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
710 struct window *w;
711 int cursor_on_p, mouse_face_overwritten_p;
713 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
715 if (!w->pseudo_window_p)
717 BLOCK_INPUT;
719 if (cursor_on_p)
720 x_display_and_set_cursor (w, 1, output_cursor.hpos,
721 output_cursor.vpos,
722 output_cursor.x, output_cursor.y);
724 x_draw_vertical_border (w);
725 UNBLOCK_INPUT;
728 /* If a row with mouse-face was overwritten, arrange for
729 XTframe_up_to_date to redisplay the mouse highlight. */
730 if (mouse_face_overwritten_p)
732 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
733 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
734 dpyinfo->mouse_face_window = Qnil;
737 updated_window = NULL;
741 /* End update of frame F. This function is installed as a hook in
742 update_end. */
744 static void
745 x_update_end (f)
746 struct frame *f;
748 /* Mouse highlight may be displayed again. */
749 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
751 BLOCK_INPUT;
752 XFlush (FRAME_X_DISPLAY (f));
753 UNBLOCK_INPUT;
757 /* This function is called from various places in xdisp.c whenever a
758 complete update has been performed. The global variable
759 updated_window is not available here. */
761 static void
762 XTframe_up_to_date (f)
763 struct frame *f;
765 if (FRAME_X_P (f))
767 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
769 if (dpyinfo->mouse_face_deferred_gc
770 || f == dpyinfo->mouse_face_mouse_frame)
772 BLOCK_INPUT;
773 if (dpyinfo->mouse_face_mouse_frame)
774 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
775 dpyinfo->mouse_face_mouse_x,
776 dpyinfo->mouse_face_mouse_y);
777 dpyinfo->mouse_face_deferred_gc = 0;
778 UNBLOCK_INPUT;
784 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
785 arrow bitmaps, or clear the fringes if no bitmaps are required
786 before DESIRED_ROW is made current. The window being updated is
787 found in updated_window. This function It is called from
788 update_window_line only if it is known that there are differences
789 between bitmaps to be drawn between current row and DESIRED_ROW. */
791 static void
792 x_after_update_window_line (desired_row)
793 struct glyph_row *desired_row;
795 struct window *w = updated_window;
796 struct frame *f;
797 int width, height;
799 xassert (w);
801 if (!desired_row->mode_line_p && !w->pseudo_window_p)
803 BLOCK_INPUT;
804 x_draw_row_fringe_bitmaps (w, desired_row);
805 UNBLOCK_INPUT;
808 /* When a window has disappeared, make sure that no rest of
809 full-width rows stays visible in the internal border. Could
810 check here if updated_window is the leftmost/rightmost window,
811 but I guess it's not worth doing since vertically split windows
812 are almost never used, internal border is rarely set, and the
813 overhead is very small. */
814 if (windows_or_buffers_changed
815 && desired_row->full_width_p
816 && (f = XFRAME (w->frame),
817 width = FRAME_INTERNAL_BORDER_WIDTH (f),
818 width != 0)
819 && (height = desired_row->visible_height,
820 height > 0))
822 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
824 /* Internal border is drawn below the tool bar. */
825 if (WINDOWP (f->tool_bar_window)
826 && w == XWINDOW (f->tool_bar_window))
827 y -= width;
829 BLOCK_INPUT;
830 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
831 0, y, width, height, False);
832 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
833 f->output_data.x->pixel_width - width,
834 y, width, height, False);
835 UNBLOCK_INPUT;
840 /* Draw the bitmap WHICH in one of the left or right fringes of
841 window W. ROW is the glyph row for which to display the bitmap; it
842 determines the vertical position at which the bitmap has to be
843 drawn. */
845 static void
846 x_draw_fringe_bitmap (w, row, which, left_p)
847 struct window *w;
848 struct glyph_row *row;
849 enum fringe_bitmap_type which;
850 int left_p;
852 struct frame *f = XFRAME (WINDOW_FRAME (w));
853 Display *display = FRAME_X_DISPLAY (f);
854 Window window = FRAME_X_WINDOW (f);
855 int x, y, wd, h, dy;
856 int b1, b2;
857 unsigned char *bits;
858 Pixmap pixmap;
859 GC gc = f->output_data.x->normal_gc;
860 struct face *face;
861 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
863 /* Must clip because of partially visible lines. */
864 x_clip_to_row (w, row, gc, 1);
866 /* Convert row to frame coordinates. */
867 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
869 switch (which)
871 case NO_FRINGE_BITMAP:
872 wd = 0;
873 h = 0;
874 break;
876 case LEFT_TRUNCATION_BITMAP:
877 wd = left_width;
878 h = left_height;
879 bits = left_bits;
880 break;
882 case OVERLAY_ARROW_BITMAP:
883 wd = ov_width;
884 h = ov_height;
885 bits = ov_bits;
886 break;
888 case RIGHT_TRUNCATION_BITMAP:
889 wd = right_width;
890 h = right_height;
891 bits = right_bits;
892 break;
894 case CONTINUED_LINE_BITMAP:
895 wd = continued_width;
896 h = continued_height;
897 bits = continued_bits;
898 break;
900 case CONTINUATION_LINE_BITMAP:
901 wd = continuation_width;
902 h = continuation_height;
903 bits = continuation_bits;
904 break;
906 case ZV_LINE_BITMAP:
907 wd = zv_width;
908 h = zv_height - (y % zv_period);
909 bits = zv_bits + (y % zv_period);
910 break;
912 default:
913 abort ();
916 /* Clip bitmap if too high. */
917 if (h > row->height)
918 h = row->height;
920 /* Set dy to the offset in the row to start drawing the bitmap. */
921 dy = (row->height - h) / 2;
923 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
924 PREPARE_FACE_FOR_DISPLAY (f, face);
926 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
927 the fringe. */
928 b1 = b2 = -1;
929 if (left_p)
931 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
932 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
933 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
934 - wd
935 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
936 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
938 /* If W has a vertical border to its left, don't draw over it. */
939 int border = ((XFASTINT (w->left) > 0
940 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
941 ? 1 : 0);
942 b1 = (window_box_left (w, -1)
943 - FRAME_X_LEFT_FRINGE_WIDTH (f)
944 + border);
945 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
948 else
950 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
951 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
952 x = (window_box_right (w, -1)
953 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
954 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
955 the fringe. */
956 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
958 b1 = window_box_right (w, -1);
959 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
963 if (b1 >= 0)
965 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
967 /* In case the same realized face is used for fringes and
968 for something displayed in the text (e.g. face `region' on
969 mono-displays, the fill style may have been changed to
970 FillSolid in x_draw_glyph_string_background. */
971 if (face->stipple)
972 XSetFillStyle (display, face->gc, FillOpaqueStippled);
973 else
974 XSetForeground (display, face->gc, face->background);
976 XFillRectangle (display, window, face->gc,
978 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
979 row->y)),
981 row->visible_height);
982 if (!face->stipple)
983 XSetForeground (display, face->gc, face->foreground);
986 if (which != NO_FRINGE_BITMAP)
988 /* Draw the bitmap. I believe these small pixmaps can be cached
989 by the server. */
990 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
991 face->foreground,
992 face->background, depth);
993 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
994 XFreePixmap (display, pixmap);
997 XSetClipMask (display, gc, None);
1001 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1002 function with input blocked. */
1004 static void
1005 x_draw_row_fringe_bitmaps (w, row)
1006 struct window *w;
1007 struct glyph_row *row;
1009 struct frame *f = XFRAME (w->frame);
1010 enum fringe_bitmap_type bitmap;
1012 xassert (interrupt_input_blocked);
1014 /* If row is completely invisible, because of vscrolling, we
1015 don't have to draw anything. */
1016 if (row->visible_height <= 0)
1017 return;
1019 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1021 /* Decide which bitmap to draw in the left fringe. */
1022 if (row->overlay_arrow_p)
1023 bitmap = OVERLAY_ARROW_BITMAP;
1024 else if (row->truncated_on_left_p)
1025 bitmap = LEFT_TRUNCATION_BITMAP;
1026 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1027 bitmap = CONTINUATION_LINE_BITMAP;
1028 else if (row->indicate_empty_line_p)
1029 bitmap = ZV_LINE_BITMAP;
1030 else
1031 bitmap = NO_FRINGE_BITMAP;
1033 x_draw_fringe_bitmap (w, row, bitmap, 1);
1036 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1038 /* Decide which bitmap to draw in the right fringe. */
1039 if (row->truncated_on_right_p)
1040 bitmap = RIGHT_TRUNCATION_BITMAP;
1041 else if (row->continued_p)
1042 bitmap = CONTINUED_LINE_BITMAP;
1043 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1044 bitmap = ZV_LINE_BITMAP;
1045 else
1046 bitmap = NO_FRINGE_BITMAP;
1048 x_draw_fringe_bitmap (w, row, bitmap, 0);
1054 /* This is called when starting Emacs and when restarting after
1055 suspend. When starting Emacs, no X window is mapped. And nothing
1056 must be done to Emacs's own window if it is suspended (though that
1057 rarely happens). */
1059 static void
1060 XTset_terminal_modes ()
1064 /* This is called when exiting or suspending Emacs. Exiting will make
1065 the X-windows go away, and suspending requires no action. */
1067 static void
1068 XTreset_terminal_modes ()
1074 /***********************************************************************
1075 Output Cursor
1076 ***********************************************************************/
1078 /* Set the global variable output_cursor to CURSOR. All cursor
1079 positions are relative to updated_window. */
1081 static void
1082 set_output_cursor (cursor)
1083 struct cursor_pos *cursor;
1085 output_cursor.hpos = cursor->hpos;
1086 output_cursor.vpos = cursor->vpos;
1087 output_cursor.x = cursor->x;
1088 output_cursor.y = cursor->y;
1092 /* Set a nominal cursor position.
1094 HPOS and VPOS are column/row positions in a window glyph matrix. X
1095 and Y are window text area relative pixel positions.
1097 If this is done during an update, updated_window will contain the
1098 window that is being updated and the position is the future output
1099 cursor position for that window. If updated_window is null, use
1100 selected_window and display the cursor at the given position. */
1102 static void
1103 XTcursor_to (vpos, hpos, y, x)
1104 int vpos, hpos, y, x;
1106 struct window *w;
1108 /* If updated_window is not set, work on selected_window. */
1109 if (updated_window)
1110 w = updated_window;
1111 else
1112 w = XWINDOW (selected_window);
1114 /* Set the output cursor. */
1115 output_cursor.hpos = hpos;
1116 output_cursor.vpos = vpos;
1117 output_cursor.x = x;
1118 output_cursor.y = y;
1120 /* If not called as part of an update, really display the cursor.
1121 This will also set the cursor position of W. */
1122 if (updated_window == NULL)
1124 BLOCK_INPUT;
1125 x_display_cursor (w, 1, hpos, vpos, x, y);
1126 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1127 UNBLOCK_INPUT;
1133 /***********************************************************************
1134 Display Iterator
1135 ***********************************************************************/
1137 /* Function prototypes of this page. */
1139 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1140 struct glyph *,
1141 XChar2b *,
1142 int *));
1143 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1144 int, XChar2b *, int));
1145 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1146 static void x_encode_char P_ ((int, XChar2b *, struct font_info *,
1147 struct charset *));
1148 static void x_append_glyph P_ ((struct it *));
1149 static void x_append_composite_glyph P_ ((struct it *));
1150 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1151 int, int, double));
1152 static void x_produce_glyphs P_ ((struct it *));
1153 static void x_produce_image_glyph P_ ((struct it *it));
1156 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1157 is not contained in the font. */
1159 static INLINE XCharStruct *
1160 x_per_char_metric (font, char2b)
1161 XFontStruct *font;
1162 XChar2b *char2b;
1164 /* The result metric information. */
1165 XCharStruct *pcm = NULL;
1167 xassert (font && char2b);
1169 if (font->per_char != NULL)
1171 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1173 /* min_char_or_byte2 specifies the linear character index
1174 corresponding to the first element of the per_char array,
1175 max_char_or_byte2 is the index of the last character. A
1176 character with non-zero CHAR2B->byte1 is not in the font.
1177 A character with byte2 less than min_char_or_byte2 or
1178 greater max_char_or_byte2 is not in the font. */
1179 if (char2b->byte1 == 0
1180 && char2b->byte2 >= font->min_char_or_byte2
1181 && char2b->byte2 <= font->max_char_or_byte2)
1182 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1184 else
1186 /* If either min_byte1 or max_byte1 are nonzero, both
1187 min_char_or_byte2 and max_char_or_byte2 are less than
1188 256, and the 2-byte character index values corresponding
1189 to the per_char array element N (counting from 0) are:
1191 byte1 = N/D + min_byte1
1192 byte2 = N\D + min_char_or_byte2
1194 where:
1196 D = max_char_or_byte2 - min_char_or_byte2 + 1
1197 / = integer division
1198 \ = integer modulus */
1199 if (char2b->byte1 >= font->min_byte1
1200 && char2b->byte1 <= font->max_byte1
1201 && char2b->byte2 >= font->min_char_or_byte2
1202 && char2b->byte2 <= font->max_char_or_byte2)
1204 pcm = (font->per_char
1205 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1206 * (char2b->byte1 - font->min_byte1))
1207 + (char2b->byte2 - font->min_char_or_byte2));
1211 else
1213 /* If the per_char pointer is null, all glyphs between the first
1214 and last character indexes inclusive have the same
1215 information, as given by both min_bounds and max_bounds. */
1216 if (char2b->byte2 >= font->min_char_or_byte2
1217 && char2b->byte2 <= font->max_char_or_byte2)
1218 pcm = &font->max_bounds;
1221 return ((pcm == NULL
1222 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1223 ? NULL : pcm);
1227 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1228 the two-byte form of C. Encoding is returned in *CHAR2B. */
1230 static INLINE void
1231 x_encode_char (c, char2b, font_info, charset)
1232 int c;
1233 XChar2b *char2b;
1234 struct font_info *font_info;
1235 struct charset *charset;
1237 XFontStruct *font = font_info->font;
1239 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1240 This may be either a program in a special encoder language or a
1241 fixed encoding. */
1242 if (font_info->font_encoder)
1244 /* It's a program. */
1245 struct ccl_program *ccl = font_info->font_encoder;
1247 if (CHARSET_DIMENSION (charset) == 1)
1249 ccl->reg[0] = CHARSET_ID (charset);
1250 ccl->reg[1] = char2b->byte2;
1252 else
1254 ccl->reg[0] = CHARSET_ID (charset);
1255 ccl->reg[1] = char2b->byte1;
1256 ccl->reg[2] = char2b->byte2;
1259 ccl_driver (ccl, NULL, NULL, 0, 0);
1261 /* We assume that MSBs are appropriately set/reset by CCL
1262 program. */
1263 if (font->max_byte1 == 0) /* 1-byte font */
1264 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1265 else
1266 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1268 else if (font_info->encoding_type)
1270 /* Fixed encoding scheme. See fontset.h for the meaning of the
1271 encoding numbers. */
1272 unsigned char enc = font_info->encoding_type;
1274 if ((enc == 1 || enc == 2)
1275 && CHARSET_DIMENSION (charset) == 2)
1276 char2b->byte1 |= 0x80;
1278 if (enc == 1 || enc == 3)
1279 char2b->byte2 |= 0x80;
1284 /* Get face and two-byte form of character C in face FACE_ID on frame
1285 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1286 means we want to display multibyte text. Value is a pointer to a
1287 realized face that is ready for display. */
1289 static INLINE struct face *
1290 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1291 struct frame *f;
1292 int c, face_id;
1293 XChar2b *char2b;
1294 int multibyte_p;
1296 struct face *face = FACE_FROM_ID (f, face_id);
1298 if (!multibyte_p)
1300 /* Unibyte case. We don't have to encode, but we have to make
1301 sure to use a face suitable for unibyte. */
1302 char2b->byte1 = 0;
1303 char2b->byte2 = c;
1304 face_id = FACE_FOR_CHAR (f, face, c);
1305 face = FACE_FROM_ID (f, face_id);
1307 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1309 /* Case of ASCII in a face known to fit ASCII. */
1310 char2b->byte1 = 0;
1311 char2b->byte2 = c;
1313 else if (face->font != NULL)
1315 struct font_info *font_info
1316 = FONT_INFO_FROM_ID (f, face->font_info_id);
1317 struct charset *charset = CHARSET_FROM_ID (font_info->charset);
1318 unsigned code = ENCODE_CHAR (charset, c);
1320 if (CHARSET_DIMENSION (charset) == 1)
1321 char2b->byte1 = 0, char2b->byte2 = code;
1322 else
1323 char2b->byte1 = code >> 8, char2b->byte2 = code & 0xFF;
1325 /* Maybe encode the character in *CHAR2B. */
1326 x_encode_char (c, char2b, font_info, charset);
1329 /* Make sure X resources of the face are allocated. */
1330 xassert (face != NULL);
1331 PREPARE_FACE_FOR_DISPLAY (f, face);
1333 return face;
1337 /* Get face and two-byte form of character glyph GLYPH on frame F.
1338 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1339 a pointer to a realized face that is ready for display. */
1341 static INLINE struct face *
1342 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1343 struct frame *f;
1344 struct glyph *glyph;
1345 XChar2b *char2b;
1346 int *two_byte_p;
1348 struct face *face;
1350 xassert (glyph->type == CHAR_GLYPH);
1351 face = FACE_FROM_ID (f, glyph->face_id);
1353 if (two_byte_p)
1354 *two_byte_p = 0;
1356 if (!glyph->multibyte_p)
1358 /* Unibyte case. We don't have to encode, but we have to make
1359 sure to use a face suitable for unibyte. */
1360 char2b->byte1 = 0;
1361 char2b->byte2 = glyph->u.ch;
1363 else if (glyph->u.ch < 128
1364 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1366 /* Case of ASCII in a face known to fit ASCII. */
1367 char2b->byte1 = 0;
1368 char2b->byte2 = glyph->u.ch;
1370 else
1372 struct font_info *font_info
1373 = FONT_INFO_FROM_ID (f, face->font_info_id);
1374 if (font_info)
1376 struct charset *charset = CHARSET_FROM_ID (font_info->charset);
1377 unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
1379 if (CHARSET_DIMENSION (charset) == 1)
1380 char2b->byte1 = 0, char2b->byte2 = code;
1381 else
1382 char2b->byte1 = code >> 8, char2b->byte2 = code & 0xFF;
1384 /* Maybe encode the character in *CHAR2B. */
1385 if (CHARSET_ID (charset) != charset_ascii)
1387 x_encode_char (glyph->u.ch, char2b, font_info, charset);
1388 if (two_byte_p)
1389 *two_byte_p
1390 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1395 /* Make sure X resources of the face are allocated. */
1396 xassert (face != NULL);
1397 PREPARE_FACE_FOR_DISPLAY (f, face);
1398 return face;
1402 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1403 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1405 static INLINE void
1406 x_append_glyph (it)
1407 struct it *it;
1409 struct glyph *glyph;
1410 enum glyph_row_area area = it->area;
1412 xassert (it->glyph_row);
1413 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1415 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1416 if (glyph < it->glyph_row->glyphs[area + 1])
1418 glyph->charpos = CHARPOS (it->position);
1419 glyph->object = it->object;
1420 glyph->pixel_width = it->pixel_width;
1421 glyph->voffset = it->voffset;
1422 glyph->type = CHAR_GLYPH;
1423 glyph->multibyte_p = it->multibyte_p;
1424 glyph->left_box_line_p = it->start_of_box_run_p;
1425 glyph->right_box_line_p = it->end_of_box_run_p;
1426 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1427 || it->phys_descent > it->descent);
1428 glyph->padding_p = 0;
1429 glyph->glyph_not_available_p = it->glyph_not_available_p;
1430 glyph->face_id = it->face_id;
1431 glyph->u.ch = it->char_to_display;
1432 ++it->glyph_row->used[area];
1436 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1437 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1439 static INLINE void
1440 x_append_composite_glyph (it)
1441 struct it *it;
1443 struct glyph *glyph;
1444 enum glyph_row_area area = it->area;
1446 xassert (it->glyph_row);
1448 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1449 if (glyph < it->glyph_row->glyphs[area + 1])
1451 glyph->charpos = CHARPOS (it->position);
1452 glyph->object = it->object;
1453 glyph->pixel_width = it->pixel_width;
1454 glyph->voffset = it->voffset;
1455 glyph->type = COMPOSITE_GLYPH;
1456 glyph->multibyte_p = it->multibyte_p;
1457 glyph->left_box_line_p = it->start_of_box_run_p;
1458 glyph->right_box_line_p = it->end_of_box_run_p;
1459 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1460 || it->phys_descent > it->descent);
1461 glyph->padding_p = 0;
1462 glyph->glyph_not_available_p = 0;
1463 glyph->face_id = it->face_id;
1464 glyph->u.cmp_id = it->cmp_id;
1465 ++it->glyph_row->used[area];
1470 /* Change IT->ascent and IT->height according to the setting of
1471 IT->voffset. */
1473 static INLINE void
1474 take_vertical_position_into_account (it)
1475 struct it *it;
1477 if (it->voffset)
1479 if (it->voffset < 0)
1480 /* Increase the ascent so that we can display the text higher
1481 in the line. */
1482 it->ascent += abs (it->voffset);
1483 else
1484 /* Increase the descent so that we can display the text lower
1485 in the line. */
1486 it->descent += it->voffset;
1491 /* Produce glyphs/get display metrics for the image IT is loaded with.
1492 See the description of struct display_iterator in dispextern.h for
1493 an overview of struct display_iterator. */
1495 static void
1496 x_produce_image_glyph (it)
1497 struct it *it;
1499 struct image *img;
1500 struct face *face;
1502 xassert (it->what == IT_IMAGE);
1504 face = FACE_FROM_ID (it->f, it->face_id);
1505 img = IMAGE_FROM_ID (it->f, it->image_id);
1506 xassert (img);
1508 /* Make sure X resources of the face and image are loaded. */
1509 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1510 prepare_image_for_display (it->f, img);
1512 it->ascent = it->phys_ascent = image_ascent (img, face);
1513 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1514 it->pixel_width = img->width + 2 * img->hmargin;
1516 it->nglyphs = 1;
1518 if (face->box != FACE_NO_BOX)
1520 if (face->box_line_width > 0)
1522 it->ascent += face->box_line_width;
1523 it->descent += face->box_line_width;
1526 if (it->start_of_box_run_p)
1527 it->pixel_width += abs (face->box_line_width);
1528 if (it->end_of_box_run_p)
1529 it->pixel_width += abs (face->box_line_width);
1532 take_vertical_position_into_account (it);
1534 if (it->glyph_row)
1536 struct glyph *glyph;
1537 enum glyph_row_area area = it->area;
1539 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1540 if (glyph < it->glyph_row->glyphs[area + 1])
1542 glyph->charpos = CHARPOS (it->position);
1543 glyph->object = it->object;
1544 glyph->pixel_width = it->pixel_width;
1545 glyph->voffset = it->voffset;
1546 glyph->type = IMAGE_GLYPH;
1547 glyph->multibyte_p = it->multibyte_p;
1548 glyph->left_box_line_p = it->start_of_box_run_p;
1549 glyph->right_box_line_p = it->end_of_box_run_p;
1550 glyph->overlaps_vertically_p = 0;
1551 glyph->padding_p = 0;
1552 glyph->glyph_not_available_p = 0;
1553 glyph->face_id = it->face_id;
1554 glyph->u.img_id = img->id;
1555 ++it->glyph_row->used[area];
1561 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1562 of the glyph, WIDTH and HEIGHT are the width and height of the
1563 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1564 ascent of the glyph (0 <= ASCENT <= 1). */
1566 static void
1567 x_append_stretch_glyph (it, object, width, height, ascent)
1568 struct it *it;
1569 Lisp_Object object;
1570 int width, height;
1571 double ascent;
1573 struct glyph *glyph;
1574 enum glyph_row_area area = it->area;
1576 xassert (ascent >= 0 && ascent <= 1);
1578 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1579 if (glyph < it->glyph_row->glyphs[area + 1])
1581 glyph->charpos = CHARPOS (it->position);
1582 glyph->object = object;
1583 glyph->pixel_width = width;
1584 glyph->voffset = it->voffset;
1585 glyph->type = STRETCH_GLYPH;
1586 glyph->multibyte_p = it->multibyte_p;
1587 glyph->left_box_line_p = it->start_of_box_run_p;
1588 glyph->right_box_line_p = it->end_of_box_run_p;
1589 glyph->overlaps_vertically_p = 0;
1590 glyph->padding_p = 0;
1591 glyph->glyph_not_available_p = 0;
1592 glyph->face_id = it->face_id;
1593 glyph->u.stretch.ascent = height * ascent;
1594 glyph->u.stretch.height = height;
1595 ++it->glyph_row->used[area];
1600 /* Produce a stretch glyph for iterator IT. IT->object is the value
1601 of the glyph property displayed. The value must be a list
1602 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1603 being recognized:
1605 1. `:width WIDTH' specifies that the space should be WIDTH *
1606 canonical char width wide. WIDTH may be an integer or floating
1607 point number.
1609 2. `:relative-width FACTOR' specifies that the width of the stretch
1610 should be computed from the width of the first character having the
1611 `glyph' property, and should be FACTOR times that width.
1613 3. `:align-to HPOS' specifies that the space should be wide enough
1614 to reach HPOS, a value in canonical character units.
1616 Exactly one of the above pairs must be present.
1618 4. `:height HEIGHT' specifies that the height of the stretch produced
1619 should be HEIGHT, measured in canonical character units.
1621 5. `:relative-height FACTOR' specifies that the height of the
1622 stretch should be FACTOR times the height of the characters having
1623 the glyph property.
1625 Either none or exactly one of 4 or 5 must be present.
1627 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1628 of the stretch should be used for the ascent of the stretch.
1629 ASCENT must be in the range 0 <= ASCENT <= 100. */
1631 #define NUMVAL(X) \
1632 ((INTEGERP (X) || FLOATP (X)) \
1633 ? XFLOATINT (X) \
1634 : - 1)
1637 static void
1638 x_produce_stretch_glyph (it)
1639 struct it *it;
1641 /* (space :width WIDTH :height HEIGHT. */
1642 #if GLYPH_DEBUG
1643 extern Lisp_Object Qspace;
1644 #endif
1645 extern Lisp_Object QCwidth, QCheight, QCascent;
1646 extern Lisp_Object QCrelative_width, QCrelative_height;
1647 extern Lisp_Object QCalign_to;
1648 Lisp_Object prop, plist;
1649 double width = 0, height = 0, ascent = 0;
1650 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1651 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1653 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1655 /* List should start with `space'. */
1656 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1657 plist = XCDR (it->object);
1659 /* Compute the width of the stretch. */
1660 if (prop = Fplist_get (plist, QCwidth),
1661 NUMVAL (prop) > 0)
1662 /* Absolute width `:width WIDTH' specified and valid. */
1663 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1664 else if (prop = Fplist_get (plist, QCrelative_width),
1665 NUMVAL (prop) > 0)
1667 /* Relative width `:relative-width FACTOR' specified and valid.
1668 Compute the width of the characters having the `glyph'
1669 property. */
1670 struct it it2;
1671 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1673 it2 = *it;
1674 if (it->multibyte_p)
1676 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1677 - IT_BYTEPOS (*it));
1678 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1680 else
1681 it2.c = *p, it2.len = 1;
1683 it2.glyph_row = NULL;
1684 it2.what = IT_CHARACTER;
1685 x_produce_glyphs (&it2);
1686 width = NUMVAL (prop) * it2.pixel_width;
1688 else if (prop = Fplist_get (plist, QCalign_to),
1689 NUMVAL (prop) > 0)
1690 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1691 else
1692 /* Nothing specified -> width defaults to canonical char width. */
1693 width = CANON_X_UNIT (it->f);
1695 /* Compute height. */
1696 if (prop = Fplist_get (plist, QCheight),
1697 NUMVAL (prop) > 0)
1698 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1699 else if (prop = Fplist_get (plist, QCrelative_height),
1700 NUMVAL (prop) > 0)
1701 height = FONT_HEIGHT (font) * NUMVAL (prop);
1702 else
1703 height = FONT_HEIGHT (font);
1705 /* Compute percentage of height used for ascent. If
1706 `:ascent ASCENT' is present and valid, use that. Otherwise,
1707 derive the ascent from the font in use. */
1708 if (prop = Fplist_get (plist, QCascent),
1709 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1710 ascent = NUMVAL (prop) / 100.0;
1711 else
1712 ascent = (double) font->ascent / FONT_HEIGHT (font);
1714 if (width <= 0)
1715 width = 1;
1716 if (height <= 0)
1717 height = 1;
1719 if (it->glyph_row)
1721 Lisp_Object object = it->stack[it->sp - 1].string;
1722 if (!STRINGP (object))
1723 object = it->w->buffer;
1724 x_append_stretch_glyph (it, object, width, height, ascent);
1727 it->pixel_width = width;
1728 it->ascent = it->phys_ascent = height * ascent;
1729 it->descent = it->phys_descent = height - it->ascent;
1730 it->nglyphs = 1;
1732 if (face->box != FACE_NO_BOX)
1734 if (face->box_line_width > 0)
1736 it->ascent += face->box_line_width;
1737 it->descent += face->box_line_width;
1740 if (it->start_of_box_run_p)
1741 it->pixel_width += abs (face->box_line_width);
1742 if (it->end_of_box_run_p)
1743 it->pixel_width += abs (face->box_line_width);
1746 take_vertical_position_into_account (it);
1749 /* Return proper value to be used as baseline offset of font that has
1750 ASCENT and DESCENT to draw characters by the font at the vertical
1751 center of the line of frame F.
1753 Here, out task is to find the value of BOFF in the following figure;
1755 -------------------------+-----------+-
1756 -+-+---------+-+ | |
1757 | | | | | |
1758 | | | | F_ASCENT F_HEIGHT
1759 | | | ASCENT | |
1760 HEIGHT | | | | |
1761 | | |-|-+------+-----------|------- baseline
1762 | | | | BOFF | |
1763 | |---------|-+-+ | |
1764 | | | DESCENT | |
1765 -+-+---------+-+ F_DESCENT |
1766 -------------------------+-----------+-
1768 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1769 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1770 DESCENT = FONT->descent
1771 HEIGHT = FONT_HEIGHT (FONT)
1772 F_DESCENT = (F->output_data.x->font->descent
1773 - F->output_data.x->baseline_offset)
1774 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1777 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1778 ((FONT)->descent \
1779 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1780 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1781 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1783 /* Produce glyphs/get display metrics for the display element IT is
1784 loaded with. See the description of struct display_iterator in
1785 dispextern.h for an overview of struct display_iterator. */
1787 static void
1788 x_produce_glyphs (it)
1789 struct it *it;
1791 it->glyph_not_available_p = 0;
1793 if (it->what == IT_CHARACTER)
1795 XChar2b char2b;
1796 XFontStruct *font;
1797 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1798 XCharStruct *pcm;
1799 int font_not_found_p;
1800 struct font_info *font_info;
1801 int boff; /* baseline offset */
1802 /* We may change it->multibyte_p upon unibyte<->multibyte
1803 conversion. So, save the current value now and restore it
1804 later.
1806 Note: It seems that we don't have to record multibyte_p in
1807 struct glyph because the character code itself tells if or
1808 not the character is multibyte. Thus, in the future, we must
1809 consider eliminating the field `multibyte_p' in the struct
1810 glyph. */
1811 int saved_multibyte_p = it->multibyte_p;
1813 /* Maybe translate single-byte characters to multibyte, or the
1814 other way. */
1815 it->char_to_display = it->c;
1816 if (!ASCII_BYTE_P (it->c))
1818 if (unibyte_display_via_language_environment
1819 && SINGLE_BYTE_CHAR_P (it->c))
1821 it->char_to_display = unibyte_char_to_multibyte (it->c);
1822 it->multibyte_p = 1;
1823 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1824 face = FACE_FROM_ID (it->f, it->face_id);
1826 else if (!SINGLE_BYTE_CHAR_P (it->c)
1827 && !it->multibyte_p)
1829 it->multibyte_p = 1;
1830 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1831 face = FACE_FROM_ID (it->f, it->face_id);
1835 /* Get font to use. Encode IT->char_to_display. */
1836 x_get_char_face_and_encoding (it->f, it->char_to_display,
1837 it->face_id, &char2b,
1838 it->multibyte_p);
1839 font = face->font;
1841 /* When no suitable font found, use the default font. */
1842 font_not_found_p = font == NULL;
1843 if (font_not_found_p)
1845 font = FRAME_FONT (it->f);
1846 boff = it->f->output_data.x->baseline_offset;
1847 font_info = NULL;
1849 else
1851 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1852 boff = font_info->baseline_offset;
1853 if (font_info->vertical_centering)
1854 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1857 if (it->char_to_display >= ' '
1858 && (!it->multibyte_p || it->char_to_display < 128))
1860 /* Either unibyte or ASCII. */
1861 int stretched_p;
1863 it->nglyphs = 1;
1865 pcm = x_per_char_metric (font, &char2b);
1866 it->ascent = font->ascent + boff;
1867 it->descent = font->descent - boff;
1869 if (pcm)
1871 it->phys_ascent = pcm->ascent + boff;
1872 it->phys_descent = pcm->descent - boff;
1873 it->pixel_width = pcm->width;
1875 else
1877 it->glyph_not_available_p = 1;
1878 it->phys_ascent = font->ascent + boff;
1879 it->phys_descent = font->descent - boff;
1880 it->pixel_width = FONT_WIDTH (font);
1883 /* If this is a space inside a region of text with
1884 `space-width' property, change its width. */
1885 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1886 if (stretched_p)
1887 it->pixel_width *= XFLOATINT (it->space_width);
1889 /* If face has a box, add the box thickness to the character
1890 height. If character has a box line to the left and/or
1891 right, add the box line width to the character's width. */
1892 if (face->box != FACE_NO_BOX)
1894 int thick = face->box_line_width;
1896 if (thick > 0)
1898 it->ascent += thick;
1899 it->descent += thick;
1901 else
1902 thick = -thick;
1904 if (it->start_of_box_run_p)
1905 it->pixel_width += thick;
1906 if (it->end_of_box_run_p)
1907 it->pixel_width += thick;
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face->overline_p)
1913 it->ascent += 2;
1915 take_vertical_position_into_account (it);
1917 /* If we have to actually produce glyphs, do it. */
1918 if (it->glyph_row)
1920 if (stretched_p)
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1925 x_append_stretch_glyph (it, it->object, it->pixel_width,
1926 it->ascent + it->descent, ascent);
1928 else
1929 x_append_glyph (it);
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1934 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1935 it->glyph_row->contains_overlapping_glyphs_p = 1;
1938 else if (it->char_to_display == '\n')
1940 /* A newline has no width but we need the height of the line. */
1941 it->pixel_width = 0;
1942 it->nglyphs = 0;
1943 it->ascent = it->phys_ascent = font->ascent + boff;
1944 it->descent = it->phys_descent = font->descent - boff;
1946 if (face->box != FACE_NO_BOX
1947 && face->box_line_width > 0)
1949 it->ascent += face->box_line_width;
1950 it->descent += face->box_line_width;
1953 else if (it->char_to_display == '\t')
1955 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1956 int x = it->current_x + it->continuation_lines_width;
1957 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x - x < CANON_X_UNIT (it->f))
1963 next_tab_x += tab_width;
1965 it->pixel_width = next_tab_x - x;
1966 it->nglyphs = 1;
1967 it->ascent = it->phys_ascent = font->ascent + boff;
1968 it->descent = it->phys_descent = font->descent - boff;
1970 if (it->glyph_row)
1972 double ascent = (double) it->ascent / (it->ascent + it->descent);
1973 x_append_stretch_glyph (it, it->object, it->pixel_width,
1974 it->ascent + it->descent, ascent);
1977 else
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
1981 width of the font. */
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character by
1986 multiplying the width of font by the width of the
1987 character. */
1988 pcm = x_per_char_metric (font, &char2b);
1989 if (font_not_found_p || !pcm)
1991 it->glyph_not_available_p = 1;
1992 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1993 * CHAR_WIDTH (it->char_to_display));
1994 it->phys_ascent = font->ascent + boff;
1995 it->phys_descent = font->descent - boff;
1997 else
1999 it->pixel_width = pcm->width;
2000 it->phys_ascent = pcm->ascent + boff;
2001 it->phys_descent = pcm->descent - boff;
2002 if (it->glyph_row
2003 && (pcm->lbearing < 0
2004 || pcm->rbearing > pcm->width))
2005 it->glyph_row->contains_overlapping_glyphs_p = 1;
2007 it->nglyphs = 1;
2008 it->ascent = font->ascent + boff;
2009 it->descent = font->descent - boff;
2010 if (face->box != FACE_NO_BOX)
2012 int thick = face->box_line_width;
2014 if (thick > 0)
2016 it->ascent += thick;
2017 it->descent += thick;
2019 else
2020 thick = - thick;
2022 if (it->start_of_box_run_p)
2023 it->pixel_width += thick;
2024 if (it->end_of_box_run_p)
2025 it->pixel_width += thick;
2028 /* If face has an overline, add the height of the overline
2029 (1 pixel) and a 1 pixel margin to the character height. */
2030 if (face->overline_p)
2031 it->ascent += 2;
2033 take_vertical_position_into_account (it);
2035 if (it->glyph_row)
2036 x_append_glyph (it);
2038 it->multibyte_p = saved_multibyte_p;
2040 else if (it->what == IT_COMPOSITION)
2042 /* Note: A composition is represented as one glyph in the
2043 glyph matrix. There are no padding glyphs. */
2044 XChar2b char2b;
2045 XFontStruct *font;
2046 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2047 XCharStruct *pcm;
2048 int font_not_found_p;
2049 struct font_info *font_info;
2050 int boff; /* baseline offset */
2051 struct composition *cmp = composition_table[it->cmp_id];
2053 /* Maybe translate single-byte characters to multibyte. */
2054 it->char_to_display = it->c;
2055 if (unibyte_display_via_language_environment
2056 && it->c >= 0200)
2058 it->char_to_display = unibyte_char_to_multibyte (it->c);
2061 /* Get face and font to use. Encode IT->char_to_display. */
2062 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2063 face = FACE_FROM_ID (it->f, it->face_id);
2064 x_get_char_face_and_encoding (it->f, it->char_to_display,
2065 it->face_id, &char2b, it->multibyte_p);
2066 font = face->font;
2068 /* When no suitable font found, use the default font. */
2069 font_not_found_p = font == NULL;
2070 if (font_not_found_p)
2072 font = FRAME_FONT (it->f);
2073 boff = it->f->output_data.x->baseline_offset;
2074 font_info = NULL;
2076 else
2078 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2079 boff = font_info->baseline_offset;
2080 if (font_info->vertical_centering)
2081 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2084 /* There are no padding glyphs, so there is only one glyph to
2085 produce for the composition. Important is that pixel_width,
2086 ascent and descent are the values of what is drawn by
2087 draw_glyphs (i.e. the values of the overall glyphs composed). */
2088 it->nglyphs = 1;
2090 /* If we have not yet calculated pixel size data of glyphs of
2091 the composition for the current face font, calculate them
2092 now. Theoretically, we have to check all fonts for the
2093 glyphs, but that requires much time and memory space. So,
2094 here we check only the font of the first glyph. This leads
2095 to incorrect display very rarely, and C-l (recenter) can
2096 correct the display anyway. */
2097 if (cmp->font != (void *) font)
2099 /* Ascent and descent of the font of the first character of
2100 this composition (adjusted by baseline offset). Ascent
2101 and descent of overall glyphs should not be less than
2102 them respectively. */
2103 int font_ascent = font->ascent + boff;
2104 int font_descent = font->descent - boff;
2105 /* Bounding box of the overall glyphs. */
2106 int leftmost, rightmost, lowest, highest;
2107 int i, width, ascent, descent;
2109 cmp->font = (void *) font;
2111 /* Initialize the bounding box. */
2112 if (font_info
2113 && (pcm = x_per_char_metric (font, &char2b)))
2115 width = pcm->width;
2116 ascent = pcm->ascent;
2117 descent = pcm->descent;
2119 else
2121 width = FONT_WIDTH (font);
2122 ascent = font->ascent;
2123 descent = font->descent;
2126 rightmost = width;
2127 lowest = - descent + boff;
2128 highest = ascent + boff;
2129 leftmost = 0;
2131 if (font_info
2132 && font_info->default_ascent
2133 && CHAR_TABLE_P (Vuse_default_ascent)
2134 && !NILP (Faref (Vuse_default_ascent,
2135 make_number (it->char_to_display))))
2136 highest = font_info->default_ascent + boff;
2138 /* Draw the first glyph at the normal position. It may be
2139 shifted to right later if some other glyphs are drawn at
2140 the left. */
2141 cmp->offsets[0] = 0;
2142 cmp->offsets[1] = boff;
2144 /* Set cmp->offsets for the remaining glyphs. */
2145 for (i = 1; i < cmp->glyph_len; i++)
2147 int left, right, btm, top;
2148 int ch = COMPOSITION_GLYPH (cmp, i);
2149 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2151 face = FACE_FROM_ID (it->f, face_id);
2152 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2153 it->multibyte_p);
2154 font = face->font;
2155 if (font == NULL)
2157 font = FRAME_FONT (it->f);
2158 boff = it->f->output_data.x->baseline_offset;
2159 font_info = NULL;
2161 else
2163 font_info
2164 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2165 boff = font_info->baseline_offset;
2166 if (font_info->vertical_centering)
2167 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2170 if (font_info
2171 && (pcm = x_per_char_metric (font, &char2b)))
2173 width = pcm->width;
2174 ascent = pcm->ascent;
2175 descent = pcm->descent;
2177 else
2179 width = FONT_WIDTH (font);
2180 ascent = 1;
2181 descent = 0;
2184 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2186 /* Relative composition with or without
2187 alternate chars. */
2188 left = (leftmost + rightmost - width) / 2;
2189 btm = - descent + boff;
2190 if (font_info && font_info->relative_compose
2191 && (! CHAR_TABLE_P (Vignore_relative_composition)
2192 || NILP (Faref (Vignore_relative_composition,
2193 make_number (ch)))))
2196 if (- descent >= font_info->relative_compose)
2197 /* One extra pixel between two glyphs. */
2198 btm = highest + 1;
2199 else if (ascent <= 0)
2200 /* One extra pixel between two glyphs. */
2201 btm = lowest - 1 - ascent - descent;
2204 else
2206 /* A composition rule is specified by an integer
2207 value that encodes global and new reference
2208 points (GREF and NREF). GREF and NREF are
2209 specified by numbers as below:
2211 0---1---2 -- ascent
2215 9--10--11 -- center
2217 ---3---4---5--- baseline
2219 6---7---8 -- descent
2221 int rule = COMPOSITION_RULE (cmp, i);
2222 int gref, nref, grefx, grefy, nrefx, nrefy;
2224 COMPOSITION_DECODE_RULE (rule, gref, nref);
2225 grefx = gref % 3, nrefx = nref % 3;
2226 grefy = gref / 3, nrefy = nref / 3;
2228 left = (leftmost
2229 + grefx * (rightmost - leftmost) / 2
2230 - nrefx * width / 2);
2231 btm = ((grefy == 0 ? highest
2232 : grefy == 1 ? 0
2233 : grefy == 2 ? lowest
2234 : (highest + lowest) / 2)
2235 - (nrefy == 0 ? ascent + descent
2236 : nrefy == 1 ? descent - boff
2237 : nrefy == 2 ? 0
2238 : (ascent + descent) / 2));
2241 cmp->offsets[i * 2] = left;
2242 cmp->offsets[i * 2 + 1] = btm + descent;
2244 /* Update the bounding box of the overall glyphs. */
2245 right = left + width;
2246 top = btm + descent + ascent;
2247 if (left < leftmost)
2248 leftmost = left;
2249 if (right > rightmost)
2250 rightmost = right;
2251 if (top > highest)
2252 highest = top;
2253 if (btm < lowest)
2254 lowest = btm;
2257 /* If there are glyphs whose x-offsets are negative,
2258 shift all glyphs to the right and make all x-offsets
2259 non-negative. */
2260 if (leftmost < 0)
2262 for (i = 0; i < cmp->glyph_len; i++)
2263 cmp->offsets[i * 2] -= leftmost;
2264 rightmost -= leftmost;
2267 cmp->pixel_width = rightmost;
2268 cmp->ascent = highest;
2269 cmp->descent = - lowest;
2270 if (cmp->ascent < font_ascent)
2271 cmp->ascent = font_ascent;
2272 if (cmp->descent < font_descent)
2273 cmp->descent = font_descent;
2276 it->pixel_width = cmp->pixel_width;
2277 it->ascent = it->phys_ascent = cmp->ascent;
2278 it->descent = it->phys_descent = cmp->descent;
2280 if (face->box != FACE_NO_BOX)
2282 int thick = face->box_line_width;
2284 if (thick > 0)
2286 it->ascent += thick;
2287 it->descent += thick;
2289 else
2290 thick = - thick;
2292 if (it->start_of_box_run_p)
2293 it->pixel_width += thick;
2294 if (it->end_of_box_run_p)
2295 it->pixel_width += thick;
2298 /* If face has an overline, add the height of the overline
2299 (1 pixel) and a 1 pixel margin to the character height. */
2300 if (face->overline_p)
2301 it->ascent += 2;
2303 take_vertical_position_into_account (it);
2305 if (it->glyph_row)
2306 x_append_composite_glyph (it);
2308 else if (it->what == IT_IMAGE)
2309 x_produce_image_glyph (it);
2310 else if (it->what == IT_STRETCH)
2311 x_produce_stretch_glyph (it);
2313 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2314 because this isn't true for images with `:ascent 100'. */
2315 xassert (it->ascent >= 0 && it->descent >= 0);
2316 if (it->area == TEXT_AREA)
2317 it->current_x += it->pixel_width;
2319 it->descent += it->extra_line_spacing;
2321 it->max_ascent = max (it->max_ascent, it->ascent);
2322 it->max_descent = max (it->max_descent, it->descent);
2323 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2324 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2328 /* Estimate the pixel height of the mode or top line on frame F.
2329 FACE_ID specifies what line's height to estimate. */
2332 x_estimate_mode_line_height (f, face_id)
2333 struct frame *f;
2334 enum face_id face_id;
2336 int height = FONT_HEIGHT (FRAME_FONT (f));
2338 /* This function is called so early when Emacs starts that the face
2339 cache and mode line face are not yet initialized. */
2340 if (FRAME_FACE_CACHE (f))
2342 struct face *face = FACE_FROM_ID (f, face_id);
2343 if (face)
2345 if (face->font)
2346 height = FONT_HEIGHT (face->font);
2347 if (face->box_line_width > 0)
2348 height += 2 * face->box_line_width;
2352 return height;
2356 /***********************************************************************
2357 Glyph display
2358 ***********************************************************************/
2360 /* A sequence of glyphs to be drawn in the same face.
2362 This data structure is not really completely X specific, so it
2363 could possibly, at least partially, be useful for other systems. It
2364 is currently not part of the external redisplay interface because
2365 it's not clear what other systems will need. */
2367 struct glyph_string
2369 /* X-origin of the string. */
2370 int x;
2372 /* Y-origin and y-position of the base line of this string. */
2373 int y, ybase;
2375 /* The width of the string, not including a face extension. */
2376 int width;
2378 /* The width of the string, including a face extension. */
2379 int background_width;
2381 /* The height of this string. This is the height of the line this
2382 string is drawn in, and can be different from the height of the
2383 font the string is drawn in. */
2384 int height;
2386 /* Number of pixels this string overwrites in front of its x-origin.
2387 This number is zero if the string has an lbearing >= 0; it is
2388 -lbearing, if the string has an lbearing < 0. */
2389 int left_overhang;
2391 /* Number of pixels this string overwrites past its right-most
2392 nominal x-position, i.e. x + width. Zero if the string's
2393 rbearing is <= its nominal width, rbearing - width otherwise. */
2394 int right_overhang;
2396 /* The frame on which the glyph string is drawn. */
2397 struct frame *f;
2399 /* The window on which the glyph string is drawn. */
2400 struct window *w;
2402 /* X display and window for convenience. */
2403 Display *display;
2404 Window window;
2406 /* The glyph row for which this string was built. It determines the
2407 y-origin and height of the string. */
2408 struct glyph_row *row;
2410 /* The area within row. */
2411 enum glyph_row_area area;
2413 /* Characters to be drawn, and number of characters. */
2414 XChar2b *char2b;
2415 int nchars;
2417 /* A face-override for drawing cursors, mouse face and similar. */
2418 enum draw_glyphs_face hl;
2420 /* Face in which this string is to be drawn. */
2421 struct face *face;
2423 /* Font in which this string is to be drawn. */
2424 XFontStruct *font;
2426 /* Font info for this string. */
2427 struct font_info *font_info;
2429 /* Non-null means this string describes (part of) a composition.
2430 All characters from char2b are drawn composed. */
2431 struct composition *cmp;
2433 /* Index of this glyph string's first character in the glyph
2434 definition of CMP. If this is zero, this glyph string describes
2435 the first character of a composition. */
2436 int gidx;
2438 /* 1 means this glyph strings face has to be drawn to the right end
2439 of the window's drawing area. */
2440 unsigned extends_to_end_of_line_p : 1;
2442 /* 1 means the background of this string has been drawn. */
2443 unsigned background_filled_p : 1;
2445 /* 1 means glyph string must be drawn with 16-bit functions. */
2446 unsigned two_byte_p : 1;
2448 /* 1 means that the original font determined for drawing this glyph
2449 string could not be loaded. The member `font' has been set to
2450 the frame's default font in this case. */
2451 unsigned font_not_found_p : 1;
2453 /* 1 means that the face in which this glyph string is drawn has a
2454 stipple pattern. */
2455 unsigned stippled_p : 1;
2457 /* 1 means only the foreground of this glyph string must be drawn,
2458 and we should use the physical height of the line this glyph
2459 string appears in as clip rect. */
2460 unsigned for_overlaps_p : 1;
2462 /* The GC to use for drawing this glyph string. */
2463 GC gc;
2465 /* A pointer to the first glyph in the string. This glyph
2466 corresponds to char2b[0]. Needed to draw rectangles if
2467 font_not_found_p is 1. */
2468 struct glyph *first_glyph;
2470 /* Image, if any. */
2471 struct image *img;
2473 struct glyph_string *next, *prev;
2477 #if GLYPH_DEBUG
2479 static void
2480 x_dump_glyph_string (s)
2481 struct glyph_string *s;
2483 fprintf (stderr, "glyph string\n");
2484 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2485 s->x, s->y, s->width, s->height);
2486 fprintf (stderr, " ybase = %d\n", s->ybase);
2487 fprintf (stderr, " hl = %d\n", s->hl);
2488 fprintf (stderr, " left overhang = %d, right = %d\n",
2489 s->left_overhang, s->right_overhang);
2490 fprintf (stderr, " nchars = %d\n", s->nchars);
2491 fprintf (stderr, " extends to end of line = %d\n",
2492 s->extends_to_end_of_line_p);
2493 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2494 fprintf (stderr, " bg width = %d\n", s->background_width);
2497 #endif /* GLYPH_DEBUG */
2501 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2502 struct glyph_string **,
2503 struct glyph_string *,
2504 struct glyph_string *));
2505 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2506 struct glyph_string **,
2507 struct glyph_string *,
2508 struct glyph_string *));
2509 static void x_append_glyph_string P_ ((struct glyph_string **,
2510 struct glyph_string **,
2511 struct glyph_string *));
2512 static int x_left_overwritten P_ ((struct glyph_string *));
2513 static int x_left_overwriting P_ ((struct glyph_string *));
2514 static int x_right_overwritten P_ ((struct glyph_string *));
2515 static int x_right_overwriting P_ ((struct glyph_string *));
2516 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2517 int));
2518 static void x_init_glyph_string P_ ((struct glyph_string *,
2519 XChar2b *, struct window *,
2520 struct glyph_row *,
2521 enum glyph_row_area, int,
2522 enum draw_glyphs_face));
2523 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2524 enum glyph_row_area, int, int,
2525 enum draw_glyphs_face, int));
2526 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2527 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2528 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2529 int));
2530 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2531 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2532 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2533 static void x_draw_glyph_string P_ ((struct glyph_string *));
2534 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2535 static void x_set_cursor_gc P_ ((struct glyph_string *));
2536 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2537 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2538 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2539 int *, int *));
2540 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2541 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2542 unsigned long *, double, int));
2543 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2544 double, int, unsigned long));
2545 static void x_setup_relief_colors P_ ((struct glyph_string *));
2546 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2547 static void x_draw_image_relief P_ ((struct glyph_string *));
2548 static void x_draw_image_foreground P_ ((struct glyph_string *));
2549 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2550 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2551 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2552 int, int, int));
2553 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2554 int, int, int, int, XRectangle *));
2555 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2556 int, int, int, XRectangle *));
2557 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2558 enum glyph_row_area));
2559 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2560 struct glyph_row *,
2561 enum glyph_row_area, int, int));
2563 #if GLYPH_DEBUG
2564 static void x_check_font P_ ((struct frame *, XFontStruct *));
2565 #endif
2568 /* Append the list of glyph strings with head H and tail T to the list
2569 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2571 static INLINE void
2572 x_append_glyph_string_lists (head, tail, h, t)
2573 struct glyph_string **head, **tail;
2574 struct glyph_string *h, *t;
2576 if (h)
2578 if (*head)
2579 (*tail)->next = h;
2580 else
2581 *head = h;
2582 h->prev = *tail;
2583 *tail = t;
2588 /* Prepend the list of glyph strings with head H and tail T to the
2589 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2590 result. */
2592 static INLINE void
2593 x_prepend_glyph_string_lists (head, tail, h, t)
2594 struct glyph_string **head, **tail;
2595 struct glyph_string *h, *t;
2597 if (h)
2599 if (*head)
2600 (*head)->prev = t;
2601 else
2602 *tail = t;
2603 t->next = *head;
2604 *head = h;
2609 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2610 Set *HEAD and *TAIL to the resulting list. */
2612 static INLINE void
2613 x_append_glyph_string (head, tail, s)
2614 struct glyph_string **head, **tail;
2615 struct glyph_string *s;
2617 s->next = s->prev = NULL;
2618 x_append_glyph_string_lists (head, tail, s, s);
2622 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2623 face. */
2625 static void
2626 x_set_cursor_gc (s)
2627 struct glyph_string *s;
2629 if (s->font == FRAME_FONT (s->f)
2630 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2631 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2632 && !s->cmp)
2633 s->gc = s->f->output_data.x->cursor_gc;
2634 else
2636 /* Cursor on non-default face: must merge. */
2637 XGCValues xgcv;
2638 unsigned long mask;
2640 xgcv.background = s->f->output_data.x->cursor_pixel;
2641 xgcv.foreground = s->face->background;
2643 /* If the glyph would be invisible, try a different foreground. */
2644 if (xgcv.foreground == xgcv.background)
2645 xgcv.foreground = s->face->foreground;
2646 if (xgcv.foreground == xgcv.background)
2647 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2648 if (xgcv.foreground == xgcv.background)
2649 xgcv.foreground = s->face->foreground;
2651 /* Make sure the cursor is distinct from text in this face. */
2652 if (xgcv.background == s->face->background
2653 && xgcv.foreground == s->face->foreground)
2655 xgcv.background = s->face->foreground;
2656 xgcv.foreground = s->face->background;
2659 IF_DEBUG (x_check_font (s->f, s->font));
2660 xgcv.font = s->font->fid;
2661 xgcv.graphics_exposures = False;
2662 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2664 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2665 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2666 mask, &xgcv);
2667 else
2668 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2669 = XCreateGC (s->display, s->window, mask, &xgcv);
2671 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2676 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2678 static void
2679 x_set_mouse_face_gc (s)
2680 struct glyph_string *s;
2682 int face_id;
2683 struct face *face;
2685 /* What face has to be used last for the mouse face? */
2686 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2687 face = FACE_FROM_ID (s->f, face_id);
2688 if (face == NULL)
2689 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2691 if (s->first_glyph->type == CHAR_GLYPH)
2692 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2693 else
2694 face_id = FACE_FOR_CHAR (s->f, face, 0);
2695 s->face = FACE_FROM_ID (s->f, face_id);
2696 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2698 /* If font in this face is same as S->font, use it. */
2699 if (s->font == s->face->font)
2700 s->gc = s->face->gc;
2701 else
2703 /* Otherwise construct scratch_cursor_gc with values from FACE
2704 but font FONT. */
2705 XGCValues xgcv;
2706 unsigned long mask;
2708 xgcv.background = s->face->background;
2709 xgcv.foreground = s->face->foreground;
2710 IF_DEBUG (x_check_font (s->f, s->font));
2711 xgcv.font = s->font->fid;
2712 xgcv.graphics_exposures = False;
2713 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2715 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2716 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2717 mask, &xgcv);
2718 else
2719 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2720 = XCreateGC (s->display, s->window, mask, &xgcv);
2722 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2725 xassert (s->gc != 0);
2729 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2730 Faces to use in the mode line have already been computed when the
2731 matrix was built, so there isn't much to do, here. */
2733 static INLINE void
2734 x_set_mode_line_face_gc (s)
2735 struct glyph_string *s;
2737 s->gc = s->face->gc;
2741 /* Set S->gc of glyph string S for drawing that glyph string. Set
2742 S->stippled_p to a non-zero value if the face of S has a stipple
2743 pattern. */
2745 static INLINE void
2746 x_set_glyph_string_gc (s)
2747 struct glyph_string *s;
2749 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2751 if (s->hl == DRAW_NORMAL_TEXT)
2753 s->gc = s->face->gc;
2754 s->stippled_p = s->face->stipple != 0;
2756 else if (s->hl == DRAW_INVERSE_VIDEO)
2758 x_set_mode_line_face_gc (s);
2759 s->stippled_p = s->face->stipple != 0;
2761 else if (s->hl == DRAW_CURSOR)
2763 x_set_cursor_gc (s);
2764 s->stippled_p = 0;
2766 else if (s->hl == DRAW_MOUSE_FACE)
2768 x_set_mouse_face_gc (s);
2769 s->stippled_p = s->face->stipple != 0;
2771 else if (s->hl == DRAW_IMAGE_RAISED
2772 || s->hl == DRAW_IMAGE_SUNKEN)
2774 s->gc = s->face->gc;
2775 s->stippled_p = s->face->stipple != 0;
2777 else
2779 s->gc = s->face->gc;
2780 s->stippled_p = s->face->stipple != 0;
2783 /* GC must have been set. */
2784 xassert (s->gc != 0);
2788 /* Return in *R the clipping rectangle for glyph string S. */
2790 static void
2791 x_get_glyph_string_clip_rect (s, r)
2792 struct glyph_string *s;
2793 XRectangle *r;
2795 if (s->row->full_width_p)
2797 /* Draw full-width. X coordinates are relative to S->w->left. */
2798 int canon_x = CANON_X_UNIT (s->f);
2800 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2801 r->width = XFASTINT (s->w->width) * canon_x;
2803 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2805 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2806 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2807 r->x -= width;
2810 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2812 /* Unless displaying a mode or menu bar line, which are always
2813 fully visible, clip to the visible part of the row. */
2814 if (s->w->pseudo_window_p)
2815 r->height = s->row->visible_height;
2816 else
2817 r->height = s->height;
2819 else
2821 /* This is a text line that may be partially visible. */
2822 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2823 r->width = window_box_width (s->w, s->area);
2824 r->height = s->row->visible_height;
2827 /* If S draws overlapping rows, it's sufficient to use the top and
2828 bottom of the window for clipping because this glyph string
2829 intentionally draws over other lines. */
2830 if (s->for_overlaps_p)
2832 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2833 r->height = window_text_bottom_y (s->w) - r->y;
2835 else
2837 /* Don't use S->y for clipping because it doesn't take partially
2838 visible lines into account. For example, it can be negative for
2839 partially visible lines at the top of a window. */
2840 if (!s->row->full_width_p
2841 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2842 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2843 else
2844 r->y = max (0, s->row->y);
2846 /* If drawing a tool-bar window, draw it over the internal border
2847 at the top of the window. */
2848 if (s->w == XWINDOW (s->f->tool_bar_window))
2849 r->y -= s->f->output_data.x->internal_border_width;
2852 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2856 /* Set clipping for output of glyph string S. S may be part of a mode
2857 line or menu if we don't have X toolkit support. */
2859 static INLINE void
2860 x_set_glyph_string_clipping (s)
2861 struct glyph_string *s;
2863 XRectangle r;
2864 x_get_glyph_string_clip_rect (s, &r);
2865 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2869 /* Compute left and right overhang of glyph string S. If S is a glyph
2870 string for a composition, assume overhangs don't exist. */
2872 static INLINE void
2873 x_compute_glyph_string_overhangs (s)
2874 struct glyph_string *s;
2876 if (s->cmp == NULL
2877 && s->first_glyph->type == CHAR_GLYPH)
2879 XCharStruct cs;
2880 int direction, font_ascent, font_descent;
2881 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2882 &font_ascent, &font_descent, &cs);
2883 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2884 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2889 /* Compute overhangs and x-positions for glyph string S and its
2890 predecessors, or successors. X is the starting x-position for S.
2891 BACKWARD_P non-zero means process predecessors. */
2893 static void
2894 x_compute_overhangs_and_x (s, x, backward_p)
2895 struct glyph_string *s;
2896 int x;
2897 int backward_p;
2899 if (backward_p)
2901 while (s)
2903 x_compute_glyph_string_overhangs (s);
2904 x -= s->width;
2905 s->x = x;
2906 s = s->prev;
2909 else
2911 while (s)
2913 x_compute_glyph_string_overhangs (s);
2914 s->x = x;
2915 x += s->width;
2916 s = s->next;
2922 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2923 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2924 assumed to be zero. */
2926 static void
2927 x_get_glyph_overhangs (glyph, f, left, right)
2928 struct glyph *glyph;
2929 struct frame *f;
2930 int *left, *right;
2932 *left = *right = 0;
2934 if (glyph->type == CHAR_GLYPH)
2936 XFontStruct *font;
2937 struct face *face;
2938 struct font_info *font_info;
2939 XChar2b char2b;
2940 XCharStruct *pcm;
2942 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2943 font = face->font;
2944 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2945 if (font
2946 && (pcm = x_per_char_metric (font, &char2b)))
2948 if (pcm->rbearing > pcm->width)
2949 *right = pcm->rbearing - pcm->width;
2950 if (pcm->lbearing < 0)
2951 *left = -pcm->lbearing;
2957 /* Return the index of the first glyph preceding glyph string S that
2958 is overwritten by S because of S's left overhang. Value is -1
2959 if no glyphs are overwritten. */
2961 static int
2962 x_left_overwritten (s)
2963 struct glyph_string *s;
2965 int k;
2967 if (s->left_overhang)
2969 int x = 0, i;
2970 struct glyph *glyphs = s->row->glyphs[s->area];
2971 int first = s->first_glyph - glyphs;
2973 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2974 x -= glyphs[i].pixel_width;
2976 k = i + 1;
2978 else
2979 k = -1;
2981 return k;
2985 /* Return the index of the first glyph preceding glyph string S that
2986 is overwriting S because of its right overhang. Value is -1 if no
2987 glyph in front of S overwrites S. */
2989 static int
2990 x_left_overwriting (s)
2991 struct glyph_string *s;
2993 int i, k, x;
2994 struct glyph *glyphs = s->row->glyphs[s->area];
2995 int first = s->first_glyph - glyphs;
2997 k = -1;
2998 x = 0;
2999 for (i = first - 1; i >= 0; --i)
3001 int left, right;
3002 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3003 if (x + right > 0)
3004 k = i;
3005 x -= glyphs[i].pixel_width;
3008 return k;
3012 /* Return the index of the last glyph following glyph string S that is
3013 not overwritten by S because of S's right overhang. Value is -1 if
3014 no such glyph is found. */
3016 static int
3017 x_right_overwritten (s)
3018 struct glyph_string *s;
3020 int k = -1;
3022 if (s->right_overhang)
3024 int x = 0, i;
3025 struct glyph *glyphs = s->row->glyphs[s->area];
3026 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3027 int end = s->row->used[s->area];
3029 for (i = first; i < end && s->right_overhang > x; ++i)
3030 x += glyphs[i].pixel_width;
3032 k = i;
3035 return k;
3039 /* Return the index of the last glyph following glyph string S that
3040 overwrites S because of its left overhang. Value is negative
3041 if no such glyph is found. */
3043 static int
3044 x_right_overwriting (s)
3045 struct glyph_string *s;
3047 int i, k, x;
3048 int end = s->row->used[s->area];
3049 struct glyph *glyphs = s->row->glyphs[s->area];
3050 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3052 k = -1;
3053 x = 0;
3054 for (i = first; i < end; ++i)
3056 int left, right;
3057 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3058 if (x - left < 0)
3059 k = i;
3060 x += glyphs[i].pixel_width;
3063 return k;
3067 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3069 static INLINE void
3070 x_clear_glyph_string_rect (s, x, y, w, h)
3071 struct glyph_string *s;
3072 int x, y, w, h;
3074 XGCValues xgcv;
3075 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3076 XSetForeground (s->display, s->gc, xgcv.background);
3077 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3078 XSetForeground (s->display, s->gc, xgcv.foreground);
3082 /* Draw the background of glyph_string S. If S->background_filled_p
3083 is non-zero don't draw it. FORCE_P non-zero means draw the
3084 background even if it wouldn't be drawn normally. This is used
3085 when a string preceding S draws into the background of S, or S
3086 contains the first component of a composition. */
3088 static void
3089 x_draw_glyph_string_background (s, force_p)
3090 struct glyph_string *s;
3091 int force_p;
3093 /* Nothing to do if background has already been drawn or if it
3094 shouldn't be drawn in the first place. */
3095 if (!s->background_filled_p)
3097 int box_line_width = max (s->face->box_line_width, 0);
3099 if (s->stippled_p)
3101 /* Fill background with a stipple pattern. */
3102 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3103 XFillRectangle (s->display, s->window, s->gc, s->x,
3104 s->y + box_line_width,
3105 s->background_width,
3106 s->height - 2 * box_line_width);
3107 XSetFillStyle (s->display, s->gc, FillSolid);
3108 s->background_filled_p = 1;
3110 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3111 || s->font_not_found_p
3112 || s->extends_to_end_of_line_p
3113 || force_p)
3115 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3116 s->background_width,
3117 s->height - 2 * box_line_width);
3118 s->background_filled_p = 1;
3124 /* Draw the foreground of glyph string S. */
3126 static void
3127 x_draw_glyph_string_foreground (s)
3128 struct glyph_string *s;
3130 int i, x;
3132 /* If first glyph of S has a left box line, start drawing the text
3133 of S to the right of that box line. */
3134 if (s->face->box != FACE_NO_BOX
3135 && s->first_glyph->left_box_line_p)
3136 x = s->x + abs (s->face->box_line_width);
3137 else
3138 x = s->x;
3140 /* Draw characters of S as rectangles if S's font could not be
3141 loaded. */
3142 if (s->font_not_found_p)
3144 for (i = 0; i < s->nchars; ++i)
3146 struct glyph *g = s->first_glyph + i;
3147 XDrawRectangle (s->display, s->window,
3148 s->gc, x, s->y, g->pixel_width - 1,
3149 s->height - 1);
3150 x += g->pixel_width;
3153 else
3155 char *char1b = (char *) s->char2b;
3156 int boff = s->font_info->baseline_offset;
3158 if (s->font_info->vertical_centering)
3159 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3161 /* If we can use 8-bit functions, condense S->char2b. */
3162 if (!s->two_byte_p)
3163 for (i = 0; i < s->nchars; ++i)
3164 char1b[i] = s->char2b[i].byte2;
3166 /* Draw text with XDrawString if background has already been
3167 filled. Otherwise, use XDrawImageString. (Note that
3168 XDrawImageString is usually faster than XDrawString.) Always
3169 use XDrawImageString when drawing the cursor so that there is
3170 no chance that characters under a box cursor are invisible. */
3171 if (s->for_overlaps_p
3172 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3174 /* Draw characters with 16-bit or 8-bit functions. */
3175 if (s->two_byte_p)
3176 XDrawString16 (s->display, s->window, s->gc, x,
3177 s->ybase - boff, s->char2b, s->nchars);
3178 else
3179 XDrawString (s->display, s->window, s->gc, x,
3180 s->ybase - boff, char1b, s->nchars);
3182 else
3184 if (s->two_byte_p)
3185 XDrawImageString16 (s->display, s->window, s->gc, x,
3186 s->ybase - boff, s->char2b, s->nchars);
3187 else
3188 XDrawImageString (s->display, s->window, s->gc, x,
3189 s->ybase - boff, char1b, s->nchars);
3194 /* Draw the foreground of composite glyph string S. */
3196 static void
3197 x_draw_composite_glyph_string_foreground (s)
3198 struct glyph_string *s;
3200 int i, x;
3202 /* If first glyph of S has a left box line, start drawing the text
3203 of S to the right of that box line. */
3204 if (s->face->box != FACE_NO_BOX
3205 && s->first_glyph->left_box_line_p)
3206 x = s->x + abs (s->face->box_line_width);
3207 else
3208 x = s->x;
3210 /* S is a glyph string for a composition. S->gidx is the index of
3211 the first character drawn for glyphs of this composition.
3212 S->gidx == 0 means we are drawing the very first character of
3213 this composition. */
3215 /* Draw a rectangle for the composition if the font for the very
3216 first character of the composition could not be loaded. */
3217 if (s->font_not_found_p)
3219 if (s->gidx == 0)
3220 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3221 s->width - 1, s->height - 1);
3223 else
3225 for (i = 0; i < s->nchars; i++, ++s->gidx)
3226 XDrawString16 (s->display, s->window, s->gc,
3227 x + s->cmp->offsets[s->gidx * 2],
3228 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3229 s->char2b + i, 1);
3234 #ifdef USE_X_TOOLKIT
3236 static struct frame *x_frame_of_widget P_ ((Widget));
3237 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3238 XrmValue *, XrmValue *, XtPointer *));
3239 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3240 XrmValue *, Cardinal *));
3243 /* Return the frame on which widget WIDGET is used.. Abort if frame
3244 cannot be determined. */
3246 static struct frame *
3247 x_frame_of_widget (widget)
3248 Widget widget;
3250 struct x_display_info *dpyinfo;
3251 Lisp_Object tail;
3252 struct frame *f;
3254 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3256 /* Find the top-level shell of the widget. Note that this function
3257 can be called when the widget is not yet realized, so XtWindow
3258 (widget) == 0. That's the reason we can't simply use
3259 x_any_window_to_frame. */
3260 while (!XtIsTopLevelShell (widget))
3261 widget = XtParent (widget);
3263 /* Look for a frame with that top-level widget. Allocate the color
3264 on that frame to get the right gamma correction value. */
3265 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3266 if (GC_FRAMEP (XCAR (tail))
3267 && (f = XFRAME (XCAR (tail)),
3268 (f->output_data.nothing != 1
3269 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3270 && f->output_data.x->widget == widget)
3271 return f;
3273 abort ();
3277 /* Allocate the color COLOR->pixel on the screen and display of
3278 widget WIDGET in colormap CMAP. If an exact match cannot be
3279 allocated, try the nearest color available. Value is non-zero
3280 if successful. This is called from lwlib. */
3283 x_alloc_nearest_color_for_widget (widget, cmap, color)
3284 Widget widget;
3285 Colormap cmap;
3286 XColor *color;
3288 struct frame *f = x_frame_of_widget (widget);
3289 return x_alloc_nearest_color (f, cmap, color);
3293 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3294 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3295 If this produces the same color as PIXEL, try a color where all RGB
3296 values have DELTA added. Return the allocated color in *PIXEL.
3297 DISPLAY is the X display, CMAP is the colormap to operate on.
3298 Value is non-zero if successful. */
3301 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3302 Widget widget;
3303 Display *display;
3304 Colormap cmap;
3305 unsigned long *pixel;
3306 double factor;
3307 int delta;
3309 struct frame *f = x_frame_of_widget (widget);
3310 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3314 /* Structure specifying which arguments should be passed by Xt to
3315 cvt_string_to_pixel. We want the widget's screen and colormap. */
3317 static XtConvertArgRec cvt_string_to_pixel_args[] =
3319 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3320 sizeof (Screen *)},
3321 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3322 sizeof (Colormap)}
3326 /* The address of this variable is returned by
3327 cvt_string_to_pixel. */
3329 static Pixel cvt_string_to_pixel_value;
3332 /* Convert a color name to a pixel color.
3334 DPY is the display we are working on.
3336 ARGS is an array of *NARGS XrmValue structures holding additional
3337 information about the widget for which the conversion takes place.
3338 The contents of this array are determined by the specification
3339 in cvt_string_to_pixel_args.
3341 FROM is a pointer to an XrmValue which points to the color name to
3342 convert. TO is an XrmValue in which to return the pixel color.
3344 CLOSURE_RET is a pointer to user-data, in which we record if
3345 we allocated the color or not.
3347 Value is True if successful, False otherwise. */
3349 static Boolean
3350 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3351 Display *dpy;
3352 XrmValue *args;
3353 Cardinal *nargs;
3354 XrmValue *from, *to;
3355 XtPointer *closure_ret;
3357 Screen *screen;
3358 Colormap cmap;
3359 Pixel pixel;
3360 String color_name;
3361 XColor color;
3363 if (*nargs != 2)
3365 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3366 "wrongParameters", "cvt_string_to_pixel",
3367 "XtToolkitError",
3368 "Screen and colormap args required", NULL, NULL);
3369 return False;
3372 screen = *(Screen **) args[0].addr;
3373 cmap = *(Colormap *) args[1].addr;
3374 color_name = (String) from->addr;
3376 if (strcmp (color_name, XtDefaultBackground) == 0)
3378 *closure_ret = (XtPointer) False;
3379 pixel = WhitePixelOfScreen (screen);
3381 else if (strcmp (color_name, XtDefaultForeground) == 0)
3383 *closure_ret = (XtPointer) False;
3384 pixel = BlackPixelOfScreen (screen);
3386 else if (XParseColor (dpy, cmap, color_name, &color)
3387 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3389 pixel = color.pixel;
3390 *closure_ret = (XtPointer) True;
3392 else
3394 String params[1];
3395 Cardinal nparams = 1;
3397 params[0] = color_name;
3398 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3399 "badValue", "cvt_string_to_pixel",
3400 "XtToolkitError", "Invalid color `%s'",
3401 params, &nparams);
3402 return False;
3405 if (to->addr != NULL)
3407 if (to->size < sizeof (Pixel))
3409 to->size = sizeof (Pixel);
3410 return False;
3413 *(Pixel *) to->addr = pixel;
3415 else
3417 cvt_string_to_pixel_value = pixel;
3418 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3421 to->size = sizeof (Pixel);
3422 return True;
3426 /* Free a pixel color which was previously allocated via
3427 cvt_string_to_pixel. This is registered as the destructor
3428 for this type of resource via XtSetTypeConverter.
3430 APP is the application context in which we work.
3432 TO is a pointer to an XrmValue holding the color to free.
3433 CLOSURE is the value we stored in CLOSURE_RET for this color
3434 in cvt_string_to_pixel.
3436 ARGS and NARGS are like for cvt_string_to_pixel. */
3438 static void
3439 cvt_pixel_dtor (app, to, closure, args, nargs)
3440 XtAppContext app;
3441 XrmValuePtr to;
3442 XtPointer closure;
3443 XrmValuePtr args;
3444 Cardinal *nargs;
3446 if (*nargs != 2)
3448 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3449 "XtToolkitError",
3450 "Screen and colormap arguments required",
3451 NULL, NULL);
3453 else if (closure != NULL)
3455 /* We did allocate the pixel, so free it. */
3456 Screen *screen = *(Screen **) args[0].addr;
3457 Colormap cmap = *(Colormap *) args[1].addr;
3458 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3459 (Pixel *) to->addr, 1);
3464 #endif /* USE_X_TOOLKIT */
3467 /* Value is an array of XColor structures for the contents of the
3468 color map of display DPY. Set *NCELLS to the size of the array.
3469 Note that this probably shouldn't be called for large color maps,
3470 say a 24-bit TrueColor map. */
3472 static const XColor *
3473 x_color_cells (dpy, ncells)
3474 Display *dpy;
3475 int *ncells;
3477 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3479 if (dpyinfo->color_cells == NULL)
3481 Screen *screen = dpyinfo->screen;
3482 int i;
3484 dpyinfo->ncolor_cells
3485 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3486 dpyinfo->color_cells
3487 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3488 * sizeof *dpyinfo->color_cells);
3490 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3491 dpyinfo->color_cells[i].pixel = i;
3493 XQueryColors (dpy, dpyinfo->cmap,
3494 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3497 *ncells = dpyinfo->ncolor_cells;
3498 return dpyinfo->color_cells;
3502 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3503 colors in COLORS. Use cached information, if available. */
3505 void
3506 x_query_colors (f, colors, ncolors)
3507 struct frame *f;
3508 XColor *colors;
3509 int ncolors;
3511 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3513 if (dpyinfo->color_cells)
3515 int i;
3516 for (i = 0; i < ncolors; ++i)
3518 unsigned long pixel = colors[i].pixel;
3519 xassert (pixel < dpyinfo->ncolor_cells);
3520 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3521 colors[i] = dpyinfo->color_cells[pixel];
3524 else
3525 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3529 /* On frame F, translate pixel color to RGB values for the color in
3530 COLOR. Use cached information, if available. */
3532 void
3533 x_query_color (f, color)
3534 struct frame *f;
3535 XColor *color;
3537 x_query_colors (f, color, 1);
3541 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3542 exact match can't be allocated, try the nearest color available.
3543 Value is non-zero if successful. Set *COLOR to the color
3544 allocated. */
3546 static int
3547 x_alloc_nearest_color_1 (dpy, cmap, color)
3548 Display *dpy;
3549 Colormap cmap;
3550 XColor *color;
3552 int rc;
3554 rc = XAllocColor (dpy, cmap, color);
3555 if (rc == 0)
3557 /* If we got to this point, the colormap is full, so we're going
3558 to try to get the next closest color. The algorithm used is
3559 a least-squares matching, which is what X uses for closest
3560 color matching with StaticColor visuals. */
3561 int nearest, i;
3562 unsigned long nearest_delta = ~0;
3563 int ncells;
3564 const XColor *cells = x_color_cells (dpy, &ncells);
3566 for (nearest = i = 0; i < ncells; ++i)
3568 long dred = (color->red >> 8) - (cells[i].red >> 8);
3569 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3570 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3571 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3573 if (delta < nearest_delta)
3575 nearest = i;
3576 nearest_delta = delta;
3580 color->red = cells[nearest].red;
3581 color->green = cells[nearest].green;
3582 color->blue = cells[nearest].blue;
3583 rc = XAllocColor (dpy, cmap, color);
3585 else
3587 /* If allocation succeeded, and the allocated pixel color is not
3588 equal to a cached pixel color recorded earlier, there was a
3589 change in the colormap, so clear the color cache. */
3590 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3591 XColor *cached_color;
3593 if (dpyinfo->color_cells
3594 && (cached_color = &dpyinfo->color_cells[color->pixel],
3595 (cached_color->red != color->red
3596 || cached_color->blue != color->blue
3597 || cached_color->green != color->green)))
3599 xfree (dpyinfo->color_cells);
3600 dpyinfo->color_cells = NULL;
3601 dpyinfo->ncolor_cells = 0;
3605 #ifdef DEBUG_X_COLORS
3606 if (rc)
3607 register_color (color->pixel);
3608 #endif /* DEBUG_X_COLORS */
3610 return rc;
3614 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3615 exact match can't be allocated, try the nearest color available.
3616 Value is non-zero if successful. Set *COLOR to the color
3617 allocated. */
3620 x_alloc_nearest_color (f, cmap, color)
3621 struct frame *f;
3622 Colormap cmap;
3623 XColor *color;
3625 gamma_correct (f, color);
3626 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3630 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3631 It's necessary to do this instead of just using PIXEL directly to
3632 get color reference counts right. */
3634 unsigned long
3635 x_copy_color (f, pixel)
3636 struct frame *f;
3637 unsigned long pixel;
3639 XColor color;
3641 color.pixel = pixel;
3642 BLOCK_INPUT;
3643 x_query_color (f, &color);
3644 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3645 UNBLOCK_INPUT;
3646 #ifdef DEBUG_X_COLORS
3647 register_color (pixel);
3648 #endif
3649 return color.pixel;
3653 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3654 It's necessary to do this instead of just using PIXEL directly to
3655 get color reference counts right. */
3657 unsigned long
3658 x_copy_dpy_color (dpy, cmap, pixel)
3659 Display *dpy;
3660 Colormap cmap;
3661 unsigned long pixel;
3663 XColor color;
3665 color.pixel = pixel;
3666 BLOCK_INPUT;
3667 XQueryColor (dpy, cmap, &color);
3668 XAllocColor (dpy, cmap, &color);
3669 UNBLOCK_INPUT;
3670 #ifdef DEBUG_X_COLORS
3671 register_color (pixel);
3672 #endif
3673 return color.pixel;
3677 /* Brightness beyond which a color won't have its highlight brightness
3678 boosted.
3680 Nominally, highlight colors for `3d' faces are calculated by
3681 brightening an object's color by a constant scale factor, but this
3682 doesn't yield good results for dark colors, so for colors who's
3683 brightness is less than this value (on a scale of 0-65535) have an
3684 use an additional additive factor.
3686 The value here is set so that the default menu-bar/mode-line color
3687 (grey75) will not have its highlights changed at all. */
3688 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3691 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3692 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3693 If this produces the same color as PIXEL, try a color where all RGB
3694 values have DELTA added. Return the allocated color in *PIXEL.
3695 DISPLAY is the X display, CMAP is the colormap to operate on.
3696 Value is non-zero if successful. */
3698 static int
3699 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3700 struct frame *f;
3701 Display *display;
3702 Colormap cmap;
3703 unsigned long *pixel;
3704 double factor;
3705 int delta;
3707 XColor color, new;
3708 long bright;
3709 int success_p;
3711 /* Get RGB color values. */
3712 color.pixel = *pixel;
3713 x_query_color (f, &color);
3715 /* Change RGB values by specified FACTOR. Avoid overflow! */
3716 xassert (factor >= 0);
3717 new.red = min (0xffff, factor * color.red);
3718 new.green = min (0xffff, factor * color.green);
3719 new.blue = min (0xffff, factor * color.blue);
3721 /* Calculate brightness of COLOR. */
3722 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3724 /* We only boost colors that are darker than
3725 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3726 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3727 /* Make an additive adjustment to NEW, because it's dark enough so
3728 that scaling by FACTOR alone isn't enough. */
3730 /* How far below the limit this color is (0 - 1, 1 being darker). */
3731 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3732 /* The additive adjustment. */
3733 int min_delta = delta * dimness * factor / 2;
3735 if (factor < 1)
3737 new.red = max (0, new.red - min_delta);
3738 new.green = max (0, new.green - min_delta);
3739 new.blue = max (0, new.blue - min_delta);
3741 else
3743 new.red = min (0xffff, min_delta + new.red);
3744 new.green = min (0xffff, min_delta + new.green);
3745 new.blue = min (0xffff, min_delta + new.blue);
3749 /* Try to allocate the color. */
3750 success_p = x_alloc_nearest_color (f, cmap, &new);
3751 if (success_p)
3753 if (new.pixel == *pixel)
3755 /* If we end up with the same color as before, try adding
3756 delta to the RGB values. */
3757 x_free_colors (f, &new.pixel, 1);
3759 new.red = min (0xffff, delta + color.red);
3760 new.green = min (0xffff, delta + color.green);
3761 new.blue = min (0xffff, delta + color.blue);
3762 success_p = x_alloc_nearest_color (f, cmap, &new);
3764 else
3765 success_p = 1;
3766 *pixel = new.pixel;
3769 return success_p;
3773 /* Set up the foreground color for drawing relief lines of glyph
3774 string S. RELIEF is a pointer to a struct relief containing the GC
3775 with which lines will be drawn. Use a color that is FACTOR or
3776 DELTA lighter or darker than the relief's background which is found
3777 in S->f->output_data.x->relief_background. If such a color cannot
3778 be allocated, use DEFAULT_PIXEL, instead. */
3780 static void
3781 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3782 struct frame *f;
3783 struct relief *relief;
3784 double factor;
3785 int delta;
3786 unsigned long default_pixel;
3788 XGCValues xgcv;
3789 struct x_output *di = f->output_data.x;
3790 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3791 unsigned long pixel;
3792 unsigned long background = di->relief_background;
3793 Colormap cmap = FRAME_X_COLORMAP (f);
3794 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3795 Display *dpy = FRAME_X_DISPLAY (f);
3797 xgcv.graphics_exposures = False;
3798 xgcv.line_width = 1;
3800 /* Free previously allocated color. The color cell will be reused
3801 when it has been freed as many times as it was allocated, so this
3802 doesn't affect faces using the same colors. */
3803 if (relief->gc
3804 && relief->allocated_p)
3806 x_free_colors (f, &relief->pixel, 1);
3807 relief->allocated_p = 0;
3810 /* Allocate new color. */
3811 xgcv.foreground = default_pixel;
3812 pixel = background;
3813 if (dpyinfo->n_planes != 1
3814 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3816 relief->allocated_p = 1;
3817 xgcv.foreground = relief->pixel = pixel;
3820 if (relief->gc == 0)
3822 xgcv.stipple = dpyinfo->gray;
3823 mask |= GCStipple;
3824 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3826 else
3827 XChangeGC (dpy, relief->gc, mask, &xgcv);
3831 /* Set up colors for the relief lines around glyph string S. */
3833 static void
3834 x_setup_relief_colors (s)
3835 struct glyph_string *s;
3837 struct x_output *di = s->f->output_data.x;
3838 unsigned long color;
3840 if (s->face->use_box_color_for_shadows_p)
3841 color = s->face->box_color;
3842 else if (s->first_glyph->type == IMAGE_GLYPH
3843 && s->img->pixmap
3844 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3845 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3846 else
3848 XGCValues xgcv;
3850 /* Get the background color of the face. */
3851 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3852 color = xgcv.background;
3855 if (di->white_relief.gc == 0
3856 || color != di->relief_background)
3858 di->relief_background = color;
3859 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3860 WHITE_PIX_DEFAULT (s->f));
3861 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3862 BLACK_PIX_DEFAULT (s->f));
3867 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3868 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3869 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3870 relief. LEFT_P non-zero means draw a relief on the left side of
3871 the rectangle. RIGHT_P non-zero means draw a relief on the right
3872 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3873 when drawing. */
3875 static void
3876 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3877 raised_p, left_p, right_p, clip_rect)
3878 struct frame *f;
3879 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3880 XRectangle *clip_rect;
3882 Display *dpy = FRAME_X_DISPLAY (f);
3883 Window window = FRAME_X_WINDOW (f);
3884 int i;
3885 GC gc;
3887 if (raised_p)
3888 gc = f->output_data.x->white_relief.gc;
3889 else
3890 gc = f->output_data.x->black_relief.gc;
3891 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3893 /* Top. */
3894 for (i = 0; i < width; ++i)
3895 XDrawLine (dpy, window, gc,
3896 left_x + i * left_p, top_y + i,
3897 right_x + 1 - i * right_p, top_y + i);
3899 /* Left. */
3900 if (left_p)
3901 for (i = 0; i < width; ++i)
3902 XDrawLine (dpy, window, gc,
3903 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3905 XSetClipMask (dpy, gc, None);
3906 if (raised_p)
3907 gc = f->output_data.x->black_relief.gc;
3908 else
3909 gc = f->output_data.x->white_relief.gc;
3910 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3912 /* Bottom. */
3913 for (i = 0; i < width; ++i)
3914 XDrawLine (dpy, window, gc,
3915 left_x + i * left_p, bottom_y - i,
3916 right_x + 1 - i * right_p, bottom_y - i);
3918 /* Right. */
3919 if (right_p)
3920 for (i = 0; i < width; ++i)
3921 XDrawLine (dpy, window, gc,
3922 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3924 XSetClipMask (dpy, gc, None);
3928 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3929 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3930 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3931 left side of the rectangle. RIGHT_P non-zero means draw a line
3932 on the right side of the rectangle. CLIP_RECT is the clipping
3933 rectangle to use when drawing. */
3935 static void
3936 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3937 left_p, right_p, clip_rect)
3938 struct glyph_string *s;
3939 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3940 XRectangle *clip_rect;
3942 XGCValues xgcv;
3944 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3945 XSetForeground (s->display, s->gc, s->face->box_color);
3946 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3948 /* Top. */
3949 XFillRectangle (s->display, s->window, s->gc,
3950 left_x, top_y, right_x - left_x + 1, width);
3952 /* Left. */
3953 if (left_p)
3954 XFillRectangle (s->display, s->window, s->gc,
3955 left_x, top_y, width, bottom_y - top_y + 1);
3957 /* Bottom. */
3958 XFillRectangle (s->display, s->window, s->gc,
3959 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3961 /* Right. */
3962 if (right_p)
3963 XFillRectangle (s->display, s->window, s->gc,
3964 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3966 XSetForeground (s->display, s->gc, xgcv.foreground);
3967 XSetClipMask (s->display, s->gc, None);
3971 /* Draw a box around glyph string S. */
3973 static void
3974 x_draw_glyph_string_box (s)
3975 struct glyph_string *s;
3977 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3978 int left_p, right_p;
3979 struct glyph *last_glyph;
3980 XRectangle clip_rect;
3982 last_x = window_box_right (s->w, s->area);
3983 if (s->row->full_width_p
3984 && !s->w->pseudo_window_p)
3986 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
3987 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3988 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3991 /* The glyph that may have a right box line. */
3992 last_glyph = (s->cmp || s->img
3993 ? s->first_glyph
3994 : s->first_glyph + s->nchars - 1);
3996 width = abs (s->face->box_line_width);
3997 raised_p = s->face->box == FACE_RAISED_BOX;
3998 left_x = s->x;
3999 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
4000 ? last_x - 1
4001 : min (last_x, s->x + s->background_width) - 1);
4002 top_y = s->y;
4003 bottom_y = top_y + s->height - 1;
4005 left_p = (s->first_glyph->left_box_line_p
4006 || (s->hl == DRAW_MOUSE_FACE
4007 && (s->prev == NULL
4008 || s->prev->hl != s->hl)));
4009 right_p = (last_glyph->right_box_line_p
4010 || (s->hl == DRAW_MOUSE_FACE
4011 && (s->next == NULL
4012 || s->next->hl != s->hl)));
4014 x_get_glyph_string_clip_rect (s, &clip_rect);
4016 if (s->face->box == FACE_SIMPLE_BOX)
4017 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4018 left_p, right_p, &clip_rect);
4019 else
4021 x_setup_relief_colors (s);
4022 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4023 width, raised_p, left_p, right_p, &clip_rect);
4028 /* Draw foreground of image glyph string S. */
4030 static void
4031 x_draw_image_foreground (s)
4032 struct glyph_string *s;
4034 int x;
4035 int y = s->ybase - image_ascent (s->img, s->face);
4037 /* If first glyph of S has a left box line, start drawing it to the
4038 right of that line. */
4039 if (s->face->box != FACE_NO_BOX
4040 && s->first_glyph->left_box_line_p)
4041 x = s->x + abs (s->face->box_line_width);
4042 else
4043 x = s->x;
4045 /* If there is a margin around the image, adjust x- and y-position
4046 by that margin. */
4047 x += s->img->hmargin;
4048 y += s->img->vmargin;
4050 if (s->img->pixmap)
4052 if (s->img->mask)
4054 /* We can't set both a clip mask and use XSetClipRectangles
4055 because the latter also sets a clip mask. We also can't
4056 trust on the shape extension to be available
4057 (XShapeCombineRegion). So, compute the rectangle to draw
4058 manually. */
4059 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4060 | GCFunction);
4061 XGCValues xgcv;
4062 XRectangle clip_rect, image_rect, r;
4064 xgcv.clip_mask = s->img->mask;
4065 xgcv.clip_x_origin = x;
4066 xgcv.clip_y_origin = y;
4067 xgcv.function = GXcopy;
4068 XChangeGC (s->display, s->gc, mask, &xgcv);
4070 x_get_glyph_string_clip_rect (s, &clip_rect);
4071 image_rect.x = x;
4072 image_rect.y = y;
4073 image_rect.width = s->img->width;
4074 image_rect.height = s->img->height;
4075 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4076 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4077 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4079 else
4081 XRectangle clip_rect, image_rect, r;
4083 x_get_glyph_string_clip_rect (s, &clip_rect);
4084 image_rect.x = x;
4085 image_rect.y = y;
4086 image_rect.width = s->img->width;
4087 image_rect.height = s->img->height;
4088 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4089 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4090 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4092 /* When the image has a mask, we can expect that at
4093 least part of a mouse highlight or a block cursor will
4094 be visible. If the image doesn't have a mask, make
4095 a block cursor visible by drawing a rectangle around
4096 the image. I believe it's looking better if we do
4097 nothing here for mouse-face. */
4098 if (s->hl == DRAW_CURSOR)
4099 XDrawRectangle (s->display, s->window, s->gc, x, y,
4100 s->img->width - 1, s->img->height - 1);
4103 else
4104 /* Draw a rectangle if image could not be loaded. */
4105 XDrawRectangle (s->display, s->window, s->gc, x, y,
4106 s->img->width - 1, s->img->height - 1);
4110 /* Draw a relief around the image glyph string S. */
4112 static void
4113 x_draw_image_relief (s)
4114 struct glyph_string *s;
4116 int x0, y0, x1, y1, thick, raised_p;
4117 XRectangle r;
4118 int x;
4119 int y = s->ybase - image_ascent (s->img, s->face);
4121 /* If first glyph of S has a left box line, start drawing it to the
4122 right of that line. */
4123 if (s->face->box != FACE_NO_BOX
4124 && s->first_glyph->left_box_line_p)
4125 x = s->x + abs (s->face->box_line_width);
4126 else
4127 x = s->x;
4129 /* If there is a margin around the image, adjust x- and y-position
4130 by that margin. */
4131 x += s->img->hmargin;
4132 y += s->img->vmargin;
4134 if (s->hl == DRAW_IMAGE_SUNKEN
4135 || s->hl == DRAW_IMAGE_RAISED)
4137 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4138 raised_p = s->hl == DRAW_IMAGE_RAISED;
4140 else
4142 thick = abs (s->img->relief);
4143 raised_p = s->img->relief > 0;
4146 x0 = x - thick;
4147 y0 = y - thick;
4148 x1 = x + s->img->width + thick - 1;
4149 y1 = y + s->img->height + thick - 1;
4151 x_setup_relief_colors (s);
4152 x_get_glyph_string_clip_rect (s, &r);
4153 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4157 /* Draw the foreground of image glyph string S to PIXMAP. */
4159 static void
4160 x_draw_image_foreground_1 (s, pixmap)
4161 struct glyph_string *s;
4162 Pixmap pixmap;
4164 int x;
4165 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4167 /* If first glyph of S has a left box line, start drawing it to the
4168 right of that line. */
4169 if (s->face->box != FACE_NO_BOX
4170 && s->first_glyph->left_box_line_p)
4171 x = abs (s->face->box_line_width);
4172 else
4173 x = 0;
4175 /* If there is a margin around the image, adjust x- and y-position
4176 by that margin. */
4177 x += s->img->hmargin;
4178 y += s->img->vmargin;
4180 if (s->img->pixmap)
4182 if (s->img->mask)
4184 /* We can't set both a clip mask and use XSetClipRectangles
4185 because the latter also sets a clip mask. We also can't
4186 trust on the shape extension to be available
4187 (XShapeCombineRegion). So, compute the rectangle to draw
4188 manually. */
4189 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4190 | GCFunction);
4191 XGCValues xgcv;
4193 xgcv.clip_mask = s->img->mask;
4194 xgcv.clip_x_origin = x;
4195 xgcv.clip_y_origin = y;
4196 xgcv.function = GXcopy;
4197 XChangeGC (s->display, s->gc, mask, &xgcv);
4199 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4200 0, 0, s->img->width, s->img->height, x, y);
4201 XSetClipMask (s->display, s->gc, None);
4203 else
4205 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4206 0, 0, s->img->width, s->img->height, x, y);
4208 /* When the image has a mask, we can expect that at
4209 least part of a mouse highlight or a block cursor will
4210 be visible. If the image doesn't have a mask, make
4211 a block cursor visible by drawing a rectangle around
4212 the image. I believe it's looking better if we do
4213 nothing here for mouse-face. */
4214 if (s->hl == DRAW_CURSOR)
4215 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4216 s->img->width - 1, s->img->height - 1);
4219 else
4220 /* Draw a rectangle if image could not be loaded. */
4221 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4222 s->img->width - 1, s->img->height - 1);
4226 /* Draw part of the background of glyph string S. X, Y, W, and H
4227 give the rectangle to draw. */
4229 static void
4230 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4231 struct glyph_string *s;
4232 int x, y, w, h;
4234 if (s->stippled_p)
4236 /* Fill background with a stipple pattern. */
4237 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4238 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4239 XSetFillStyle (s->display, s->gc, FillSolid);
4241 else
4242 x_clear_glyph_string_rect (s, x, y, w, h);
4246 /* Draw image glyph string S.
4248 s->y
4249 s->x +-------------------------
4250 | s->face->box
4252 | +-------------------------
4253 | | s->img->margin
4255 | | +-------------------
4256 | | | the image
4260 static void
4261 x_draw_image_glyph_string (s)
4262 struct glyph_string *s;
4264 int x, y;
4265 int box_line_hwidth = abs (s->face->box_line_width);
4266 int box_line_vwidth = max (s->face->box_line_width, 0);
4267 int height;
4268 Pixmap pixmap = None;
4270 height = s->height - 2 * box_line_vwidth;
4272 /* Fill background with face under the image. Do it only if row is
4273 taller than image or if image has a clip mask to reduce
4274 flickering. */
4275 s->stippled_p = s->face->stipple != 0;
4276 if (height > s->img->height
4277 || s->img->hmargin
4278 || s->img->vmargin
4279 || s->img->mask
4280 || s->img->pixmap == 0
4281 || s->width != s->background_width)
4283 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4284 x = s->x + box_line_hwidth;
4285 else
4286 x = s->x;
4288 y = s->y + box_line_vwidth;
4290 if (s->img->mask)
4292 /* Create a pixmap as large as the glyph string. Fill it
4293 with the background color. Copy the image to it, using
4294 its mask. Copy the temporary pixmap to the display. */
4295 Screen *screen = FRAME_X_SCREEN (s->f);
4296 int depth = DefaultDepthOfScreen (screen);
4298 /* Create a pixmap as large as the glyph string. */
4299 pixmap = XCreatePixmap (s->display, s->window,
4300 s->background_width,
4301 s->height, depth);
4303 /* Don't clip in the following because we're working on the
4304 pixmap. */
4305 XSetClipMask (s->display, s->gc, None);
4307 /* Fill the pixmap with the background color/stipple. */
4308 if (s->stippled_p)
4310 /* Fill background with a stipple pattern. */
4311 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4312 XFillRectangle (s->display, pixmap, s->gc,
4313 0, 0, s->background_width, s->height);
4314 XSetFillStyle (s->display, s->gc, FillSolid);
4316 else
4318 XGCValues xgcv;
4319 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4320 &xgcv);
4321 XSetForeground (s->display, s->gc, xgcv.background);
4322 XFillRectangle (s->display, pixmap, s->gc,
4323 0, 0, s->background_width, s->height);
4324 XSetForeground (s->display, s->gc, xgcv.foreground);
4327 else
4328 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4330 s->background_filled_p = 1;
4333 /* Draw the foreground. */
4334 if (pixmap != None)
4336 x_draw_image_foreground_1 (s, pixmap);
4337 x_set_glyph_string_clipping (s);
4338 XCopyArea (s->display, pixmap, s->window, s->gc,
4339 0, 0, s->background_width, s->height, s->x, s->y);
4340 XFreePixmap (s->display, pixmap);
4342 else
4343 x_draw_image_foreground (s);
4345 /* If we must draw a relief around the image, do it. */
4346 if (s->img->relief
4347 || s->hl == DRAW_IMAGE_RAISED
4348 || s->hl == DRAW_IMAGE_SUNKEN)
4349 x_draw_image_relief (s);
4353 /* Draw stretch glyph string S. */
4355 static void
4356 x_draw_stretch_glyph_string (s)
4357 struct glyph_string *s;
4359 xassert (s->first_glyph->type == STRETCH_GLYPH);
4360 s->stippled_p = s->face->stipple != 0;
4362 if (s->hl == DRAW_CURSOR
4363 && !x_stretch_cursor_p)
4365 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4366 as wide as the stretch glyph. */
4367 int width = min (CANON_X_UNIT (s->f), s->background_width);
4369 /* Draw cursor. */
4370 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4372 /* Clear rest using the GC of the original non-cursor face. */
4373 if (width < s->background_width)
4375 int x = s->x + width, y = s->y;
4376 int w = s->background_width - width, h = s->height;
4377 XRectangle r;
4378 GC gc;
4380 if (s->row->mouse_face_p
4381 && cursor_in_mouse_face_p (s->w))
4383 x_set_mouse_face_gc (s);
4384 gc = s->gc;
4386 else
4387 gc = s->face->gc;
4389 x_get_glyph_string_clip_rect (s, &r);
4390 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4392 if (s->face->stipple)
4394 /* Fill background with a stipple pattern. */
4395 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4396 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4397 XSetFillStyle (s->display, gc, FillSolid);
4399 else
4401 XGCValues xgcv;
4402 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4403 XSetForeground (s->display, gc, xgcv.background);
4404 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4405 XSetForeground (s->display, gc, xgcv.foreground);
4409 else if (!s->background_filled_p)
4410 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4411 s->height);
4413 s->background_filled_p = 1;
4417 /* Draw glyph string S. */
4419 static void
4420 x_draw_glyph_string (s)
4421 struct glyph_string *s;
4423 int relief_drawn_p = 0;
4425 /* If S draws into the background of its successor, draw the
4426 background of the successor first so that S can draw into it.
4427 This makes S->next use XDrawString instead of XDrawImageString. */
4428 if (s->next && s->right_overhang && !s->for_overlaps_p)
4430 xassert (s->next->img == NULL);
4431 x_set_glyph_string_gc (s->next);
4432 x_set_glyph_string_clipping (s->next);
4433 x_draw_glyph_string_background (s->next, 1);
4436 /* Set up S->gc, set clipping and draw S. */
4437 x_set_glyph_string_gc (s);
4439 /* Draw relief (if any) in advance for char/composition so that the
4440 glyph string can be drawn over it. */
4441 if (!s->for_overlaps_p
4442 && s->face->box != FACE_NO_BOX
4443 && (s->first_glyph->type == CHAR_GLYPH
4444 || s->first_glyph->type == COMPOSITE_GLYPH))
4447 x_set_glyph_string_clipping (s);
4448 x_draw_glyph_string_background (s, 1);
4449 x_draw_glyph_string_box (s);
4450 x_set_glyph_string_clipping (s);
4451 relief_drawn_p = 1;
4453 else
4454 x_set_glyph_string_clipping (s);
4456 switch (s->first_glyph->type)
4458 case IMAGE_GLYPH:
4459 x_draw_image_glyph_string (s);
4460 break;
4462 case STRETCH_GLYPH:
4463 x_draw_stretch_glyph_string (s);
4464 break;
4466 case CHAR_GLYPH:
4467 if (s->for_overlaps_p)
4468 s->background_filled_p = 1;
4469 else
4470 x_draw_glyph_string_background (s, 0);
4471 x_draw_glyph_string_foreground (s);
4472 break;
4474 case COMPOSITE_GLYPH:
4475 if (s->for_overlaps_p || s->gidx > 0)
4476 s->background_filled_p = 1;
4477 else
4478 x_draw_glyph_string_background (s, 1);
4479 x_draw_composite_glyph_string_foreground (s);
4480 break;
4482 default:
4483 abort ();
4486 if (!s->for_overlaps_p)
4488 /* Draw underline. */
4489 if (s->face->underline_p)
4491 unsigned long tem, h;
4492 int y;
4494 /* Get the underline thickness. Default is 1 pixel. */
4495 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4496 h = 1;
4498 /* Get the underline position. This is the recommended
4499 vertical offset in pixels from the baseline to the top of
4500 the underline. This is a signed value according to the
4501 specs, and its default is
4503 ROUND ((maximum descent) / 2), with
4504 ROUND(x) = floor (x + 0.5) */
4506 if (x_use_underline_position_properties
4507 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4508 y = s->ybase + (long) tem;
4509 else if (s->face->font)
4510 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4511 else
4512 y = s->y + s->height - h;
4514 if (s->face->underline_defaulted_p)
4515 XFillRectangle (s->display, s->window, s->gc,
4516 s->x, y, s->width, h);
4517 else
4519 XGCValues xgcv;
4520 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4521 XSetForeground (s->display, s->gc, s->face->underline_color);
4522 XFillRectangle (s->display, s->window, s->gc,
4523 s->x, y, s->width, h);
4524 XSetForeground (s->display, s->gc, xgcv.foreground);
4528 /* Draw overline. */
4529 if (s->face->overline_p)
4531 unsigned long dy = 0, h = 1;
4533 if (s->face->overline_color_defaulted_p)
4534 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4535 s->width, h);
4536 else
4538 XGCValues xgcv;
4539 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4540 XSetForeground (s->display, s->gc, s->face->overline_color);
4541 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4542 s->width, h);
4543 XSetForeground (s->display, s->gc, xgcv.foreground);
4547 /* Draw strike-through. */
4548 if (s->face->strike_through_p)
4550 unsigned long h = 1;
4551 unsigned long dy = (s->height - h) / 2;
4553 if (s->face->strike_through_color_defaulted_p)
4554 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4555 s->width, h);
4556 else
4558 XGCValues xgcv;
4559 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4560 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4561 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4562 s->width, h);
4563 XSetForeground (s->display, s->gc, xgcv.foreground);
4567 /* Draw relief if not yet drawn. */
4568 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4569 x_draw_glyph_string_box (s);
4572 /* Reset clipping. */
4573 XSetClipMask (s->display, s->gc, None);
4577 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4578 struct face **, int));
4581 /* Fill glyph string S with composition components specified by S->cmp.
4583 FACES is an array of faces for all components of this composition.
4584 S->gidx is the index of the first component for S.
4585 OVERLAPS_P non-zero means S should draw the foreground only, and
4586 use its physical height for clipping.
4588 Value is the index of a component not in S. */
4590 static int
4591 x_fill_composite_glyph_string (s, faces, overlaps_p)
4592 struct glyph_string *s;
4593 struct face **faces;
4594 int overlaps_p;
4596 int i;
4598 xassert (s);
4600 s->for_overlaps_p = overlaps_p;
4602 s->face = faces[s->gidx];
4603 s->font = s->face->font;
4604 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4606 /* For all glyphs of this composition, starting at the offset
4607 S->gidx, until we reach the end of the definition or encounter a
4608 glyph that requires the different face, add it to S. */
4609 ++s->nchars;
4610 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4611 ++s->nchars;
4613 /* All glyph strings for the same composition has the same width,
4614 i.e. the width set for the first component of the composition. */
4616 s->width = s->first_glyph->pixel_width;
4618 /* If the specified font could not be loaded, use the frame's
4619 default font, but record the fact that we couldn't load it in
4620 the glyph string so that we can draw rectangles for the
4621 characters of the glyph string. */
4622 if (s->font == NULL)
4624 s->font_not_found_p = 1;
4625 s->font = FRAME_FONT (s->f);
4628 /* Adjust base line for subscript/superscript text. */
4629 s->ybase += s->first_glyph->voffset;
4631 xassert (s->face && s->face->gc);
4633 /* This glyph string must always be drawn with 16-bit functions. */
4634 s->two_byte_p = 1;
4636 return s->gidx + s->nchars;
4640 /* Fill glyph string S from a sequence of character glyphs.
4642 FACE_ID is the face id of the string. START is the index of the
4643 first glyph to consider, END is the index of the last + 1.
4644 OVERLAPS_P non-zero means S should draw the foreground only, and
4645 use its physical height for clipping.
4647 Value is the index of the first glyph not in S. */
4649 static int
4650 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4651 struct glyph_string *s;
4652 int face_id;
4653 int start, end, overlaps_p;
4655 struct glyph *glyph, *last;
4656 int voffset;
4657 int glyph_not_available_p;
4659 xassert (s->f == XFRAME (s->w->frame));
4660 xassert (s->nchars == 0);
4661 xassert (start >= 0 && end > start);
4663 s->for_overlaps_p = overlaps_p,
4664 glyph = s->row->glyphs[s->area] + start;
4665 last = s->row->glyphs[s->area] + end;
4666 voffset = glyph->voffset;
4668 glyph_not_available_p = glyph->glyph_not_available_p;
4670 while (glyph < last
4671 && glyph->type == CHAR_GLYPH
4672 && glyph->voffset == voffset
4673 /* Same face id implies same font, nowadays. */
4674 && glyph->face_id == face_id
4675 && glyph->glyph_not_available_p == glyph_not_available_p)
4677 int two_byte_p;
4679 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4680 s->char2b + s->nchars,
4681 &two_byte_p);
4682 s->two_byte_p = two_byte_p;
4683 ++s->nchars;
4684 xassert (s->nchars <= end - start);
4685 s->width += glyph->pixel_width;
4686 ++glyph;
4689 s->font = s->face->font;
4690 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4692 /* If the specified font could not be loaded, use the frame's font,
4693 but record the fact that we couldn't load it in
4694 S->font_not_found_p so that we can draw rectangles for the
4695 characters of the glyph string. */
4696 if (s->font == NULL || glyph_not_available_p)
4698 s->font_not_found_p = 1;
4699 s->font = FRAME_FONT (s->f);
4702 /* Adjust base line for subscript/superscript text. */
4703 s->ybase += voffset;
4705 xassert (s->face && s->face->gc);
4706 return glyph - s->row->glyphs[s->area];
4710 /* Fill glyph string S from image glyph S->first_glyph. */
4712 static void
4713 x_fill_image_glyph_string (s)
4714 struct glyph_string *s;
4716 xassert (s->first_glyph->type == IMAGE_GLYPH);
4717 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4718 xassert (s->img);
4719 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4720 s->font = s->face->font;
4721 s->width = s->first_glyph->pixel_width;
4723 /* Adjust base line for subscript/superscript text. */
4724 s->ybase += s->first_glyph->voffset;
4728 /* Fill glyph string S from a sequence of stretch glyphs.
4730 ROW is the glyph row in which the glyphs are found, AREA is the
4731 area within the row. START is the index of the first glyph to
4732 consider, END is the index of the last + 1.
4734 Value is the index of the first glyph not in S. */
4736 static int
4737 x_fill_stretch_glyph_string (s, row, area, start, end)
4738 struct glyph_string *s;
4739 struct glyph_row *row;
4740 enum glyph_row_area area;
4741 int start, end;
4743 struct glyph *glyph, *last;
4744 int voffset, face_id;
4746 xassert (s->first_glyph->type == STRETCH_GLYPH);
4748 glyph = s->row->glyphs[s->area] + start;
4749 last = s->row->glyphs[s->area] + end;
4750 face_id = glyph->face_id;
4751 s->face = FACE_FROM_ID (s->f, face_id);
4752 s->font = s->face->font;
4753 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4754 s->width = glyph->pixel_width;
4755 voffset = glyph->voffset;
4757 for (++glyph;
4758 (glyph < last
4759 && glyph->type == STRETCH_GLYPH
4760 && glyph->voffset == voffset
4761 && glyph->face_id == face_id);
4762 ++glyph)
4763 s->width += glyph->pixel_width;
4765 /* Adjust base line for subscript/superscript text. */
4766 s->ybase += voffset;
4768 /* The case that face->gc == 0 is handled when drawing the glyph
4769 string by calling PREPARE_FACE_FOR_DISPLAY. */
4770 xassert (s->face);
4771 return glyph - s->row->glyphs[s->area];
4775 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4776 of XChar2b structures for S; it can't be allocated in
4777 x_init_glyph_string because it must be allocated via `alloca'. W
4778 is the window on which S is drawn. ROW and AREA are the glyph row
4779 and area within the row from which S is constructed. START is the
4780 index of the first glyph structure covered by S. HL is a
4781 face-override for drawing S. */
4783 static void
4784 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4785 struct glyph_string *s;
4786 XChar2b *char2b;
4787 struct window *w;
4788 struct glyph_row *row;
4789 enum glyph_row_area area;
4790 int start;
4791 enum draw_glyphs_face hl;
4793 bzero (s, sizeof *s);
4794 s->w = w;
4795 s->f = XFRAME (w->frame);
4796 s->display = FRAME_X_DISPLAY (s->f);
4797 s->window = FRAME_X_WINDOW (s->f);
4798 s->char2b = char2b;
4799 s->hl = hl;
4800 s->row = row;
4801 s->area = area;
4802 s->first_glyph = row->glyphs[area] + start;
4803 s->height = row->height;
4804 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4806 /* Display the internal border below the tool-bar window. */
4807 if (s->w == XWINDOW (s->f->tool_bar_window))
4808 s->y -= s->f->output_data.x->internal_border_width;
4810 s->ybase = s->y + row->ascent;
4814 /* Set background width of glyph string S. START is the index of the
4815 first glyph following S. LAST_X is the right-most x-position + 1
4816 in the drawing area. */
4818 static INLINE void
4819 x_set_glyph_string_background_width (s, start, last_x)
4820 struct glyph_string *s;
4821 int start;
4822 int last_x;
4824 /* If the face of this glyph string has to be drawn to the end of
4825 the drawing area, set S->extends_to_end_of_line_p. */
4826 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4828 if (start == s->row->used[s->area]
4829 && s->area == TEXT_AREA
4830 && ((s->hl == DRAW_NORMAL_TEXT
4831 && (s->row->fill_line_p
4832 || s->face->background != default_face->background
4833 || s->face->stipple != default_face->stipple
4834 || s->row->mouse_face_p))
4835 || s->hl == DRAW_MOUSE_FACE
4836 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4837 && s->row->fill_line_p)))
4838 s->extends_to_end_of_line_p = 1;
4840 /* If S extends its face to the end of the line, set its
4841 background_width to the distance to the right edge of the drawing
4842 area. */
4843 if (s->extends_to_end_of_line_p)
4844 s->background_width = last_x - s->x + 1;
4845 else
4846 s->background_width = s->width;
4850 /* Add a glyph string for a stretch glyph to the list of strings
4851 between HEAD and TAIL. START is the index of the stretch glyph in
4852 row area AREA of glyph row ROW. END is the index of the last glyph
4853 in that glyph row area. X is the current output position assigned
4854 to the new glyph string constructed. HL overrides that face of the
4855 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4856 is the right-most x-position of the drawing area. */
4858 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4859 and below -- keep them on one line. */
4860 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4861 do \
4863 s = (struct glyph_string *) alloca (sizeof *s); \
4864 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4865 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4866 x_append_glyph_string (&HEAD, &TAIL, s); \
4867 s->x = (X); \
4869 while (0)
4872 /* Add a glyph string for an image glyph to the list of strings
4873 between HEAD and TAIL. START is the index of the image glyph in
4874 row area AREA of glyph row ROW. END is the index of the last glyph
4875 in that glyph row area. X is the current output position assigned
4876 to the new glyph string constructed. HL overrides that face of the
4877 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4878 is the right-most x-position of the drawing area. */
4880 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4881 do \
4883 s = (struct glyph_string *) alloca (sizeof *s); \
4884 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4885 x_fill_image_glyph_string (s); \
4886 x_append_glyph_string (&HEAD, &TAIL, s); \
4887 ++START; \
4888 s->x = (X); \
4890 while (0)
4893 /* Add a glyph string for a sequence of character glyphs to the list
4894 of strings between HEAD and TAIL. START is the index of the first
4895 glyph in row area AREA of glyph row ROW that is part of the new
4896 glyph string. END is the index of the last glyph in that glyph row
4897 area. X is the current output position assigned to the new glyph
4898 string constructed. HL overrides that face of the glyph; e.g. it
4899 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4900 right-most x-position of the drawing area. */
4902 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4903 do \
4905 int c, face_id; \
4906 XChar2b *char2b; \
4908 c = (ROW)->glyphs[AREA][START].u.ch; \
4909 face_id = (ROW)->glyphs[AREA][START].face_id; \
4911 s = (struct glyph_string *) alloca (sizeof *s); \
4912 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4913 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4914 x_append_glyph_string (&HEAD, &TAIL, s); \
4915 s->x = (X); \
4916 START = x_fill_glyph_string (s, face_id, START, END, \
4917 OVERLAPS_P); \
4919 while (0)
4922 /* Add a glyph string for a composite sequence to the list of strings
4923 between HEAD and TAIL. START is the index of the first glyph in
4924 row area AREA of glyph row ROW that is part of the new glyph
4925 string. END is the index of the last glyph in that glyph row area.
4926 X is the current output position assigned to the new glyph string
4927 constructed. HL overrides that face of the glyph; e.g. it is
4928 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4929 x-position of the drawing area. */
4931 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4932 do { \
4933 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4934 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4935 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4936 struct composition *cmp = composition_table[cmp_id]; \
4937 int glyph_len = cmp->glyph_len; \
4938 XChar2b *char2b; \
4939 struct face **faces; \
4940 struct glyph_string *first_s = NULL; \
4941 int n; \
4943 base_face = base_face->ascii_face; \
4944 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4945 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4946 /* At first, fill in `char2b' and `faces'. */ \
4947 for (n = 0; n < glyph_len; n++) \
4949 int c = COMPOSITION_GLYPH (cmp, n); \
4950 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4951 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4952 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4953 this_face_id, char2b + n, 1); \
4956 /* Make glyph_strings for each glyph sequence that is drawable by \
4957 the same face, and append them to HEAD/TAIL. */ \
4958 for (n = 0; n < cmp->glyph_len;) \
4960 s = (struct glyph_string *) alloca (sizeof *s); \
4961 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4962 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4963 s->cmp = cmp; \
4964 s->gidx = n; \
4965 s->x = (X); \
4967 if (n == 0) \
4968 first_s = s; \
4970 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4973 ++START; \
4974 s = first_s; \
4975 } while (0)
4978 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4979 of AREA of glyph row ROW on window W between indices START and END.
4980 HL overrides the face for drawing glyph strings, e.g. it is
4981 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4982 x-positions of the drawing area.
4984 This is an ugly monster macro construct because we must use alloca
4985 to allocate glyph strings (because x_draw_glyphs can be called
4986 asynchronously). */
4988 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4989 do \
4991 HEAD = TAIL = NULL; \
4992 while (START < END) \
4994 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4995 switch (first_glyph->type) \
4997 case CHAR_GLYPH: \
4998 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4999 TAIL, HL, X, LAST_X, \
5000 OVERLAPS_P); \
5001 break; \
5003 case COMPOSITE_GLYPH: \
5004 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5005 HEAD, TAIL, HL, X, LAST_X,\
5006 OVERLAPS_P); \
5007 break; \
5009 case STRETCH_GLYPH: \
5010 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5011 HEAD, TAIL, HL, X, LAST_X); \
5012 break; \
5014 case IMAGE_GLYPH: \
5015 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5016 TAIL, HL, X, LAST_X); \
5017 break; \
5019 default: \
5020 abort (); \
5023 x_set_glyph_string_background_width (s, START, LAST_X); \
5024 (X) += s->width; \
5027 while (0)
5030 /* Draw glyphs between START and END in AREA of ROW on window W,
5031 starting at x-position X. X is relative to AREA in W. HL is a
5032 face-override with the following meaning:
5034 DRAW_NORMAL_TEXT draw normally
5035 DRAW_CURSOR draw in cursor face
5036 DRAW_MOUSE_FACE draw in mouse face.
5037 DRAW_INVERSE_VIDEO draw in mode line face
5038 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5039 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5041 If OVERLAPS_P is non-zero, draw only the foreground of characters
5042 and clip to the physical height of ROW.
5044 Value is the x-position reached, relative to AREA of W. */
5046 static int
5047 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5048 struct window *w;
5049 int x;
5050 struct glyph_row *row;
5051 enum glyph_row_area area;
5052 int start, end;
5053 enum draw_glyphs_face hl;
5054 int overlaps_p;
5056 struct glyph_string *head, *tail;
5057 struct glyph_string *s;
5058 int last_x, area_width;
5059 int x_reached;
5060 int i, j;
5062 /* Let's rather be paranoid than getting a SEGV. */
5063 end = min (end, row->used[area]);
5064 start = max (0, start);
5065 start = min (end, start);
5067 /* Translate X to frame coordinates. Set last_x to the right
5068 end of the drawing area. */
5069 if (row->full_width_p)
5071 /* X is relative to the left edge of W, without scroll bars
5072 or fringes. */
5073 struct frame *f = XFRAME (w->frame);
5074 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5076 x += window_left_x;
5077 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5078 last_x = window_left_x + area_width;
5080 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5082 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5083 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5084 last_x += width;
5085 else
5086 x -= width;
5089 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5090 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5092 else
5094 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5095 area_width = window_box_width (w, area);
5096 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5099 /* Build a doubly-linked list of glyph_string structures between
5100 head and tail from what we have to draw. Note that the macro
5101 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5102 the reason we use a separate variable `i'. */
5103 i = start;
5104 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5105 overlaps_p);
5106 if (tail)
5107 x_reached = tail->x + tail->background_width;
5108 else
5109 x_reached = x;
5111 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5112 the row, redraw some glyphs in front or following the glyph
5113 strings built above. */
5114 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5116 int dummy_x = 0;
5117 struct glyph_string *h, *t;
5119 /* Compute overhangs for all glyph strings. */
5120 for (s = head; s; s = s->next)
5121 x_compute_glyph_string_overhangs (s);
5123 /* Prepend glyph strings for glyphs in front of the first glyph
5124 string that are overwritten because of the first glyph
5125 string's left overhang. The background of all strings
5126 prepended must be drawn because the first glyph string
5127 draws over it. */
5128 i = x_left_overwritten (head);
5129 if (i >= 0)
5131 j = i;
5132 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5133 DRAW_NORMAL_TEXT, dummy_x, last_x,
5134 overlaps_p);
5135 start = i;
5136 x_compute_overhangs_and_x (t, head->x, 1);
5137 x_prepend_glyph_string_lists (&head, &tail, h, t);
5140 /* Prepend glyph strings for glyphs in front of the first glyph
5141 string that overwrite that glyph string because of their
5142 right overhang. For these strings, only the foreground must
5143 be drawn, because it draws over the glyph string at `head'.
5144 The background must not be drawn because this would overwrite
5145 right overhangs of preceding glyphs for which no glyph
5146 strings exist. */
5147 i = x_left_overwriting (head);
5148 if (i >= 0)
5150 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5151 DRAW_NORMAL_TEXT, dummy_x, last_x,
5152 overlaps_p);
5153 for (s = h; s; s = s->next)
5154 s->background_filled_p = 1;
5155 x_compute_overhangs_and_x (t, head->x, 1);
5156 x_prepend_glyph_string_lists (&head, &tail, h, t);
5159 /* Append glyphs strings for glyphs following the last glyph
5160 string tail that are overwritten by tail. The background of
5161 these strings has to be drawn because tail's foreground draws
5162 over it. */
5163 i = x_right_overwritten (tail);
5164 if (i >= 0)
5166 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5167 DRAW_NORMAL_TEXT, x, last_x,
5168 overlaps_p);
5169 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5170 x_append_glyph_string_lists (&head, &tail, h, t);
5173 /* Append glyph strings for glyphs following the last glyph
5174 string tail that overwrite tail. The foreground of such
5175 glyphs has to be drawn because it writes into the background
5176 of tail. The background must not be drawn because it could
5177 paint over the foreground of following glyphs. */
5178 i = x_right_overwriting (tail);
5179 if (i >= 0)
5181 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5182 DRAW_NORMAL_TEXT, x, last_x,
5183 overlaps_p);
5184 for (s = h; s; s = s->next)
5185 s->background_filled_p = 1;
5186 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5187 x_append_glyph_string_lists (&head, &tail, h, t);
5191 /* Draw all strings. */
5192 for (s = head; s; s = s->next)
5193 x_draw_glyph_string (s);
5195 if (area == TEXT_AREA
5196 && !row->full_width_p
5197 /* When drawing overlapping rows, only the glyph strings'
5198 foreground is drawn, which doesn't erase a cursor
5199 completely. */
5200 && !overlaps_p)
5202 int x0 = head ? head->x : x;
5203 int x1 = tail ? tail->x + tail->background_width : x;
5205 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5206 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5208 if (XFASTINT (w->left_margin_width) != 0)
5210 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5211 x0 -= left_area_width;
5212 x1 -= left_area_width;
5215 notice_overwritten_cursor (w, area, x0, x1,
5216 row->y, MATRIX_ROW_BOTTOM_Y (row));
5219 /* Value is the x-position up to which drawn, relative to AREA of W.
5220 This doesn't include parts drawn because of overhangs. */
5221 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5222 if (!row->full_width_p)
5224 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5225 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5226 if (area > TEXT_AREA)
5227 x_reached -= window_box_width (w, TEXT_AREA);
5230 return x_reached;
5234 /* Fix the display of area AREA of overlapping row ROW in window W. */
5236 static void
5237 x_fix_overlapping_area (w, row, area)
5238 struct window *w;
5239 struct glyph_row *row;
5240 enum glyph_row_area area;
5242 int i, x;
5244 BLOCK_INPUT;
5246 if (area == LEFT_MARGIN_AREA)
5247 x = 0;
5248 else if (area == TEXT_AREA)
5249 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5250 else
5251 x = (window_box_width (w, LEFT_MARGIN_AREA)
5252 + window_box_width (w, TEXT_AREA));
5254 for (i = 0; i < row->used[area];)
5256 if (row->glyphs[area][i].overlaps_vertically_p)
5258 int start = i, start_x = x;
5262 x += row->glyphs[area][i].pixel_width;
5263 ++i;
5265 while (i < row->used[area]
5266 && row->glyphs[area][i].overlaps_vertically_p);
5268 x_draw_glyphs (w, start_x, row, area, start, i,
5269 DRAW_NORMAL_TEXT, 1);
5271 else
5273 x += row->glyphs[area][i].pixel_width;
5274 ++i;
5278 UNBLOCK_INPUT;
5282 /* Output LEN glyphs starting at START at the nominal cursor position.
5283 Advance the nominal cursor over the text. The global variable
5284 updated_window contains the window being updated, updated_row is
5285 the glyph row being updated, and updated_area is the area of that
5286 row being updated. */
5288 static void
5289 x_write_glyphs (start, len)
5290 struct glyph *start;
5291 int len;
5293 int x, hpos;
5295 xassert (updated_window && updated_row);
5296 BLOCK_INPUT;
5298 /* Write glyphs. */
5300 hpos = start - updated_row->glyphs[updated_area];
5301 x = x_draw_glyphs (updated_window, output_cursor.x,
5302 updated_row, updated_area,
5303 hpos, hpos + len,
5304 DRAW_NORMAL_TEXT, 0);
5306 UNBLOCK_INPUT;
5308 /* Advance the output cursor. */
5309 output_cursor.hpos += len;
5310 output_cursor.x = x;
5314 /* Insert LEN glyphs from START at the nominal cursor position. */
5316 static void
5317 x_insert_glyphs (start, len)
5318 struct glyph *start;
5319 register int len;
5321 struct frame *f;
5322 struct window *w;
5323 int line_height, shift_by_width, shifted_region_width;
5324 struct glyph_row *row;
5325 struct glyph *glyph;
5326 int frame_x, frame_y, hpos;
5328 xassert (updated_window && updated_row);
5329 BLOCK_INPUT;
5330 w = updated_window;
5331 f = XFRAME (WINDOW_FRAME (w));
5333 /* Get the height of the line we are in. */
5334 row = updated_row;
5335 line_height = row->height;
5337 /* Get the width of the glyphs to insert. */
5338 shift_by_width = 0;
5339 for (glyph = start; glyph < start + len; ++glyph)
5340 shift_by_width += glyph->pixel_width;
5342 /* Get the width of the region to shift right. */
5343 shifted_region_width = (window_box_width (w, updated_area)
5344 - output_cursor.x
5345 - shift_by_width);
5347 /* Shift right. */
5348 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5349 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5350 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5351 f->output_data.x->normal_gc,
5352 frame_x, frame_y,
5353 shifted_region_width, line_height,
5354 frame_x + shift_by_width, frame_y);
5356 /* Write the glyphs. */
5357 hpos = start - row->glyphs[updated_area];
5358 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5359 DRAW_NORMAL_TEXT, 0);
5361 /* Advance the output cursor. */
5362 output_cursor.hpos += len;
5363 output_cursor.x += shift_by_width;
5364 UNBLOCK_INPUT;
5368 /* Delete N glyphs at the nominal cursor position. Not implemented
5369 for X frames. */
5371 static void
5372 x_delete_glyphs (n)
5373 register int n;
5375 abort ();
5379 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5380 If they are <= 0, this is probably an error. */
5382 void
5383 x_clear_area (dpy, window, x, y, width, height, exposures)
5384 Display *dpy;
5385 Window window;
5386 int x, y;
5387 int width, height;
5388 int exposures;
5390 xassert (width > 0 && height > 0);
5391 XClearArea (dpy, window, x, y, width, height, exposures);
5395 /* Erase the current text line from the nominal cursor position
5396 (inclusive) to pixel column TO_X (exclusive). The idea is that
5397 everything from TO_X onward is already erased.
5399 TO_X is a pixel position relative to updated_area of
5400 updated_window. TO_X == -1 means clear to the end of this area. */
5402 static void
5403 x_clear_end_of_line (to_x)
5404 int to_x;
5406 struct frame *f;
5407 struct window *w = updated_window;
5408 int max_x, min_y, max_y;
5409 int from_x, from_y, to_y;
5411 xassert (updated_window && updated_row);
5412 f = XFRAME (w->frame);
5414 if (updated_row->full_width_p)
5416 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5417 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5418 && !w->pseudo_window_p)
5419 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5421 else
5422 max_x = window_box_width (w, updated_area);
5423 max_y = window_text_bottom_y (w);
5425 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5426 of window. For TO_X > 0, truncate to end of drawing area. */
5427 if (to_x == 0)
5428 return;
5429 else if (to_x < 0)
5430 to_x = max_x;
5431 else
5432 to_x = min (to_x, max_x);
5434 to_y = min (max_y, output_cursor.y + updated_row->height);
5436 /* Notice if the cursor will be cleared by this operation. */
5437 if (!updated_row->full_width_p)
5438 notice_overwritten_cursor (w, updated_area,
5439 output_cursor.x, -1,
5440 updated_row->y,
5441 MATRIX_ROW_BOTTOM_Y (updated_row));
5443 from_x = output_cursor.x;
5445 /* Translate to frame coordinates. */
5446 if (updated_row->full_width_p)
5448 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5449 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5451 else
5453 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5454 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5457 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5458 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5459 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5461 /* Prevent inadvertently clearing to end of the X window. */
5462 if (to_x > from_x && to_y > from_y)
5464 BLOCK_INPUT;
5465 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5466 from_x, from_y, to_x - from_x, to_y - from_y,
5467 False);
5468 UNBLOCK_INPUT;
5473 /* Clear entire frame. If updating_frame is non-null, clear that
5474 frame. Otherwise clear the selected frame. */
5476 static void
5477 x_clear_frame ()
5479 struct frame *f;
5481 if (updating_frame)
5482 f = updating_frame;
5483 else
5484 f = SELECTED_FRAME ();
5486 /* Clearing the frame will erase any cursor, so mark them all as no
5487 longer visible. */
5488 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5489 output_cursor.hpos = output_cursor.vpos = 0;
5490 output_cursor.x = -1;
5492 /* We don't set the output cursor here because there will always
5493 follow an explicit cursor_to. */
5494 BLOCK_INPUT;
5495 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5497 /* We have to clear the scroll bars, too. If we have changed
5498 colors or something like that, then they should be notified. */
5499 x_scroll_bar_clear (f);
5501 XFlush (FRAME_X_DISPLAY (f));
5502 UNBLOCK_INPUT;
5507 /* Invert the middle quarter of the frame for .15 sec. */
5509 /* We use the select system call to do the waiting, so we have to make
5510 sure it's available. If it isn't, we just won't do visual bells. */
5512 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5515 /* Subtract the `struct timeval' values X and Y, storing the result in
5516 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5518 static int
5519 timeval_subtract (result, x, y)
5520 struct timeval *result, x, y;
5522 /* Perform the carry for the later subtraction by updating y. This
5523 is safer because on some systems the tv_sec member is unsigned. */
5524 if (x.tv_usec < y.tv_usec)
5526 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5527 y.tv_usec -= 1000000 * nsec;
5528 y.tv_sec += nsec;
5531 if (x.tv_usec - y.tv_usec > 1000000)
5533 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5534 y.tv_usec += 1000000 * nsec;
5535 y.tv_sec -= nsec;
5538 /* Compute the time remaining to wait. tv_usec is certainly
5539 positive. */
5540 result->tv_sec = x.tv_sec - y.tv_sec;
5541 result->tv_usec = x.tv_usec - y.tv_usec;
5543 /* Return indication of whether the result should be considered
5544 negative. */
5545 return x.tv_sec < y.tv_sec;
5548 void
5549 XTflash (f)
5550 struct frame *f;
5552 BLOCK_INPUT;
5555 GC gc;
5557 /* Create a GC that will use the GXxor function to flip foreground
5558 pixels into background pixels. */
5560 XGCValues values;
5562 values.function = GXxor;
5563 values.foreground = (f->output_data.x->foreground_pixel
5564 ^ f->output_data.x->background_pixel);
5566 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5567 GCFunction | GCForeground, &values);
5571 /* Get the height not including a menu bar widget. */
5572 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5573 /* Height of each line to flash. */
5574 int flash_height = FRAME_LINE_HEIGHT (f);
5575 /* These will be the left and right margins of the rectangles. */
5576 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5577 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5579 int width;
5581 /* Don't flash the area between a scroll bar and the frame
5582 edge it is next to. */
5583 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5585 case vertical_scroll_bar_left:
5586 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5587 break;
5589 case vertical_scroll_bar_right:
5590 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5591 break;
5593 default:
5594 break;
5597 width = flash_right - flash_left;
5599 /* If window is tall, flash top and bottom line. */
5600 if (height > 3 * FRAME_LINE_HEIGHT (f))
5602 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5603 flash_left,
5604 (FRAME_INTERNAL_BORDER_WIDTH (f)
5605 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5606 width, flash_height);
5607 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5608 flash_left,
5609 (height - flash_height
5610 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5611 width, flash_height);
5613 else
5614 /* If it is short, flash it all. */
5615 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5616 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5617 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5619 x_flush (f);
5622 struct timeval wakeup;
5624 EMACS_GET_TIME (wakeup);
5626 /* Compute time to wait until, propagating carry from usecs. */
5627 wakeup.tv_usec += 150000;
5628 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5629 wakeup.tv_usec %= 1000000;
5631 /* Keep waiting until past the time wakeup or any input gets
5632 available. */
5633 while (! detect_input_pending ())
5635 struct timeval current;
5636 struct timeval timeout;
5638 EMACS_GET_TIME (current);
5640 /* Break if result would be negative. */
5641 if (timeval_subtract (&current, wakeup, current))
5642 break;
5644 /* How long `select' should wait. */
5645 timeout.tv_sec = 0;
5646 timeout.tv_usec = 10000;
5648 /* Try to wait that long--but we might wake up sooner. */
5649 select (0, NULL, NULL, NULL, &timeout);
5653 /* If window is tall, flash top and bottom line. */
5654 if (height > 3 * FRAME_LINE_HEIGHT (f))
5656 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5657 flash_left,
5658 (FRAME_INTERNAL_BORDER_WIDTH (f)
5659 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5660 width, flash_height);
5661 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5662 flash_left,
5663 (height - flash_height
5664 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5665 width, flash_height);
5667 else
5668 /* If it is short, flash it all. */
5669 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5670 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5671 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5673 XFreeGC (FRAME_X_DISPLAY (f), gc);
5674 x_flush (f);
5678 UNBLOCK_INPUT;
5681 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5684 /* Make audible bell. */
5686 void
5687 XTring_bell ()
5689 struct frame *f = SELECTED_FRAME ();
5691 if (FRAME_X_DISPLAY (f))
5693 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5694 if (visible_bell)
5695 XTflash (f);
5696 else
5697 #endif
5699 BLOCK_INPUT;
5700 XBell (FRAME_X_DISPLAY (f), 0);
5701 XFlush (FRAME_X_DISPLAY (f));
5702 UNBLOCK_INPUT;
5708 /* Specify how many text lines, from the top of the window,
5709 should be affected by insert-lines and delete-lines operations.
5710 This, and those operations, are used only within an update
5711 that is bounded by calls to x_update_begin and x_update_end. */
5713 static void
5714 XTset_terminal_window (n)
5715 register int n;
5717 /* This function intentionally left blank. */
5722 /***********************************************************************
5723 Line Dance
5724 ***********************************************************************/
5726 /* Perform an insert-lines or delete-lines operation, inserting N
5727 lines or deleting -N lines at vertical position VPOS. */
5729 static void
5730 x_ins_del_lines (vpos, n)
5731 int vpos, n;
5733 abort ();
5737 /* Scroll part of the display as described by RUN. */
5739 static void
5740 x_scroll_run (w, run)
5741 struct window *w;
5742 struct run *run;
5744 struct frame *f = XFRAME (w->frame);
5745 int x, y, width, height, from_y, to_y, bottom_y;
5747 /* Get frame-relative bounding box of the text display area of W,
5748 without mode lines. Include in this box the left and right
5749 fringe of W. */
5750 window_box (w, -1, &x, &y, &width, &height);
5751 width += FRAME_X_FRINGE_WIDTH (f);
5752 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5754 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5755 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5756 bottom_y = y + height;
5758 if (to_y < from_y)
5760 /* Scrolling up. Make sure we don't copy part of the mode
5761 line at the bottom. */
5762 if (from_y + run->height > bottom_y)
5763 height = bottom_y - from_y;
5764 else
5765 height = run->height;
5767 else
5769 /* Scolling down. Make sure we don't copy over the mode line.
5770 at the bottom. */
5771 if (to_y + run->height > bottom_y)
5772 height = bottom_y - to_y;
5773 else
5774 height = run->height;
5777 BLOCK_INPUT;
5779 /* Cursor off. Will be switched on again in x_update_window_end. */
5780 updated_window = w;
5781 x_clear_cursor (w);
5783 XCopyArea (FRAME_X_DISPLAY (f),
5784 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5785 f->output_data.x->normal_gc,
5786 x, from_y,
5787 width, height,
5788 x, to_y);
5790 UNBLOCK_INPUT;
5795 /***********************************************************************
5796 Exposure Events
5797 ***********************************************************************/
5799 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5800 corner of the exposed rectangle. W and H are width and height of
5801 the exposed area. All are pixel values. W or H zero means redraw
5802 the entire frame. */
5804 static void
5805 expose_frame (f, x, y, w, h)
5806 struct frame *f;
5807 int x, y, w, h;
5809 XRectangle r;
5810 int mouse_face_overwritten_p = 0;
5812 TRACE ((stderr, "expose_frame "));
5814 /* No need to redraw if frame will be redrawn soon. */
5815 if (FRAME_GARBAGED_P (f))
5817 TRACE ((stderr, " garbaged\n"));
5818 return;
5821 /* If basic faces haven't been realized yet, there is no point in
5822 trying to redraw anything. This can happen when we get an expose
5823 event while Emacs is starting, e.g. by moving another window. */
5824 if (FRAME_FACE_CACHE (f) == NULL
5825 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5827 TRACE ((stderr, " no faces\n"));
5828 return;
5831 if (w == 0 || h == 0)
5833 r.x = r.y = 0;
5834 r.width = CANON_X_UNIT (f) * f->width;
5835 r.height = CANON_Y_UNIT (f) * f->height;
5837 else
5839 r.x = x;
5840 r.y = y;
5841 r.width = w;
5842 r.height = h;
5845 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5846 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5848 if (WINDOWP (f->tool_bar_window))
5849 mouse_face_overwritten_p
5850 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5852 #ifndef USE_X_TOOLKIT
5853 if (WINDOWP (f->menu_bar_window))
5854 mouse_face_overwritten_p
5855 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5856 #endif /* not USE_X_TOOLKIT */
5858 /* Some window managers support a focus-follows-mouse style with
5859 delayed raising of frames. Imagine a partially obscured frame,
5860 and moving the mouse into partially obscured mouse-face on that
5861 frame. The visible part of the mouse-face will be highlighted,
5862 then the WM raises the obscured frame. With at least one WM, KDE
5863 2.1, Emacs is not getting any event for the raising of the frame
5864 (even tried with SubstructureRedirectMask), only Expose events.
5865 These expose events will draw text normally, i.e. not
5866 highlighted. Which means we must redo the highlight here.
5867 Subsume it under ``we love X''. --gerd 2001-08-15 */
5868 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5870 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5871 if (f == dpyinfo->mouse_face_mouse_frame)
5873 int x = dpyinfo->mouse_face_mouse_x;
5874 int y = dpyinfo->mouse_face_mouse_y;
5875 clear_mouse_face (dpyinfo);
5876 note_mouse_highlight (f, x, y);
5882 /* Redraw (parts) of all windows in the window tree rooted at W that
5883 intersect R. R contains frame pixel coordinates. Value is
5884 non-zero if the exposure overwrites mouse-face. */
5886 static int
5887 expose_window_tree (w, r)
5888 struct window *w;
5889 XRectangle *r;
5891 struct frame *f = XFRAME (w->frame);
5892 int mouse_face_overwritten_p = 0;
5894 while (w && !FRAME_GARBAGED_P (f))
5896 if (!NILP (w->hchild))
5897 mouse_face_overwritten_p
5898 |= expose_window_tree (XWINDOW (w->hchild), r);
5899 else if (!NILP (w->vchild))
5900 mouse_face_overwritten_p
5901 |= expose_window_tree (XWINDOW (w->vchild), r);
5902 else
5903 mouse_face_overwritten_p |= expose_window (w, r);
5905 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5908 return mouse_face_overwritten_p;
5912 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5913 which intersects rectangle R. R is in window-relative coordinates. */
5915 static void
5916 expose_area (w, row, r, area)
5917 struct window *w;
5918 struct glyph_row *row;
5919 XRectangle *r;
5920 enum glyph_row_area area;
5922 struct glyph *first = row->glyphs[area];
5923 struct glyph *end = row->glyphs[area] + row->used[area];
5924 struct glyph *last;
5925 int first_x, start_x, x;
5927 if (area == TEXT_AREA && row->fill_line_p)
5928 /* If row extends face to end of line write the whole line. */
5929 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5930 DRAW_NORMAL_TEXT, 0);
5931 else
5933 /* Set START_X to the window-relative start position for drawing glyphs of
5934 AREA. The first glyph of the text area can be partially visible.
5935 The first glyphs of other areas cannot. */
5936 if (area == LEFT_MARGIN_AREA)
5937 start_x = 0;
5938 else if (area == TEXT_AREA)
5939 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5940 else
5941 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5942 + window_box_width (w, TEXT_AREA));
5943 x = start_x;
5945 /* Find the first glyph that must be redrawn. */
5946 while (first < end
5947 && x + first->pixel_width < r->x)
5949 x += first->pixel_width;
5950 ++first;
5953 /* Find the last one. */
5954 last = first;
5955 first_x = x;
5956 while (last < end
5957 && x < r->x + r->width)
5959 x += last->pixel_width;
5960 ++last;
5963 /* Repaint. */
5964 if (last > first)
5965 x_draw_glyphs (w, first_x - start_x, row, area,
5966 first - row->glyphs[area],
5967 last - row->glyphs[area],
5968 DRAW_NORMAL_TEXT, 0);
5973 /* Redraw the parts of the glyph row ROW on window W intersecting
5974 rectangle R. R is in window-relative coordinates. Value is
5975 non-zero if mouse-face was overwritten. */
5977 static int
5978 expose_line (w, row, r)
5979 struct window *w;
5980 struct glyph_row *row;
5981 XRectangle *r;
5983 xassert (row->enabled_p);
5985 if (row->mode_line_p || w->pseudo_window_p)
5986 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5987 DRAW_NORMAL_TEXT, 0);
5988 else
5990 if (row->used[LEFT_MARGIN_AREA])
5991 expose_area (w, row, r, LEFT_MARGIN_AREA);
5992 if (row->used[TEXT_AREA])
5993 expose_area (w, row, r, TEXT_AREA);
5994 if (row->used[RIGHT_MARGIN_AREA])
5995 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5996 x_draw_row_fringe_bitmaps (w, row);
5999 return row->mouse_face_p;
6003 /* Return non-zero if W's cursor intersects rectangle R. */
6005 static int
6006 x_phys_cursor_in_rect_p (w, r)
6007 struct window *w;
6008 XRectangle *r;
6010 XRectangle cr, result;
6011 struct glyph *cursor_glyph;
6013 cursor_glyph = get_phys_cursor_glyph (w);
6014 if (cursor_glyph)
6016 cr.x = w->phys_cursor.x;
6017 cr.y = w->phys_cursor.y;
6018 cr.width = cursor_glyph->pixel_width;
6019 cr.height = w->phys_cursor_height;
6020 return x_intersect_rectangles (&cr, r, &result);
6022 else
6023 return 0;
6027 /* Redraw the part of window W intersection rectangle FR. Pixel
6028 coordinates in FR are frame-relative. Call this function with
6029 input blocked. Value is non-zero if the exposure overwrites
6030 mouse-face. */
6032 static int
6033 expose_window (w, fr)
6034 struct window *w;
6035 XRectangle *fr;
6037 struct frame *f = XFRAME (w->frame);
6038 XRectangle wr, r;
6039 int mouse_face_overwritten_p = 0;
6041 /* If window is not yet fully initialized, do nothing. This can
6042 happen when toolkit scroll bars are used and a window is split.
6043 Reconfiguring the scroll bar will generate an expose for a newly
6044 created window. */
6045 if (w->current_matrix == NULL)
6046 return 0;
6048 /* When we're currently updating the window, display and current
6049 matrix usually don't agree. Arrange for a thorough display
6050 later. */
6051 if (w == updated_window)
6053 SET_FRAME_GARBAGED (f);
6054 return 0;
6057 /* Frame-relative pixel rectangle of W. */
6058 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6059 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6060 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6061 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6063 if (x_intersect_rectangles (fr, &wr, &r))
6065 int yb = window_text_bottom_y (w);
6066 struct glyph_row *row;
6067 int cursor_cleared_p;
6069 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6070 r.x, r.y, r.width, r.height));
6072 /* Convert to window coordinates. */
6073 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6074 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6076 /* Turn off the cursor. */
6077 if (!w->pseudo_window_p
6078 && x_phys_cursor_in_rect_p (w, &r))
6080 x_clear_cursor (w);
6081 cursor_cleared_p = 1;
6083 else
6084 cursor_cleared_p = 0;
6086 /* Find the first row intersecting the rectangle R. */
6087 for (row = w->current_matrix->rows;
6088 row->enabled_p;
6089 ++row)
6091 int y0 = row->y;
6092 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6094 if ((y0 >= r.y && y0 < r.y + r.height)
6095 || (y1 > r.y && y1 < r.y + r.height)
6096 || (r.y >= y0 && r.y < y1)
6097 || (r.y + r.height > y0 && r.y + r.height < y1))
6099 if (expose_line (w, row, &r))
6100 mouse_face_overwritten_p = 1;
6103 if (y1 >= yb)
6104 break;
6107 /* Display the mode line if there is one. */
6108 if (WINDOW_WANTS_MODELINE_P (w)
6109 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6110 row->enabled_p)
6111 && row->y < r.y + r.height)
6113 if (expose_line (w, row, &r))
6114 mouse_face_overwritten_p = 1;
6117 if (!w->pseudo_window_p)
6119 /* Draw border between windows. */
6120 x_draw_vertical_border (w);
6122 /* Turn the cursor on again. */
6123 if (cursor_cleared_p)
6124 x_update_window_cursor (w, 1);
6128 return mouse_face_overwritten_p;
6132 /* Determine the intersection of two rectangles R1 and R2. Return
6133 the intersection in *RESULT. Value is non-zero if RESULT is not
6134 empty. */
6136 static int
6137 x_intersect_rectangles (r1, r2, result)
6138 XRectangle *r1, *r2, *result;
6140 XRectangle *left, *right;
6141 XRectangle *upper, *lower;
6142 int intersection_p = 0;
6144 /* Rearrange so that R1 is the left-most rectangle. */
6145 if (r1->x < r2->x)
6146 left = r1, right = r2;
6147 else
6148 left = r2, right = r1;
6150 /* X0 of the intersection is right.x0, if this is inside R1,
6151 otherwise there is no intersection. */
6152 if (right->x <= left->x + left->width)
6154 result->x = right->x;
6156 /* The right end of the intersection is the minimum of the
6157 the right ends of left and right. */
6158 result->width = (min (left->x + left->width, right->x + right->width)
6159 - result->x);
6161 /* Same game for Y. */
6162 if (r1->y < r2->y)
6163 upper = r1, lower = r2;
6164 else
6165 upper = r2, lower = r1;
6167 /* The upper end of the intersection is lower.y0, if this is inside
6168 of upper. Otherwise, there is no intersection. */
6169 if (lower->y <= upper->y + upper->height)
6171 result->y = lower->y;
6173 /* The lower end of the intersection is the minimum of the lower
6174 ends of upper and lower. */
6175 result->height = (min (lower->y + lower->height,
6176 upper->y + upper->height)
6177 - result->y);
6178 intersection_p = 1;
6182 return intersection_p;
6189 static void
6190 frame_highlight (f)
6191 struct frame *f;
6193 /* We used to only do this if Vx_no_window_manager was non-nil, but
6194 the ICCCM (section 4.1.6) says that the window's border pixmap
6195 and border pixel are window attributes which are "private to the
6196 client", so we can always change it to whatever we want. */
6197 BLOCK_INPUT;
6198 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6199 f->output_data.x->border_pixel);
6200 UNBLOCK_INPUT;
6201 x_update_cursor (f, 1);
6204 static void
6205 frame_unhighlight (f)
6206 struct frame *f;
6208 /* We used to only do this if Vx_no_window_manager was non-nil, but
6209 the ICCCM (section 4.1.6) says that the window's border pixmap
6210 and border pixel are window attributes which are "private to the
6211 client", so we can always change it to whatever we want. */
6212 BLOCK_INPUT;
6213 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6214 f->output_data.x->border_tile);
6215 UNBLOCK_INPUT;
6216 x_update_cursor (f, 1);
6219 /* The focus has changed. Update the frames as necessary to reflect
6220 the new situation. Note that we can't change the selected frame
6221 here, because the Lisp code we are interrupting might become confused.
6222 Each event gets marked with the frame in which it occurred, so the
6223 Lisp code can tell when the switch took place by examining the events. */
6225 static void
6226 x_new_focus_frame (dpyinfo, frame)
6227 struct x_display_info *dpyinfo;
6228 struct frame *frame;
6230 struct frame *old_focus = dpyinfo->x_focus_frame;
6232 if (frame != dpyinfo->x_focus_frame)
6234 /* Set this before calling other routines, so that they see
6235 the correct value of x_focus_frame. */
6236 dpyinfo->x_focus_frame = frame;
6238 if (old_focus && old_focus->auto_lower)
6239 x_lower_frame (old_focus);
6241 #if 0
6242 selected_frame = frame;
6243 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6244 selected_frame);
6245 Fselect_window (selected_frame->selected_window);
6246 choose_minibuf_frame ();
6247 #endif /* ! 0 */
6249 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6250 pending_autoraise_frame = dpyinfo->x_focus_frame;
6251 else
6252 pending_autoraise_frame = 0;
6255 x_frame_rehighlight (dpyinfo);
6258 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6260 void
6261 x_mouse_leave (dpyinfo)
6262 struct x_display_info *dpyinfo;
6264 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6267 /* The focus has changed, or we have redirected a frame's focus to
6268 another frame (this happens when a frame uses a surrogate
6269 mini-buffer frame). Shift the highlight as appropriate.
6271 The FRAME argument doesn't necessarily have anything to do with which
6272 frame is being highlighted or un-highlighted; we only use it to find
6273 the appropriate X display info. */
6275 static void
6276 XTframe_rehighlight (frame)
6277 struct frame *frame;
6279 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6282 static void
6283 x_frame_rehighlight (dpyinfo)
6284 struct x_display_info *dpyinfo;
6286 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6288 if (dpyinfo->x_focus_frame)
6290 dpyinfo->x_highlight_frame
6291 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6292 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6293 : dpyinfo->x_focus_frame);
6294 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6296 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6297 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6300 else
6301 dpyinfo->x_highlight_frame = 0;
6303 if (dpyinfo->x_highlight_frame != old_highlight)
6305 if (old_highlight)
6306 frame_unhighlight (old_highlight);
6307 if (dpyinfo->x_highlight_frame)
6308 frame_highlight (dpyinfo->x_highlight_frame);
6314 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6316 /* Initialize mode_switch_bit and modifier_meaning. */
6317 static void
6318 x_find_modifier_meanings (dpyinfo)
6319 struct x_display_info *dpyinfo;
6321 int min_code, max_code;
6322 KeySym *syms;
6323 int syms_per_code;
6324 XModifierKeymap *mods;
6326 dpyinfo->meta_mod_mask = 0;
6327 dpyinfo->shift_lock_mask = 0;
6328 dpyinfo->alt_mod_mask = 0;
6329 dpyinfo->super_mod_mask = 0;
6330 dpyinfo->hyper_mod_mask = 0;
6332 #ifdef HAVE_X11R4
6333 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6334 #else
6335 min_code = dpyinfo->display->min_keycode;
6336 max_code = dpyinfo->display->max_keycode;
6337 #endif
6339 syms = XGetKeyboardMapping (dpyinfo->display,
6340 min_code, max_code - min_code + 1,
6341 &syms_per_code);
6342 mods = XGetModifierMapping (dpyinfo->display);
6344 /* Scan the modifier table to see which modifier bits the Meta and
6345 Alt keysyms are on. */
6347 int row, col; /* The row and column in the modifier table. */
6349 for (row = 3; row < 8; row++)
6350 for (col = 0; col < mods->max_keypermod; col++)
6352 KeyCode code
6353 = mods->modifiermap[(row * mods->max_keypermod) + col];
6355 /* Zeroes are used for filler. Skip them. */
6356 if (code == 0)
6357 continue;
6359 /* Are any of this keycode's keysyms a meta key? */
6361 int code_col;
6363 for (code_col = 0; code_col < syms_per_code; code_col++)
6365 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6367 switch (sym)
6369 case XK_Meta_L:
6370 case XK_Meta_R:
6371 dpyinfo->meta_mod_mask |= (1 << row);
6372 break;
6374 case XK_Alt_L:
6375 case XK_Alt_R:
6376 dpyinfo->alt_mod_mask |= (1 << row);
6377 break;
6379 case XK_Hyper_L:
6380 case XK_Hyper_R:
6381 dpyinfo->hyper_mod_mask |= (1 << row);
6382 break;
6384 case XK_Super_L:
6385 case XK_Super_R:
6386 dpyinfo->super_mod_mask |= (1 << row);
6387 break;
6389 case XK_Shift_Lock:
6390 /* Ignore this if it's not on the lock modifier. */
6391 if ((1 << row) == LockMask)
6392 dpyinfo->shift_lock_mask = LockMask;
6393 break;
6400 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6401 if (! dpyinfo->meta_mod_mask)
6403 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6404 dpyinfo->alt_mod_mask = 0;
6407 /* If some keys are both alt and meta,
6408 make them just meta, not alt. */
6409 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6411 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6414 XFree ((char *) syms);
6415 XFreeModifiermap (mods);
6418 /* Convert between the modifier bits X uses and the modifier bits
6419 Emacs uses. */
6421 static unsigned int
6422 x_x_to_emacs_modifiers (dpyinfo, state)
6423 struct x_display_info *dpyinfo;
6424 unsigned int state;
6426 EMACS_UINT mod_meta = meta_modifier;
6427 EMACS_UINT mod_alt = alt_modifier;
6428 EMACS_UINT mod_hyper = hyper_modifier;
6429 EMACS_UINT mod_super = super_modifier;
6430 Lisp_Object tem;
6432 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6433 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6434 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6435 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6436 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6437 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6438 tem = Fget (Vx_super_keysym, Qmodifier_value);
6439 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6442 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6443 | ((state & ControlMask) ? ctrl_modifier : 0)
6444 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
6445 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
6446 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
6447 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
6450 static unsigned int
6451 x_emacs_to_x_modifiers (dpyinfo, state)
6452 struct x_display_info *dpyinfo;
6453 unsigned int state;
6455 EMACS_UINT mod_meta = meta_modifier;
6456 EMACS_UINT mod_alt = alt_modifier;
6457 EMACS_UINT mod_hyper = hyper_modifier;
6458 EMACS_UINT mod_super = super_modifier;
6460 Lisp_Object tem;
6462 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6463 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6464 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6465 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6466 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6467 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6468 tem = Fget (Vx_super_keysym, Qmodifier_value);
6469 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6472 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
6473 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
6474 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
6475 | ((state & shift_modifier) ? ShiftMask : 0)
6476 | ((state & ctrl_modifier) ? ControlMask : 0)
6477 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
6480 /* Convert a keysym to its name. */
6482 char *
6483 x_get_keysym_name (keysym)
6484 KeySym keysym;
6486 char *value;
6488 BLOCK_INPUT;
6489 value = XKeysymToString (keysym);
6490 UNBLOCK_INPUT;
6492 return value;
6497 /* Mouse clicks and mouse movement. Rah. */
6499 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6500 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6501 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6502 not force the value into range. */
6504 void
6505 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6506 FRAME_PTR f;
6507 register int pix_x, pix_y;
6508 register int *x, *y;
6509 XRectangle *bounds;
6510 int noclip;
6512 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6513 even for negative values. */
6514 if (pix_x < 0)
6515 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6516 if (pix_y < 0)
6517 pix_y -= (f)->output_data.x->line_height - 1;
6519 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6520 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6522 if (bounds)
6524 bounds->width = FONT_WIDTH (f->output_data.x->font);
6525 bounds->height = f->output_data.x->line_height;
6526 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6527 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6530 if (!noclip)
6532 if (pix_x < 0)
6533 pix_x = 0;
6534 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6535 pix_x = FRAME_WINDOW_WIDTH (f);
6537 if (pix_y < 0)
6538 pix_y = 0;
6539 else if (pix_y > f->height)
6540 pix_y = f->height;
6543 *x = pix_x;
6544 *y = pix_y;
6548 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6549 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6550 can't tell the positions because W's display is not up to date,
6551 return 0. */
6554 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6555 struct window *w;
6556 int hpos, vpos;
6557 int *frame_x, *frame_y;
6559 int success_p;
6561 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6562 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6564 if (display_completed)
6566 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6567 struct glyph *glyph = row->glyphs[TEXT_AREA];
6568 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6570 *frame_y = row->y;
6571 *frame_x = row->x;
6572 while (glyph < end)
6574 *frame_x += glyph->pixel_width;
6575 ++glyph;
6578 success_p = 1;
6580 else
6582 *frame_y = *frame_x = 0;
6583 success_p = 0;
6586 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6587 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6588 return success_p;
6592 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6594 If the event is a button press, then note that we have grabbed
6595 the mouse. */
6597 static Lisp_Object
6598 construct_mouse_click (result, event, f)
6599 struct input_event *result;
6600 XButtonEvent *event;
6601 struct frame *f;
6603 /* Make the event type no_event; we'll change that when we decide
6604 otherwise. */
6605 result->kind = mouse_click;
6606 result->code = event->button - Button1;
6607 result->timestamp = event->time;
6608 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6609 event->state)
6610 | (event->type == ButtonRelease
6611 ? up_modifier
6612 : down_modifier));
6614 XSETINT (result->x, event->x);
6615 XSETINT (result->y, event->y);
6616 XSETFRAME (result->frame_or_window, f);
6617 result->arg = Qnil;
6618 return Qnil;
6622 /* Function to report a mouse movement to the mainstream Emacs code.
6623 The input handler calls this.
6625 We have received a mouse movement event, which is given in *event.
6626 If the mouse is over a different glyph than it was last time, tell
6627 the mainstream emacs code by setting mouse_moved. If not, ask for
6628 another motion event, so we can check again the next time it moves. */
6630 static XMotionEvent last_mouse_motion_event;
6631 static Lisp_Object last_mouse_motion_frame;
6633 static void
6634 note_mouse_movement (frame, event)
6635 FRAME_PTR frame;
6636 XMotionEvent *event;
6638 last_mouse_movement_time = event->time;
6639 last_mouse_motion_event = *event;
6640 XSETFRAME (last_mouse_motion_frame, frame);
6642 if (x_autoselect_window_p)
6644 int area;
6645 Lisp_Object window;
6646 static Lisp_Object last_window;
6648 window = window_from_coordinates (frame, event->x, event->y, &area, 0);
6650 /* Window will be selected only when it is not selected now and
6651 last mouse movement event was not in it. Minubuffer window
6652 will be selected iff it is active. */
6653 if (!EQ (window, last_window)
6654 && !EQ (window, selected_window)
6655 && (!MINI_WINDOW_P (XWINDOW (window))
6656 || (EQ (window, minibuf_window) && minibuf_level > 0)))
6657 Fselect_window (window);
6659 last_window=window;
6662 if (event->window != FRAME_X_WINDOW (frame))
6664 frame->mouse_moved = 1;
6665 last_mouse_scroll_bar = Qnil;
6666 note_mouse_highlight (frame, -1, -1);
6669 /* Has the mouse moved off the glyph it was on at the last sighting? */
6670 else if (event->x < last_mouse_glyph.x
6671 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6672 || event->y < last_mouse_glyph.y
6673 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6675 frame->mouse_moved = 1;
6676 last_mouse_scroll_bar = Qnil;
6677 note_mouse_highlight (frame, event->x, event->y);
6682 /************************************************************************
6683 Mouse Face
6684 ************************************************************************/
6686 /* Find the glyph under window-relative coordinates X/Y in window W.
6687 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6688 strings. Return in *HPOS and *VPOS the row and column number of
6689 the glyph found. Return in *AREA the glyph area containing X.
6690 Value is a pointer to the glyph found or null if X/Y is not on
6691 text, or we can't tell because W's current matrix is not up to
6692 date. */
6694 static struct glyph *
6695 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6696 struct window *w;
6697 int x, y;
6698 int *hpos, *vpos, *area;
6699 int buffer_only_p;
6701 struct glyph *glyph, *end;
6702 struct glyph_row *row = NULL;
6703 int x0, i, left_area_width;
6705 /* Find row containing Y. Give up if some row is not enabled. */
6706 for (i = 0; i < w->current_matrix->nrows; ++i)
6708 row = MATRIX_ROW (w->current_matrix, i);
6709 if (!row->enabled_p)
6710 return NULL;
6711 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6712 break;
6715 *vpos = i;
6716 *hpos = 0;
6718 /* Give up if Y is not in the window. */
6719 if (i == w->current_matrix->nrows)
6720 return NULL;
6722 /* Get the glyph area containing X. */
6723 if (w->pseudo_window_p)
6725 *area = TEXT_AREA;
6726 x0 = 0;
6728 else
6730 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6731 if (x < left_area_width)
6733 *area = LEFT_MARGIN_AREA;
6734 x0 = 0;
6736 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6738 *area = TEXT_AREA;
6739 x0 = row->x + left_area_width;
6741 else
6743 *area = RIGHT_MARGIN_AREA;
6744 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6748 /* Find glyph containing X. */
6749 glyph = row->glyphs[*area];
6750 end = glyph + row->used[*area];
6751 while (glyph < end)
6753 if (x < x0 + glyph->pixel_width)
6755 if (w->pseudo_window_p)
6756 break;
6757 else if (!buffer_only_p || BUFFERP (glyph->object))
6758 break;
6761 x0 += glyph->pixel_width;
6762 ++glyph;
6765 if (glyph == end)
6766 return NULL;
6768 *hpos = glyph - row->glyphs[*area];
6769 return glyph;
6773 /* Convert frame-relative x/y to coordinates relative to window W.
6774 Takes pseudo-windows into account. */
6776 static void
6777 frame_to_window_pixel_xy (w, x, y)
6778 struct window *w;
6779 int *x, *y;
6781 if (w->pseudo_window_p)
6783 /* A pseudo-window is always full-width, and starts at the
6784 left edge of the frame, plus a frame border. */
6785 struct frame *f = XFRAME (w->frame);
6786 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6787 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6789 else
6791 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6792 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6797 /* Take proper action when mouse has moved to the mode or header line of
6798 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6799 mode line. X is relative to the start of the text display area of
6800 W, so the width of fringes and scroll bars must be subtracted
6801 to get a position relative to the start of the mode line. */
6803 static void
6804 note_mode_line_highlight (w, x, mode_line_p)
6805 struct window *w;
6806 int x, mode_line_p;
6808 struct frame *f = XFRAME (w->frame);
6809 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6810 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6811 struct glyph_row *row;
6813 if (mode_line_p)
6814 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6815 else
6816 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6818 if (row->enabled_p)
6820 struct glyph *glyph, *end;
6821 Lisp_Object help, map;
6822 int x0;
6824 /* Find the glyph under X. */
6825 glyph = row->glyphs[TEXT_AREA];
6826 end = glyph + row->used[TEXT_AREA];
6827 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6828 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6830 while (glyph < end
6831 && x >= x0 + glyph->pixel_width)
6833 x0 += glyph->pixel_width;
6834 ++glyph;
6837 if (glyph < end
6838 && STRINGP (glyph->object)
6839 && XSTRING (glyph->object)->intervals
6840 && glyph->charpos >= 0
6841 && glyph->charpos < XSTRING (glyph->object)->size)
6843 /* If we're on a string with `help-echo' text property,
6844 arrange for the help to be displayed. This is done by
6845 setting the global variable help_echo to the help string. */
6846 help = Fget_text_property (make_number (glyph->charpos),
6847 Qhelp_echo, glyph->object);
6848 if (!NILP (help))
6850 help_echo = help;
6851 XSETWINDOW (help_echo_window, w);
6852 help_echo_object = glyph->object;
6853 help_echo_pos = glyph->charpos;
6856 /* Change the mouse pointer according to what is under X/Y. */
6857 map = Fget_text_property (make_number (glyph->charpos),
6858 Qlocal_map, glyph->object);
6859 if (KEYMAPP (map))
6860 cursor = f->output_data.x->nontext_cursor;
6861 else
6863 map = Fget_text_property (make_number (glyph->charpos),
6864 Qkeymap, glyph->object);
6865 if (KEYMAPP (map))
6866 cursor = f->output_data.x->nontext_cursor;
6871 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6875 /* Take proper action when the mouse has moved to position X, Y on
6876 frame F as regards highlighting characters that have mouse-face
6877 properties. Also de-highlighting chars where the mouse was before.
6878 X and Y can be negative or out of range. */
6880 static void
6881 note_mouse_highlight (f, x, y)
6882 struct frame *f;
6883 int x, y;
6885 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6886 int portion;
6887 Lisp_Object window;
6888 struct window *w;
6889 Cursor cursor = None;
6890 struct buffer *b;
6892 /* When a menu is active, don't highlight because this looks odd. */
6893 #ifdef USE_X_TOOLKIT
6894 if (popup_activated ())
6895 return;
6896 #endif
6898 if (NILP (Vmouse_highlight)
6899 || !f->glyphs_initialized_p)
6900 return;
6902 dpyinfo->mouse_face_mouse_x = x;
6903 dpyinfo->mouse_face_mouse_y = y;
6904 dpyinfo->mouse_face_mouse_frame = f;
6906 if (dpyinfo->mouse_face_defer)
6907 return;
6909 if (gc_in_progress)
6911 dpyinfo->mouse_face_deferred_gc = 1;
6912 return;
6915 /* Which window is that in? */
6916 window = window_from_coordinates (f, x, y, &portion, 1);
6918 /* If we were displaying active text in another window, clear that. */
6919 if (! EQ (window, dpyinfo->mouse_face_window))
6920 clear_mouse_face (dpyinfo);
6922 /* Not on a window -> return. */
6923 if (!WINDOWP (window))
6924 return;
6926 /* Convert to window-relative pixel coordinates. */
6927 w = XWINDOW (window);
6928 frame_to_window_pixel_xy (w, &x, &y);
6930 /* Handle tool-bar window differently since it doesn't display a
6931 buffer. */
6932 if (EQ (window, f->tool_bar_window))
6934 note_tool_bar_highlight (f, x, y);
6935 return;
6938 /* Mouse is on the mode or header line? */
6939 if (portion == 1 || portion == 3)
6941 note_mode_line_highlight (w, x, portion == 1);
6942 return;
6945 if (portion == 2)
6946 cursor = f->output_data.x->horizontal_drag_cursor;
6947 else
6948 cursor = f->output_data.x->text_cursor;
6950 /* Are we in a window whose display is up to date?
6951 And verify the buffer's text has not changed. */
6952 b = XBUFFER (w->buffer);
6953 if (/* Within text portion of the window. */
6954 portion == 0
6955 && EQ (w->window_end_valid, w->buffer)
6956 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6957 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6959 int hpos, vpos, pos, i, area;
6960 struct glyph *glyph;
6961 Lisp_Object object;
6962 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6963 Lisp_Object *overlay_vec = NULL;
6964 int len, noverlays;
6965 struct buffer *obuf;
6966 int obegv, ozv, same_region;
6968 /* Find the glyph under X/Y. */
6969 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6971 /* Clear mouse face if X/Y not over text. */
6972 if (glyph == NULL
6973 || area != TEXT_AREA
6974 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6976 if (clear_mouse_face (dpyinfo))
6977 cursor = None;
6978 goto set_cursor;
6981 pos = glyph->charpos;
6982 object = glyph->object;
6983 if (!STRINGP (object) && !BUFFERP (object))
6984 goto set_cursor;
6986 /* If we get an out-of-range value, return now; avoid an error. */
6987 if (BUFFERP (object) && pos > BUF_Z (b))
6988 goto set_cursor;
6990 /* Make the window's buffer temporarily current for
6991 overlays_at and compute_char_face. */
6992 obuf = current_buffer;
6993 current_buffer = b;
6994 obegv = BEGV;
6995 ozv = ZV;
6996 BEGV = BEG;
6997 ZV = Z;
6999 /* Is this char mouse-active or does it have help-echo? */
7000 position = make_number (pos);
7002 if (BUFFERP (object))
7004 /* Put all the overlays we want in a vector in overlay_vec.
7005 Store the length in len. If there are more than 10, make
7006 enough space for all, and try again. */
7007 len = 10;
7008 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7009 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7010 if (noverlays > len)
7012 len = noverlays;
7013 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7014 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7017 /* Sort overlays into increasing priority order. */
7018 noverlays = sort_overlays (overlay_vec, noverlays, w);
7020 else
7021 noverlays = 0;
7023 same_region = (EQ (window, dpyinfo->mouse_face_window)
7024 && vpos >= dpyinfo->mouse_face_beg_row
7025 && vpos <= dpyinfo->mouse_face_end_row
7026 && (vpos > dpyinfo->mouse_face_beg_row
7027 || hpos >= dpyinfo->mouse_face_beg_col)
7028 && (vpos < dpyinfo->mouse_face_end_row
7029 || hpos < dpyinfo->mouse_face_end_col
7030 || dpyinfo->mouse_face_past_end));
7032 if (same_region)
7033 cursor = None;
7035 /* Check mouse-face highlighting. */
7036 if (! same_region
7037 /* If there exists an overlay with mouse-face overlapping
7038 the one we are currently highlighting, we have to
7039 check if we enter the overlapping overlay, and then
7040 highlight only that. */
7041 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7042 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7044 /* Find the highest priority overlay that has a mouse-face
7045 property. */
7046 overlay = Qnil;
7047 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7049 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7050 if (!NILP (mouse_face))
7051 overlay = overlay_vec[i];
7054 /* If we're actually highlighting the same overlay as
7055 before, there's no need to do that again. */
7056 if (!NILP (overlay)
7057 && EQ (overlay, dpyinfo->mouse_face_overlay))
7058 goto check_help_echo;
7060 dpyinfo->mouse_face_overlay = overlay;
7062 /* Clear the display of the old active region, if any. */
7063 if (clear_mouse_face (dpyinfo))
7064 cursor = None;
7066 /* If no overlay applies, get a text property. */
7067 if (NILP (overlay))
7068 mouse_face = Fget_text_property (position, Qmouse_face, object);
7070 /* Handle the overlay case. */
7071 if (!NILP (overlay))
7073 /* Find the range of text around this char that
7074 should be active. */
7075 Lisp_Object before, after;
7076 int ignore;
7078 before = Foverlay_start (overlay);
7079 after = Foverlay_end (overlay);
7080 /* Record this as the current active region. */
7081 fast_find_position (w, XFASTINT (before),
7082 &dpyinfo->mouse_face_beg_col,
7083 &dpyinfo->mouse_face_beg_row,
7084 &dpyinfo->mouse_face_beg_x,
7085 &dpyinfo->mouse_face_beg_y, Qnil);
7087 dpyinfo->mouse_face_past_end
7088 = !fast_find_position (w, XFASTINT (after),
7089 &dpyinfo->mouse_face_end_col,
7090 &dpyinfo->mouse_face_end_row,
7091 &dpyinfo->mouse_face_end_x,
7092 &dpyinfo->mouse_face_end_y, Qnil);
7093 dpyinfo->mouse_face_window = window;
7094 dpyinfo->mouse_face_face_id
7095 = face_at_buffer_position (w, pos, 0, 0,
7096 &ignore, pos + 1, 1);
7098 /* Display it as active. */
7099 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7100 cursor = None;
7102 /* Handle the text property case. */
7103 else if (!NILP (mouse_face) && BUFFERP (object))
7105 /* Find the range of text around this char that
7106 should be active. */
7107 Lisp_Object before, after, beginning, end;
7108 int ignore;
7110 beginning = Fmarker_position (w->start);
7111 end = make_number (BUF_Z (XBUFFER (object))
7112 - XFASTINT (w->window_end_pos));
7113 before
7114 = Fprevious_single_property_change (make_number (pos + 1),
7115 Qmouse_face,
7116 object, beginning);
7117 after
7118 = Fnext_single_property_change (position, Qmouse_face,
7119 object, end);
7121 /* Record this as the current active region. */
7122 fast_find_position (w, XFASTINT (before),
7123 &dpyinfo->mouse_face_beg_col,
7124 &dpyinfo->mouse_face_beg_row,
7125 &dpyinfo->mouse_face_beg_x,
7126 &dpyinfo->mouse_face_beg_y, Qnil);
7127 dpyinfo->mouse_face_past_end
7128 = !fast_find_position (w, XFASTINT (after),
7129 &dpyinfo->mouse_face_end_col,
7130 &dpyinfo->mouse_face_end_row,
7131 &dpyinfo->mouse_face_end_x,
7132 &dpyinfo->mouse_face_end_y, Qnil);
7133 dpyinfo->mouse_face_window = window;
7135 if (BUFFERP (object))
7136 dpyinfo->mouse_face_face_id
7137 = face_at_buffer_position (w, pos, 0, 0,
7138 &ignore, pos + 1, 1);
7140 /* Display it as active. */
7141 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7142 cursor = None;
7144 else if (!NILP (mouse_face) && STRINGP (object))
7146 Lisp_Object b, e;
7147 int ignore;
7149 b = Fprevious_single_property_change (make_number (pos + 1),
7150 Qmouse_face,
7151 object, Qnil);
7152 e = Fnext_single_property_change (position, Qmouse_face,
7153 object, Qnil);
7154 if (NILP (b))
7155 b = make_number (0);
7156 if (NILP (e))
7157 e = make_number (XSTRING (object)->size - 1);
7158 fast_find_string_pos (w, XINT (b), object,
7159 &dpyinfo->mouse_face_beg_col,
7160 &dpyinfo->mouse_face_beg_row,
7161 &dpyinfo->mouse_face_beg_x,
7162 &dpyinfo->mouse_face_beg_y, 0);
7163 fast_find_string_pos (w, XINT (e), object,
7164 &dpyinfo->mouse_face_end_col,
7165 &dpyinfo->mouse_face_end_row,
7166 &dpyinfo->mouse_face_end_x,
7167 &dpyinfo->mouse_face_end_y, 1);
7168 dpyinfo->mouse_face_past_end = 0;
7169 dpyinfo->mouse_face_window = window;
7170 dpyinfo->mouse_face_face_id
7171 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7172 glyph->face_id, 1);
7173 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7174 cursor = None;
7176 else if (STRINGP (object) && NILP (mouse_face))
7178 /* A string which doesn't have mouse-face, but
7179 the text ``under'' it might have. */
7180 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7181 int start = MATRIX_ROW_START_CHARPOS (r);
7183 pos = string_buffer_position (w, object, start);
7184 if (pos > 0)
7185 mouse_face = get_char_property_and_overlay (make_number (pos),
7186 Qmouse_face,
7187 w->buffer,
7188 &overlay);
7189 if (!NILP (mouse_face) && !NILP (overlay))
7191 Lisp_Object before = Foverlay_start (overlay);
7192 Lisp_Object after = Foverlay_end (overlay);
7193 int ignore;
7195 /* Note that we might not be able to find position
7196 BEFORE in the glyph matrix if the overlay is
7197 entirely covered by a `display' property. In
7198 this case, we overshoot. So let's stop in
7199 the glyph matrix before glyphs for OBJECT. */
7200 fast_find_position (w, XFASTINT (before),
7201 &dpyinfo->mouse_face_beg_col,
7202 &dpyinfo->mouse_face_beg_row,
7203 &dpyinfo->mouse_face_beg_x,
7204 &dpyinfo->mouse_face_beg_y,
7205 object);
7207 dpyinfo->mouse_face_past_end
7208 = !fast_find_position (w, XFASTINT (after),
7209 &dpyinfo->mouse_face_end_col,
7210 &dpyinfo->mouse_face_end_row,
7211 &dpyinfo->mouse_face_end_x,
7212 &dpyinfo->mouse_face_end_y,
7213 Qnil);
7214 dpyinfo->mouse_face_window = window;
7215 dpyinfo->mouse_face_face_id
7216 = face_at_buffer_position (w, pos, 0, 0,
7217 &ignore, pos + 1, 1);
7219 /* Display it as active. */
7220 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7221 cursor = None;
7226 check_help_echo:
7228 /* Look for a `help-echo' property. */
7230 Lisp_Object help, overlay;
7232 /* Check overlays first. */
7233 help = overlay = Qnil;
7234 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7236 overlay = overlay_vec[i];
7237 help = Foverlay_get (overlay, Qhelp_echo);
7240 if (!NILP (help))
7242 help_echo = help;
7243 help_echo_window = window;
7244 help_echo_object = overlay;
7245 help_echo_pos = pos;
7247 else
7249 Lisp_Object object = glyph->object;
7250 int charpos = glyph->charpos;
7252 /* Try text properties. */
7253 if (STRINGP (object)
7254 && charpos >= 0
7255 && charpos < XSTRING (object)->size)
7257 help = Fget_text_property (make_number (charpos),
7258 Qhelp_echo, object);
7259 if (NILP (help))
7261 /* If the string itself doesn't specify a help-echo,
7262 see if the buffer text ``under'' it does. */
7263 struct glyph_row *r
7264 = MATRIX_ROW (w->current_matrix, vpos);
7265 int start = MATRIX_ROW_START_CHARPOS (r);
7266 int pos = string_buffer_position (w, object, start);
7267 if (pos > 0)
7269 help = Fget_char_property (make_number (pos),
7270 Qhelp_echo, w->buffer);
7271 if (!NILP (help))
7273 charpos = pos;
7274 object = w->buffer;
7279 else if (BUFFERP (object)
7280 && charpos >= BEGV
7281 && charpos < ZV)
7282 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7283 object);
7285 if (!NILP (help))
7287 help_echo = help;
7288 help_echo_window = window;
7289 help_echo_object = object;
7290 help_echo_pos = charpos;
7295 BEGV = obegv;
7296 ZV = ozv;
7297 current_buffer = obuf;
7300 set_cursor:
7302 if (cursor != None)
7303 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7306 static void
7307 redo_mouse_highlight ()
7309 if (!NILP (last_mouse_motion_frame)
7310 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7311 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7312 last_mouse_motion_event.x,
7313 last_mouse_motion_event.y);
7318 /***********************************************************************
7319 Tool-bars
7320 ***********************************************************************/
7322 static int x_tool_bar_item P_ ((struct frame *, int, int,
7323 struct glyph **, int *, int *, int *));
7325 /* Tool-bar item index of the item on which a mouse button was pressed
7326 or -1. */
7328 static int last_tool_bar_item;
7331 /* Get information about the tool-bar item at position X/Y on frame F.
7332 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7333 the current matrix of the tool-bar window of F, or NULL if not
7334 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7335 item in F->tool_bar_items. Value is
7337 -1 if X/Y is not on a tool-bar item
7338 0 if X/Y is on the same item that was highlighted before.
7339 1 otherwise. */
7341 static int
7342 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7343 struct frame *f;
7344 int x, y;
7345 struct glyph **glyph;
7346 int *hpos, *vpos, *prop_idx;
7348 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7349 struct window *w = XWINDOW (f->tool_bar_window);
7350 int area;
7352 /* Find the glyph under X/Y. */
7353 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7354 if (*glyph == NULL)
7355 return -1;
7357 /* Get the start of this tool-bar item's properties in
7358 f->tool_bar_items. */
7359 if (!tool_bar_item_info (f, *glyph, prop_idx))
7360 return -1;
7362 /* Is mouse on the highlighted item? */
7363 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7364 && *vpos >= dpyinfo->mouse_face_beg_row
7365 && *vpos <= dpyinfo->mouse_face_end_row
7366 && (*vpos > dpyinfo->mouse_face_beg_row
7367 || *hpos >= dpyinfo->mouse_face_beg_col)
7368 && (*vpos < dpyinfo->mouse_face_end_row
7369 || *hpos < dpyinfo->mouse_face_end_col
7370 || dpyinfo->mouse_face_past_end))
7371 return 0;
7373 return 1;
7377 /* Handle mouse button event on the tool-bar of frame F, at
7378 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7379 or ButtonRelase. */
7381 static void
7382 x_handle_tool_bar_click (f, button_event)
7383 struct frame *f;
7384 XButtonEvent *button_event;
7386 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7387 struct window *w = XWINDOW (f->tool_bar_window);
7388 int hpos, vpos, prop_idx;
7389 struct glyph *glyph;
7390 Lisp_Object enabled_p;
7391 int x = button_event->x;
7392 int y = button_event->y;
7394 /* If not on the highlighted tool-bar item, return. */
7395 frame_to_window_pixel_xy (w, &x, &y);
7396 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7397 return;
7399 /* If item is disabled, do nothing. */
7400 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7401 if (NILP (enabled_p))
7402 return;
7404 if (button_event->type == ButtonPress)
7406 /* Show item in pressed state. */
7407 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7408 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7409 last_tool_bar_item = prop_idx;
7411 else
7413 Lisp_Object key, frame;
7414 struct input_event event;
7416 /* Show item in released state. */
7417 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7418 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7420 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7422 XSETFRAME (frame, f);
7423 event.kind = TOOL_BAR_EVENT;
7424 event.frame_or_window = frame;
7425 event.arg = frame;
7426 kbd_buffer_store_event (&event);
7428 event.kind = TOOL_BAR_EVENT;
7429 event.frame_or_window = frame;
7430 event.arg = key;
7431 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7432 button_event->state);
7433 kbd_buffer_store_event (&event);
7434 last_tool_bar_item = -1;
7439 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7440 tool-bar window-relative coordinates X/Y. Called from
7441 note_mouse_highlight. */
7443 static void
7444 note_tool_bar_highlight (f, x, y)
7445 struct frame *f;
7446 int x, y;
7448 Lisp_Object window = f->tool_bar_window;
7449 struct window *w = XWINDOW (window);
7450 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7451 int hpos, vpos;
7452 struct glyph *glyph;
7453 struct glyph_row *row;
7454 int i;
7455 Lisp_Object enabled_p;
7456 int prop_idx;
7457 enum draw_glyphs_face draw;
7458 int mouse_down_p, rc;
7460 /* Function note_mouse_highlight is called with negative x(y
7461 values when mouse moves outside of the frame. */
7462 if (x <= 0 || y <= 0)
7464 clear_mouse_face (dpyinfo);
7465 return;
7468 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7469 if (rc < 0)
7471 /* Not on tool-bar item. */
7472 clear_mouse_face (dpyinfo);
7473 return;
7475 else if (rc == 0)
7476 goto set_help_echo;
7478 clear_mouse_face (dpyinfo);
7480 /* Mouse is down, but on different tool-bar item? */
7481 mouse_down_p = (dpyinfo->grabbed
7482 && f == last_mouse_frame
7483 && FRAME_LIVE_P (f));
7484 if (mouse_down_p
7485 && last_tool_bar_item != prop_idx)
7486 return;
7488 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7489 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7491 /* If tool-bar item is not enabled, don't highlight it. */
7492 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7493 if (!NILP (enabled_p))
7495 /* Compute the x-position of the glyph. In front and past the
7496 image is a space. We include this is the highlighted area. */
7497 row = MATRIX_ROW (w->current_matrix, vpos);
7498 for (i = x = 0; i < hpos; ++i)
7499 x += row->glyphs[TEXT_AREA][i].pixel_width;
7501 /* Record this as the current active region. */
7502 dpyinfo->mouse_face_beg_col = hpos;
7503 dpyinfo->mouse_face_beg_row = vpos;
7504 dpyinfo->mouse_face_beg_x = x;
7505 dpyinfo->mouse_face_beg_y = row->y;
7506 dpyinfo->mouse_face_past_end = 0;
7508 dpyinfo->mouse_face_end_col = hpos + 1;
7509 dpyinfo->mouse_face_end_row = vpos;
7510 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7511 dpyinfo->mouse_face_end_y = row->y;
7512 dpyinfo->mouse_face_window = window;
7513 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7515 /* Display it as active. */
7516 show_mouse_face (dpyinfo, draw);
7517 dpyinfo->mouse_face_image_state = draw;
7520 set_help_echo:
7522 /* Set help_echo to a help string to display for this tool-bar item.
7523 XTread_socket does the rest. */
7524 help_echo_object = help_echo_window = Qnil;
7525 help_echo_pos = -1;
7526 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7527 if (NILP (help_echo))
7528 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7533 /* Find the glyph matrix position of buffer position CHARPOS in window
7534 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7535 current glyphs must be up to date. If CHARPOS is above window
7536 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7537 of last line in W. In the row containing CHARPOS, stop before glyphs
7538 having STOP as object. */
7540 #if 0 /* This is a version of fast_find_position that's more correct
7541 in the presence of hscrolling, for example. I didn't install
7542 it right away because the problem fixed is minor, it failed
7543 in 20.x as well, and I think it's too risky to install
7544 so near the release of 21.1. 2001-09-25 gerd. */
7546 static int
7547 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7548 struct window *w;
7549 int charpos;
7550 int *hpos, *vpos, *x, *y;
7551 Lisp_Object stop;
7553 struct glyph_row *row, *first;
7554 struct glyph *glyph, *end;
7555 int i, past_end = 0;
7557 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7558 row = row_containing_pos (w, charpos, first, NULL, 0);
7559 if (row == NULL)
7561 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7563 *x = *y = *hpos = *vpos = 0;
7564 return 0;
7566 else
7568 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7569 past_end = 1;
7573 *x = row->x;
7574 *y = row->y;
7575 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7577 glyph = row->glyphs[TEXT_AREA];
7578 end = glyph + row->used[TEXT_AREA];
7580 /* Skip over glyphs not having an object at the start of the row.
7581 These are special glyphs like truncation marks on terminal
7582 frames. */
7583 if (row->displays_text_p)
7584 while (glyph < end
7585 && INTEGERP (glyph->object)
7586 && !EQ (stop, glyph->object)
7587 && glyph->charpos < 0)
7589 *x += glyph->pixel_width;
7590 ++glyph;
7593 while (glyph < end
7594 && !INTEGERP (glyph->object)
7595 && !EQ (stop, glyph->object)
7596 && (!BUFFERP (glyph->object)
7597 || glyph->charpos < charpos))
7599 *x += glyph->pixel_width;
7600 ++glyph;
7603 *hpos = glyph - row->glyphs[TEXT_AREA];
7604 return past_end;
7607 #else /* not 0 */
7609 static int
7610 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7611 struct window *w;
7612 int pos;
7613 int *hpos, *vpos, *x, *y;
7614 Lisp_Object stop;
7616 int i;
7617 int lastcol;
7618 int maybe_next_line_p = 0;
7619 int line_start_position;
7620 int yb = window_text_bottom_y (w);
7621 struct glyph_row *row, *best_row;
7622 int row_vpos, best_row_vpos;
7623 int current_x;
7625 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7626 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7628 while (row->y < yb)
7630 if (row->used[TEXT_AREA])
7631 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7632 else
7633 line_start_position = 0;
7635 if (line_start_position > pos)
7636 break;
7637 /* If the position sought is the end of the buffer,
7638 don't include the blank lines at the bottom of the window. */
7639 else if (line_start_position == pos
7640 && pos == BUF_ZV (XBUFFER (w->buffer)))
7642 maybe_next_line_p = 1;
7643 break;
7645 else if (line_start_position > 0)
7647 best_row = row;
7648 best_row_vpos = row_vpos;
7651 if (row->y + row->height >= yb)
7652 break;
7654 ++row;
7655 ++row_vpos;
7658 /* Find the right column within BEST_ROW. */
7659 lastcol = 0;
7660 current_x = best_row->x;
7661 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7663 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7664 int charpos = glyph->charpos;
7666 if (BUFFERP (glyph->object))
7668 if (charpos == pos)
7670 *hpos = i;
7671 *vpos = best_row_vpos;
7672 *x = current_x;
7673 *y = best_row->y;
7674 return 1;
7676 else if (charpos > pos)
7677 break;
7679 else if (EQ (glyph->object, stop))
7680 break;
7682 if (charpos > 0)
7683 lastcol = i;
7684 current_x += glyph->pixel_width;
7687 /* If we're looking for the end of the buffer,
7688 and we didn't find it in the line we scanned,
7689 use the start of the following line. */
7690 if (maybe_next_line_p)
7692 ++best_row;
7693 ++best_row_vpos;
7694 lastcol = 0;
7695 current_x = best_row->x;
7698 *vpos = best_row_vpos;
7699 *hpos = lastcol + 1;
7700 *x = current_x;
7701 *y = best_row->y;
7702 return 0;
7705 #endif /* not 0 */
7708 /* Find the position of the glyph for position POS in OBJECT in
7709 window W's current matrix, and return in *X, *Y the pixel
7710 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7712 RIGHT_P non-zero means return the position of the right edge of the
7713 glyph, RIGHT_P zero means return the left edge position.
7715 If no glyph for POS exists in the matrix, return the position of
7716 the glyph with the next smaller position that is in the matrix, if
7717 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7718 exists in the matrix, return the position of the glyph with the
7719 next larger position in OBJECT.
7721 Value is non-zero if a glyph was found. */
7723 static int
7724 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7725 struct window *w;
7726 int pos;
7727 Lisp_Object object;
7728 int *hpos, *vpos, *x, *y;
7729 int right_p;
7731 int yb = window_text_bottom_y (w);
7732 struct glyph_row *r;
7733 struct glyph *best_glyph = NULL;
7734 struct glyph_row *best_row = NULL;
7735 int best_x = 0;
7737 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7738 r->enabled_p && r->y < yb;
7739 ++r)
7741 struct glyph *g = r->glyphs[TEXT_AREA];
7742 struct glyph *e = g + r->used[TEXT_AREA];
7743 int gx;
7745 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7746 if (EQ (g->object, object))
7748 if (g->charpos == pos)
7750 best_glyph = g;
7751 best_x = gx;
7752 best_row = r;
7753 goto found;
7755 else if (best_glyph == NULL
7756 || ((abs (g->charpos - pos)
7757 < abs (best_glyph->charpos - pos))
7758 && (right_p
7759 ? g->charpos < pos
7760 : g->charpos > pos)))
7762 best_glyph = g;
7763 best_x = gx;
7764 best_row = r;
7769 found:
7771 if (best_glyph)
7773 *x = best_x;
7774 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7776 if (right_p)
7778 *x += best_glyph->pixel_width;
7779 ++*hpos;
7782 *y = best_row->y;
7783 *vpos = best_row - w->current_matrix->rows;
7786 return best_glyph != NULL;
7790 /* Display the active region described by mouse_face_*
7791 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7793 static void
7794 show_mouse_face (dpyinfo, draw)
7795 struct x_display_info *dpyinfo;
7796 enum draw_glyphs_face draw;
7798 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7799 struct frame *f = XFRAME (WINDOW_FRAME (w));
7801 if (/* If window is in the process of being destroyed, don't bother
7802 to do anything. */
7803 w->current_matrix != NULL
7804 /* Don't update mouse highlight if hidden */
7805 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7806 /* Recognize when we are called to operate on rows that don't exist
7807 anymore. This can happen when a window is split. */
7808 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7810 int phys_cursor_on_p = w->phys_cursor_on_p;
7811 struct glyph_row *row, *first, *last;
7813 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7814 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7816 for (row = first; row <= last && row->enabled_p; ++row)
7818 int start_hpos, end_hpos, start_x;
7820 /* For all but the first row, the highlight starts at column 0. */
7821 if (row == first)
7823 start_hpos = dpyinfo->mouse_face_beg_col;
7824 start_x = dpyinfo->mouse_face_beg_x;
7826 else
7828 start_hpos = 0;
7829 start_x = 0;
7832 if (row == last)
7833 end_hpos = dpyinfo->mouse_face_end_col;
7834 else
7835 end_hpos = row->used[TEXT_AREA];
7837 if (end_hpos > start_hpos)
7839 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7840 start_hpos, end_hpos, draw, 0);
7842 row->mouse_face_p
7843 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
7847 /* When we've written over the cursor, arrange for it to
7848 be displayed again. */
7849 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7850 x_display_cursor (w, 1,
7851 w->phys_cursor.hpos, w->phys_cursor.vpos,
7852 w->phys_cursor.x, w->phys_cursor.y);
7855 /* Change the mouse cursor. */
7856 if (draw == DRAW_NORMAL_TEXT)
7857 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7858 f->output_data.x->text_cursor);
7859 else if (draw == DRAW_MOUSE_FACE)
7860 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7861 f->output_data.x->cross_cursor);
7862 else
7863 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7864 f->output_data.x->nontext_cursor);
7867 /* Clear out the mouse-highlighted active region.
7868 Redraw it un-highlighted first. Value is non-zero if mouse
7869 face was actually drawn unhighlighted. */
7871 static int
7872 clear_mouse_face (dpyinfo)
7873 struct x_display_info *dpyinfo;
7875 int cleared = 0;
7877 if (!NILP (dpyinfo->mouse_face_window))
7879 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7880 cleared = 1;
7883 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7884 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7885 dpyinfo->mouse_face_window = Qnil;
7886 dpyinfo->mouse_face_overlay = Qnil;
7887 return cleared;
7891 /* Clear any mouse-face on window W. This function is part of the
7892 redisplay interface, and is called from try_window_id and similar
7893 functions to ensure the mouse-highlight is off. */
7895 static void
7896 x_clear_mouse_face (w)
7897 struct window *w;
7899 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7900 Lisp_Object window;
7902 BLOCK_INPUT;
7903 XSETWINDOW (window, w);
7904 if (EQ (window, dpyinfo->mouse_face_window))
7905 clear_mouse_face (dpyinfo);
7906 UNBLOCK_INPUT;
7910 /* Just discard the mouse face information for frame F, if any.
7911 This is used when the size of F is changed. */
7913 void
7914 cancel_mouse_face (f)
7915 FRAME_PTR f;
7917 Lisp_Object window;
7918 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7920 window = dpyinfo->mouse_face_window;
7921 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7923 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7924 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7925 dpyinfo->mouse_face_window = Qnil;
7930 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7933 /* Try to determine frame pixel position and size of the glyph under
7934 frame pixel coordinates X/Y on frame F . Return the position and
7935 size in *RECT. Value is non-zero if we could compute these
7936 values. */
7938 static int
7939 glyph_rect (f, x, y, rect)
7940 struct frame *f;
7941 int x, y;
7942 XRectangle *rect;
7944 Lisp_Object window;
7945 int part, found = 0;
7947 window = window_from_coordinates (f, x, y, &part, 0);
7948 if (!NILP (window))
7950 struct window *w = XWINDOW (window);
7951 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7952 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7954 frame_to_window_pixel_xy (w, &x, &y);
7956 for (; !found && r < end && r->enabled_p; ++r)
7957 if (r->y >= y)
7959 struct glyph *g = r->glyphs[TEXT_AREA];
7960 struct glyph *end = g + r->used[TEXT_AREA];
7961 int gx;
7963 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7964 if (gx >= x)
7966 rect->width = g->pixel_width;
7967 rect->height = r->height;
7968 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7969 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7970 found = 1;
7975 return found;
7979 /* Return the current position of the mouse.
7980 *FP should be a frame which indicates which display to ask about.
7982 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7983 and *PART to the frame, window, and scroll bar part that the mouse
7984 is over. Set *X and *Y to the portion and whole of the mouse's
7985 position on the scroll bar.
7987 If the mouse movement started elsewhere, set *FP to the frame the
7988 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7989 the mouse is over.
7991 Set *TIME to the server time-stamp for the time at which the mouse
7992 was at this position.
7994 Don't store anything if we don't have a valid set of values to report.
7996 This clears the mouse_moved flag, so we can wait for the next mouse
7997 movement. */
7999 static void
8000 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8001 FRAME_PTR *fp;
8002 int insist;
8003 Lisp_Object *bar_window;
8004 enum scroll_bar_part *part;
8005 Lisp_Object *x, *y;
8006 unsigned long *time;
8008 FRAME_PTR f1;
8010 BLOCK_INPUT;
8012 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8013 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8014 else
8016 Window root;
8017 int root_x, root_y;
8019 Window dummy_window;
8020 int dummy;
8022 Lisp_Object frame, tail;
8024 /* Clear the mouse-moved flag for every frame on this display. */
8025 FOR_EACH_FRAME (tail, frame)
8026 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
8027 XFRAME (frame)->mouse_moved = 0;
8029 last_mouse_scroll_bar = Qnil;
8031 /* Figure out which root window we're on. */
8032 XQueryPointer (FRAME_X_DISPLAY (*fp),
8033 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
8035 /* The root window which contains the pointer. */
8036 &root,
8038 /* Trash which we can't trust if the pointer is on
8039 a different screen. */
8040 &dummy_window,
8042 /* The position on that root window. */
8043 &root_x, &root_y,
8045 /* More trash we can't trust. */
8046 &dummy, &dummy,
8048 /* Modifier keys and pointer buttons, about which
8049 we don't care. */
8050 (unsigned int *) &dummy);
8052 /* Now we have a position on the root; find the innermost window
8053 containing the pointer. */
8055 Window win, child;
8056 int win_x, win_y;
8057 int parent_x = 0, parent_y = 0;
8058 int count;
8060 win = root;
8062 /* XTranslateCoordinates can get errors if the window
8063 structure is changing at the same time this function
8064 is running. So at least we must not crash from them. */
8066 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8068 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8069 && FRAME_LIVE_P (last_mouse_frame))
8071 /* If mouse was grabbed on a frame, give coords for that frame
8072 even if the mouse is now outside it. */
8073 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8075 /* From-window, to-window. */
8076 root, FRAME_X_WINDOW (last_mouse_frame),
8078 /* From-position, to-position. */
8079 root_x, root_y, &win_x, &win_y,
8081 /* Child of win. */
8082 &child);
8083 f1 = last_mouse_frame;
8085 else
8087 while (1)
8089 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8091 /* From-window, to-window. */
8092 root, win,
8094 /* From-position, to-position. */
8095 root_x, root_y, &win_x, &win_y,
8097 /* Child of win. */
8098 &child);
8100 if (child == None || child == win)
8101 break;
8103 win = child;
8104 parent_x = win_x;
8105 parent_y = win_y;
8108 /* Now we know that:
8109 win is the innermost window containing the pointer
8110 (XTC says it has no child containing the pointer),
8111 win_x and win_y are the pointer's position in it
8112 (XTC did this the last time through), and
8113 parent_x and parent_y are the pointer's position in win's parent.
8114 (They are what win_x and win_y were when win was child.
8115 If win is the root window, it has no parent, and
8116 parent_{x,y} are invalid, but that's okay, because we'll
8117 never use them in that case.) */
8119 /* Is win one of our frames? */
8120 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8122 #ifdef USE_X_TOOLKIT
8123 /* If we end up with the menu bar window, say it's not
8124 on the frame. */
8125 if (f1 != NULL
8126 && f1->output_data.x->menubar_widget
8127 && win == XtWindow (f1->output_data.x->menubar_widget))
8128 f1 = NULL;
8129 #endif /* USE_X_TOOLKIT */
8132 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8133 f1 = 0;
8135 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8137 /* If not, is it one of our scroll bars? */
8138 if (! f1)
8140 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8142 if (bar)
8144 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8145 win_x = parent_x;
8146 win_y = parent_y;
8150 if (f1 == 0 && insist > 0)
8151 f1 = SELECTED_FRAME ();
8153 if (f1)
8155 /* Ok, we found a frame. Store all the values.
8156 last_mouse_glyph is a rectangle used to reduce the
8157 generation of mouse events. To not miss any motion
8158 events, we must divide the frame into rectangles of the
8159 size of the smallest character that could be displayed
8160 on it, i.e. into the same rectangles that matrices on
8161 the frame are divided into. */
8163 int width, height, gx, gy;
8164 XRectangle rect;
8166 if (glyph_rect (f1, win_x, win_y, &rect))
8167 last_mouse_glyph = rect;
8168 else
8170 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8171 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8172 gx = win_x;
8173 gy = win_y;
8175 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8176 round down even for negative values. */
8177 if (gx < 0)
8178 gx -= width - 1;
8179 if (gy < 0)
8180 gy -= height - 1;
8181 gx = (gx + width - 1) / width * width;
8182 gy = (gy + height - 1) / height * height;
8184 last_mouse_glyph.width = width;
8185 last_mouse_glyph.height = height;
8186 last_mouse_glyph.x = gx;
8187 last_mouse_glyph.y = gy;
8190 *bar_window = Qnil;
8191 *part = 0;
8192 *fp = f1;
8193 XSETINT (*x, win_x);
8194 XSETINT (*y, win_y);
8195 *time = last_mouse_movement_time;
8200 UNBLOCK_INPUT;
8204 #ifdef USE_X_TOOLKIT
8206 /* Atimer callback function for TIMER. Called every 0.1s to process
8207 Xt timeouts, if needed. We must avoid calling XtAppPending as
8208 much as possible because that function does an implicit XFlush
8209 that slows us down. */
8211 static void
8212 x_process_timeouts (timer)
8213 struct atimer *timer;
8215 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8217 BLOCK_INPUT;
8218 while (XtAppPending (Xt_app_con) & XtIMTimer)
8219 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8220 UNBLOCK_INPUT;
8224 #endif /* USE_X_TOOLKIT */
8227 /* Scroll bar support. */
8229 /* Given an X window ID, find the struct scroll_bar which manages it.
8230 This can be called in GC, so we have to make sure to strip off mark
8231 bits. */
8233 static struct scroll_bar *
8234 x_window_to_scroll_bar (window_id)
8235 Window window_id;
8237 Lisp_Object tail;
8239 for (tail = Vframe_list;
8240 XGCTYPE (tail) == Lisp_Cons;
8241 tail = XCDR (tail))
8243 Lisp_Object frame, bar, condemned;
8245 frame = XCAR (tail);
8246 /* All elements of Vframe_list should be frames. */
8247 if (! GC_FRAMEP (frame))
8248 abort ();
8250 /* Scan this frame's scroll bar list for a scroll bar with the
8251 right window ID. */
8252 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8253 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8254 /* This trick allows us to search both the ordinary and
8255 condemned scroll bar lists with one loop. */
8256 ! GC_NILP (bar) || (bar = condemned,
8257 condemned = Qnil,
8258 ! GC_NILP (bar));
8259 bar = XSCROLL_BAR (bar)->next)
8260 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8261 return XSCROLL_BAR (bar);
8264 return 0;
8268 #if defined USE_LUCID
8270 /* Return the Lucid menu bar WINDOW is part of. Return null
8271 if WINDOW is not part of a menu bar. */
8273 static Widget
8274 x_window_to_menu_bar (window)
8275 Window window;
8277 Lisp_Object tail;
8279 for (tail = Vframe_list;
8280 XGCTYPE (tail) == Lisp_Cons;
8281 tail = XCDR (tail))
8283 Lisp_Object frame = XCAR (tail);
8284 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8286 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8287 return menu_bar;
8290 return NULL;
8293 #endif /* USE_LUCID */
8296 /************************************************************************
8297 Toolkit scroll bars
8298 ************************************************************************/
8300 #ifdef USE_TOOLKIT_SCROLL_BARS
8302 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8303 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8304 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8305 struct scroll_bar *));
8306 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8307 int, int, int));
8310 /* Id of action hook installed for scroll bars. */
8312 static XtActionHookId action_hook_id;
8314 /* Lisp window being scrolled. Set when starting to interact with
8315 a toolkit scroll bar, reset to nil when ending the interaction. */
8317 static Lisp_Object window_being_scrolled;
8319 /* Last scroll bar part sent in xm_scroll_callback. */
8321 static int last_scroll_bar_part;
8323 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8324 that movements of 1/20 of the screen size are mapped to up/down. */
8326 static Boolean xaw3d_arrow_scroll;
8328 /* Whether the drag scrolling maintains the mouse at the top of the
8329 thumb. If not, resizing the thumb needs to be done more carefully
8330 to avoid jerkyness. */
8332 static Boolean xaw3d_pick_top;
8335 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8336 bars are used.. The hook is responsible for detecting when
8337 the user ends an interaction with the scroll bar, and generates
8338 a `end-scroll' scroll_bar_click' event if so. */
8340 static void
8341 xt_action_hook (widget, client_data, action_name, event, params,
8342 num_params)
8343 Widget widget;
8344 XtPointer client_data;
8345 String action_name;
8346 XEvent *event;
8347 String *params;
8348 Cardinal *num_params;
8350 int scroll_bar_p;
8351 char *end_action;
8353 #ifdef USE_MOTIF
8354 scroll_bar_p = XmIsScrollBar (widget);
8355 end_action = "Release";
8356 #else /* !USE_MOTIF i.e. use Xaw */
8357 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8358 end_action = "EndScroll";
8359 #endif /* USE_MOTIF */
8361 if (scroll_bar_p
8362 && strcmp (action_name, end_action) == 0
8363 && WINDOWP (window_being_scrolled))
8365 struct window *w;
8367 x_send_scroll_bar_event (window_being_scrolled,
8368 scroll_bar_end_scroll, 0, 0);
8369 w = XWINDOW (window_being_scrolled);
8370 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8371 window_being_scrolled = Qnil;
8372 last_scroll_bar_part = -1;
8374 /* Xt timeouts no longer needed. */
8375 toolkit_scroll_bar_interaction = 0;
8379 /* A vector of windows used for communication between
8380 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8382 static struct window **scroll_bar_windows;
8383 static int scroll_bar_windows_size;
8386 /* Send a client message with message type Xatom_Scrollbar for a
8387 scroll action to the frame of WINDOW. PART is a value identifying
8388 the part of the scroll bar that was clicked on. PORTION is the
8389 amount to scroll of a whole of WHOLE. */
8391 static void
8392 x_send_scroll_bar_event (window, part, portion, whole)
8393 Lisp_Object window;
8394 int part, portion, whole;
8396 XEvent event;
8397 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8398 struct window *w = XWINDOW (window);
8399 struct frame *f = XFRAME (w->frame);
8400 int i;
8402 BLOCK_INPUT;
8404 /* Construct a ClientMessage event to send to the frame. */
8405 ev->type = ClientMessage;
8406 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8407 ev->display = FRAME_X_DISPLAY (f);
8408 ev->window = FRAME_X_WINDOW (f);
8409 ev->format = 32;
8411 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8412 not enough to store a pointer or Lisp_Object on a 64 bit system.
8413 So, store the window in scroll_bar_windows and pass the index
8414 into that array in the event. */
8415 for (i = 0; i < scroll_bar_windows_size; ++i)
8416 if (scroll_bar_windows[i] == NULL)
8417 break;
8419 if (i == scroll_bar_windows_size)
8421 int new_size = max (10, 2 * scroll_bar_windows_size);
8422 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8423 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8425 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8426 nbytes);
8427 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8428 scroll_bar_windows_size = new_size;
8431 scroll_bar_windows[i] = w;
8432 ev->data.l[0] = (long) i;
8433 ev->data.l[1] = (long) part;
8434 ev->data.l[2] = (long) 0;
8435 ev->data.l[3] = (long) portion;
8436 ev->data.l[4] = (long) whole;
8438 /* Make Xt timeouts work while the scroll bar is active. */
8439 toolkit_scroll_bar_interaction = 1;
8441 /* Setting the event mask to zero means that the message will
8442 be sent to the client that created the window, and if that
8443 window no longer exists, no event will be sent. */
8444 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8445 UNBLOCK_INPUT;
8449 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8450 in *IEVENT. */
8452 static void
8453 x_scroll_bar_to_input_event (event, ievent)
8454 XEvent *event;
8455 struct input_event *ievent;
8457 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8458 Lisp_Object window;
8459 struct frame *f;
8460 struct window *w;
8462 w = scroll_bar_windows[ev->data.l[0]];
8463 scroll_bar_windows[ev->data.l[0]] = NULL;
8465 XSETWINDOW (window, w);
8466 f = XFRAME (w->frame);
8468 ievent->kind = scroll_bar_click;
8469 ievent->frame_or_window = window;
8470 ievent->arg = Qnil;
8471 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8472 ievent->part = ev->data.l[1];
8473 ievent->code = ev->data.l[2];
8474 ievent->x = make_number ((int) ev->data.l[3]);
8475 ievent->y = make_number ((int) ev->data.l[4]);
8476 ievent->modifiers = 0;
8480 #ifdef USE_MOTIF
8482 /* Minimum and maximum values used for Motif scroll bars. */
8484 #define XM_SB_MIN 1
8485 #define XM_SB_MAX 10000000
8486 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8489 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8490 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8491 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8493 static void
8494 xm_scroll_callback (widget, client_data, call_data)
8495 Widget widget;
8496 XtPointer client_data, call_data;
8498 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8499 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8500 int part = -1, whole = 0, portion = 0;
8502 switch (cs->reason)
8504 case XmCR_DECREMENT:
8505 bar->dragging = Qnil;
8506 part = scroll_bar_up_arrow;
8507 break;
8509 case XmCR_INCREMENT:
8510 bar->dragging = Qnil;
8511 part = scroll_bar_down_arrow;
8512 break;
8514 case XmCR_PAGE_DECREMENT:
8515 bar->dragging = Qnil;
8516 part = scroll_bar_above_handle;
8517 break;
8519 case XmCR_PAGE_INCREMENT:
8520 bar->dragging = Qnil;
8521 part = scroll_bar_below_handle;
8522 break;
8524 case XmCR_TO_TOP:
8525 bar->dragging = Qnil;
8526 part = scroll_bar_to_top;
8527 break;
8529 case XmCR_TO_BOTTOM:
8530 bar->dragging = Qnil;
8531 part = scroll_bar_to_bottom;
8532 break;
8534 case XmCR_DRAG:
8536 int slider_size;
8537 int dragging_down_p = (INTEGERP (bar->dragging)
8538 && XINT (bar->dragging) <= cs->value);
8540 /* Get the slider size. */
8541 BLOCK_INPUT;
8542 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8543 UNBLOCK_INPUT;
8545 /* At the max position of the scroll bar, do a line-wise
8546 movement. Without doing anything, we would be called with
8547 the same cs->value again and again. If we want to make
8548 sure that we can reach the end of the buffer, we have to do
8549 something.
8551 Implementation note: setting bar->dragging always to
8552 cs->value gives a smoother movement at the max position.
8553 Setting it to nil when doing line-wise movement gives
8554 a better slider behavior. */
8556 if (cs->value + slider_size == XM_SB_MAX
8557 || (dragging_down_p
8558 && last_scroll_bar_part == scroll_bar_down_arrow))
8560 part = scroll_bar_down_arrow;
8561 bar->dragging = Qnil;
8563 else
8565 whole = XM_SB_RANGE;
8566 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8567 part = scroll_bar_handle;
8568 bar->dragging = make_number (cs->value);
8571 break;
8573 case XmCR_VALUE_CHANGED:
8574 break;
8577 if (part >= 0)
8579 window_being_scrolled = bar->window;
8580 last_scroll_bar_part = part;
8581 x_send_scroll_bar_event (bar->window, part, portion, whole);
8586 #else /* !USE_MOTIF, i.e. Xaw. */
8589 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8590 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8591 scroll bar struct. CALL_DATA is a pointer to a float saying where
8592 the thumb is. */
8594 static void
8595 xaw_jump_callback (widget, client_data, call_data)
8596 Widget widget;
8597 XtPointer client_data, call_data;
8599 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8600 float top = *(float *) call_data;
8601 float shown;
8602 int whole, portion, height;
8603 int part;
8605 /* Get the size of the thumb, a value between 0 and 1. */
8606 BLOCK_INPUT;
8607 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8608 UNBLOCK_INPUT;
8610 whole = 10000000;
8611 portion = shown < 1 ? top * whole : 0;
8613 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8614 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8615 the bottom, so we force the scrolling whenever we see that we're
8616 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8617 we try to ensure that we always stay two pixels away from the
8618 bottom). */
8619 part = scroll_bar_down_arrow;
8620 else
8621 part = scroll_bar_handle;
8623 window_being_scrolled = bar->window;
8624 bar->dragging = make_number (portion);
8625 last_scroll_bar_part = part;
8626 x_send_scroll_bar_event (bar->window, part, portion, whole);
8630 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8631 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8632 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8633 the scroll bar. CALL_DATA is an integer specifying the action that
8634 has taken place. It's magnitude is in the range 0..height of the
8635 scroll bar. Negative values mean scroll towards buffer start.
8636 Values < height of scroll bar mean line-wise movement. */
8638 static void
8639 xaw_scroll_callback (widget, client_data, call_data)
8640 Widget widget;
8641 XtPointer client_data, call_data;
8643 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8644 int position = (int) call_data;
8645 Dimension height;
8646 int part;
8648 /* Get the height of the scroll bar. */
8649 BLOCK_INPUT;
8650 XtVaGetValues (widget, XtNheight, &height, NULL);
8651 UNBLOCK_INPUT;
8653 if (abs (position) >= height)
8654 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8656 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8657 it maps line-movement to call_data = max(5, height/20). */
8658 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8659 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8660 else
8661 part = scroll_bar_move_ratio;
8663 window_being_scrolled = bar->window;
8664 bar->dragging = Qnil;
8665 last_scroll_bar_part = part;
8666 x_send_scroll_bar_event (bar->window, part, position, height);
8670 #endif /* not USE_MOTIF */
8673 /* Create the widget for scroll bar BAR on frame F. Record the widget
8674 and X window of the scroll bar in BAR. */
8676 static void
8677 x_create_toolkit_scroll_bar (f, bar)
8678 struct frame *f;
8679 struct scroll_bar *bar;
8681 Window xwindow;
8682 Widget widget;
8683 Arg av[20];
8684 int ac = 0;
8685 char *scroll_bar_name = "verticalScrollBar";
8686 unsigned long pixel;
8688 BLOCK_INPUT;
8690 #ifdef USE_MOTIF
8691 /* Set resources. Create the widget. */
8692 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8693 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8694 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8695 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8696 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8697 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8698 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8700 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8701 if (pixel != -1)
8703 XtSetArg (av[ac], XmNforeground, pixel);
8704 ++ac;
8707 pixel = f->output_data.x->scroll_bar_background_pixel;
8708 if (pixel != -1)
8710 XtSetArg (av[ac], XmNbackground, pixel);
8711 ++ac;
8714 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8715 scroll_bar_name, av, ac);
8717 /* Add one callback for everything that can happen. */
8718 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8719 (XtPointer) bar);
8720 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8721 (XtPointer) bar);
8722 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8723 (XtPointer) bar);
8724 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8725 (XtPointer) bar);
8726 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8727 (XtPointer) bar);
8728 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8729 (XtPointer) bar);
8730 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8731 (XtPointer) bar);
8733 /* Realize the widget. Only after that is the X window created. */
8734 XtRealizeWidget (widget);
8736 /* Set the cursor to an arrow. I didn't find a resource to do that.
8737 And I'm wondering why it hasn't an arrow cursor by default. */
8738 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8739 f->output_data.x->nontext_cursor);
8741 #else /* !USE_MOTIF i.e. use Xaw */
8743 /* Set resources. Create the widget. The background of the
8744 Xaw3d scroll bar widget is a little bit light for my taste.
8745 We don't alter it here to let users change it according
8746 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8747 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8748 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8749 /* For smoother scrolling with Xaw3d -sm */
8750 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8752 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8753 if (pixel != -1)
8755 XtSetArg (av[ac], XtNforeground, pixel);
8756 ++ac;
8759 pixel = f->output_data.x->scroll_bar_background_pixel;
8760 if (pixel != -1)
8762 XtSetArg (av[ac], XtNbackground, pixel);
8763 ++ac;
8766 /* Top/bottom shadow colors. */
8768 /* Allocate them, if necessary. */
8769 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8771 pixel = f->output_data.x->scroll_bar_background_pixel;
8772 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8773 &pixel, 1.2, 0x8000))
8774 pixel = -1;
8775 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8777 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8779 pixel = f->output_data.x->scroll_bar_background_pixel;
8780 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8781 &pixel, 0.6, 0x4000))
8782 pixel = -1;
8783 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8786 /* Tell the toolkit about them. */
8787 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8788 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8789 /* We tried to allocate a color for the top/bottom shadow, and
8790 failed, so tell Xaw3d to use dithering instead. */
8792 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8793 ++ac;
8795 else
8796 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8797 be more consistent with other emacs 3d colors, and since Xaw3d is
8798 not good at dealing with allocation failure. */
8800 /* This tells Xaw3d to use real colors instead of dithering for
8801 the shadows. */
8802 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8803 ++ac;
8805 /* Specify the colors. */
8806 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8807 if (pixel != -1)
8809 XtSetArg (av[ac], "topShadowPixel", pixel);
8810 ++ac;
8812 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8813 if (pixel != -1)
8815 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8816 ++ac;
8820 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8821 f->output_data.x->edit_widget, av, ac);
8824 char *initial = "";
8825 char *val = initial;
8826 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8827 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8828 if (val == initial)
8829 { /* ARROW_SCROLL */
8830 xaw3d_arrow_scroll = True;
8831 /* Isn't that just a personal preference ? -sm */
8832 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8836 /* Define callbacks. */
8837 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8838 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8839 (XtPointer) bar);
8841 /* Realize the widget. Only after that is the X window created. */
8842 XtRealizeWidget (widget);
8844 #endif /* !USE_MOTIF */
8846 /* Install an action hook that let's us detect when the user
8847 finishes interacting with a scroll bar. */
8848 if (action_hook_id == 0)
8849 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8851 /* Remember X window and widget in the scroll bar vector. */
8852 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8853 xwindow = XtWindow (widget);
8854 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8856 UNBLOCK_INPUT;
8860 /* Set the thumb size and position of scroll bar BAR. We are currently
8861 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8863 static void
8864 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8865 struct scroll_bar *bar;
8866 int portion, position, whole;
8868 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8869 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8870 float top, shown;
8872 if (whole == 0)
8873 top = 0, shown = 1;
8874 else
8876 top = (float) position / whole;
8877 shown = (float) portion / whole;
8880 BLOCK_INPUT;
8882 #ifdef USE_MOTIF
8884 int size, value;
8886 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8887 is the scroll bar's maximum and MIN is the scroll bar's minimum
8888 value. */
8889 size = shown * XM_SB_RANGE;
8890 size = min (size, XM_SB_RANGE);
8891 size = max (size, 1);
8893 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8894 value = top * XM_SB_RANGE;
8895 value = min (value, XM_SB_MAX - size);
8896 value = max (value, XM_SB_MIN);
8898 if (NILP (bar->dragging))
8899 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8900 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8901 /* This has the negative side effect that the slider value is
8902 not what it would be if we scrolled here using line-wise or
8903 page-wise movement. */
8904 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8905 else
8907 /* If currently dragging, only update the slider size.
8908 This reduces flicker effects. */
8909 int old_value, old_size, increment, page_increment;
8911 XmScrollBarGetValues (widget, &old_value, &old_size,
8912 &increment, &page_increment);
8913 XmScrollBarSetValues (widget, old_value,
8914 min (size, XM_SB_RANGE - old_value),
8915 0, 0, False);
8918 #else /* !USE_MOTIF i.e. use Xaw */
8920 float old_top, old_shown;
8921 Dimension height;
8922 XtVaGetValues (widget,
8923 XtNtopOfThumb, &old_top,
8924 XtNshown, &old_shown,
8925 XtNheight, &height,
8926 NULL);
8928 /* Massage the top+shown values. */
8929 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8930 top = max (0, min (1, top));
8931 else
8932 top = old_top;
8933 /* Keep two pixels available for moving the thumb down. */
8934 shown = max (0, min (1 - top - (2.0 / height), shown));
8936 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8937 check that your system's configuration file contains a define
8938 for `NARROWPROTO'. See s/freebsd.h for an example. */
8939 if (top != old_top || shown != old_shown)
8941 if (NILP (bar->dragging))
8942 XawScrollbarSetThumb (widget, top, shown);
8943 else
8945 #ifdef HAVE_XAW3D
8946 ScrollbarWidget sb = (ScrollbarWidget) widget;
8947 int scroll_mode = 0;
8949 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8950 if (xaw3d_arrow_scroll)
8952 /* Xaw3d stupidly ignores resize requests while dragging
8953 so we have to make it believe it's not in dragging mode. */
8954 scroll_mode = sb->scrollbar.scroll_mode;
8955 if (scroll_mode == 2)
8956 sb->scrollbar.scroll_mode = 0;
8958 #endif
8959 /* Try to make the scrolling a tad smoother. */
8960 if (!xaw3d_pick_top)
8961 shown = min (shown, old_shown);
8963 XawScrollbarSetThumb (widget, top, shown);
8965 #ifdef HAVE_XAW3D
8966 if (xaw3d_arrow_scroll && scroll_mode == 2)
8967 sb->scrollbar.scroll_mode = scroll_mode;
8968 #endif
8972 #endif /* !USE_MOTIF */
8974 UNBLOCK_INPUT;
8977 #endif /* USE_TOOLKIT_SCROLL_BARS */
8981 /************************************************************************
8982 Scroll bars, general
8983 ************************************************************************/
8985 /* Create a scroll bar and return the scroll bar vector for it. W is
8986 the Emacs window on which to create the scroll bar. TOP, LEFT,
8987 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8988 scroll bar. */
8990 static struct scroll_bar *
8991 x_scroll_bar_create (w, top, left, width, height)
8992 struct window *w;
8993 int top, left, width, height;
8995 struct frame *f = XFRAME (w->frame);
8996 struct scroll_bar *bar
8997 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8999 BLOCK_INPUT;
9001 #ifdef USE_TOOLKIT_SCROLL_BARS
9002 x_create_toolkit_scroll_bar (f, bar);
9003 #else /* not USE_TOOLKIT_SCROLL_BARS */
9005 XSetWindowAttributes a;
9006 unsigned long mask;
9007 Window window;
9009 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
9010 if (a.background_pixel == -1)
9011 a.background_pixel = f->output_data.x->background_pixel;
9013 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9014 | ButtonMotionMask | PointerMotionHintMask
9015 | ExposureMask);
9016 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
9018 mask = (CWBackPixel | CWEventMask | CWCursor);
9020 /* Clear the area of W that will serve as a scroll bar. This is
9021 for the case that a window has been split horizontally. In
9022 this case, no clear_frame is generated to reduce flickering. */
9023 if (width > 0 && height > 0)
9024 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9025 left, top, width,
9026 window_box_height (w), False);
9028 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9029 /* Position and size of scroll bar. */
9030 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9031 top,
9032 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9033 height,
9034 /* Border width, depth, class, and visual. */
9036 CopyFromParent,
9037 CopyFromParent,
9038 CopyFromParent,
9039 /* Attributes. */
9040 mask, &a);
9041 SET_SCROLL_BAR_X_WINDOW (bar, window);
9043 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9045 XSETWINDOW (bar->window, w);
9046 XSETINT (bar->top, top);
9047 XSETINT (bar->left, left);
9048 XSETINT (bar->width, width);
9049 XSETINT (bar->height, height);
9050 XSETINT (bar->start, 0);
9051 XSETINT (bar->end, 0);
9052 bar->dragging = Qnil;
9054 /* Add bar to its frame's list of scroll bars. */
9055 bar->next = FRAME_SCROLL_BARS (f);
9056 bar->prev = Qnil;
9057 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9058 if (!NILP (bar->next))
9059 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9061 /* Map the window/widget. */
9062 #ifdef USE_TOOLKIT_SCROLL_BARS
9064 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9065 XtConfigureWidget (scroll_bar,
9066 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9067 top,
9068 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9069 max (height, 1), 0);
9070 XtMapWidget (scroll_bar);
9072 #else /* not USE_TOOLKIT_SCROLL_BARS */
9073 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9074 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9076 UNBLOCK_INPUT;
9077 return bar;
9081 /* Draw BAR's handle in the proper position.
9083 If the handle is already drawn from START to END, don't bother
9084 redrawing it, unless REBUILD is non-zero; in that case, always
9085 redraw it. (REBUILD is handy for drawing the handle after expose
9086 events.)
9088 Normally, we want to constrain the start and end of the handle to
9089 fit inside its rectangle, but if the user is dragging the scroll
9090 bar handle, we want to let them drag it down all the way, so that
9091 the bar's top is as far down as it goes; otherwise, there's no way
9092 to move to the very end of the buffer. */
9094 #ifndef USE_TOOLKIT_SCROLL_BARS
9096 static void
9097 x_scroll_bar_set_handle (bar, start, end, rebuild)
9098 struct scroll_bar *bar;
9099 int start, end;
9100 int rebuild;
9102 int dragging = ! NILP (bar->dragging);
9103 Window w = SCROLL_BAR_X_WINDOW (bar);
9104 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9105 GC gc = f->output_data.x->normal_gc;
9107 /* If the display is already accurate, do nothing. */
9108 if (! rebuild
9109 && start == XINT (bar->start)
9110 && end == XINT (bar->end))
9111 return;
9113 BLOCK_INPUT;
9116 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9117 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9118 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9120 /* Make sure the values are reasonable, and try to preserve
9121 the distance between start and end. */
9123 int length = end - start;
9125 if (start < 0)
9126 start = 0;
9127 else if (start > top_range)
9128 start = top_range;
9129 end = start + length;
9131 if (end < start)
9132 end = start;
9133 else if (end > top_range && ! dragging)
9134 end = top_range;
9137 /* Store the adjusted setting in the scroll bar. */
9138 XSETINT (bar->start, start);
9139 XSETINT (bar->end, end);
9141 /* Clip the end position, just for display. */
9142 if (end > top_range)
9143 end = top_range;
9145 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9146 below top positions, to make sure the handle is always at least
9147 that many pixels tall. */
9148 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9150 /* Draw the empty space above the handle. Note that we can't clear
9151 zero-height areas; that means "clear to end of window." */
9152 if (0 < start)
9153 x_clear_area (FRAME_X_DISPLAY (f), w,
9154 /* x, y, width, height, and exposures. */
9155 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9156 VERTICAL_SCROLL_BAR_TOP_BORDER,
9157 inside_width, start,
9158 False);
9160 /* Change to proper foreground color if one is specified. */
9161 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9162 XSetForeground (FRAME_X_DISPLAY (f), gc,
9163 f->output_data.x->scroll_bar_foreground_pixel);
9165 /* Draw the handle itself. */
9166 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9167 /* x, y, width, height */
9168 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9169 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9170 inside_width, end - start);
9172 /* Restore the foreground color of the GC if we changed it above. */
9173 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9174 XSetForeground (FRAME_X_DISPLAY (f), gc,
9175 f->output_data.x->foreground_pixel);
9177 /* Draw the empty space below the handle. Note that we can't
9178 clear zero-height areas; that means "clear to end of window." */
9179 if (end < inside_height)
9180 x_clear_area (FRAME_X_DISPLAY (f), w,
9181 /* x, y, width, height, and exposures. */
9182 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9183 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9184 inside_width, inside_height - end,
9185 False);
9189 UNBLOCK_INPUT;
9192 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9194 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9195 nil. */
9197 static void
9198 x_scroll_bar_remove (bar)
9199 struct scroll_bar *bar;
9201 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9202 BLOCK_INPUT;
9204 #ifdef USE_TOOLKIT_SCROLL_BARS
9205 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9206 #else
9207 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9208 #endif
9210 /* Disassociate this scroll bar from its window. */
9211 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9213 UNBLOCK_INPUT;
9217 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9218 that we are displaying PORTION characters out of a total of WHOLE
9219 characters, starting at POSITION. If WINDOW has no scroll bar,
9220 create one. */
9222 static void
9223 XTset_vertical_scroll_bar (w, portion, whole, position)
9224 struct window *w;
9225 int portion, whole, position;
9227 struct frame *f = XFRAME (w->frame);
9228 struct scroll_bar *bar;
9229 int top, height, left, sb_left, width, sb_width;
9230 int window_x, window_y, window_width, window_height;
9232 /* Get window dimensions. */
9233 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9234 top = window_y;
9235 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9236 height = window_height;
9238 /* Compute the left edge of the scroll bar area. */
9239 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9240 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9241 else
9242 left = XFASTINT (w->left);
9243 left *= CANON_X_UNIT (f);
9244 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9246 /* Compute the width of the scroll bar which might be less than
9247 the width of the area reserved for the scroll bar. */
9248 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9249 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9250 else
9251 sb_width = width;
9253 /* Compute the left edge of the scroll bar. */
9254 #ifdef USE_TOOLKIT_SCROLL_BARS
9255 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9256 sb_left = left + width - sb_width - (width - sb_width) / 2;
9257 else
9258 sb_left = left + (width - sb_width) / 2;
9259 #else
9260 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9261 sb_left = left + width - sb_width;
9262 else
9263 sb_left = left;
9264 #endif
9266 /* Does the scroll bar exist yet? */
9267 if (NILP (w->vertical_scroll_bar))
9269 if (width > 0 && height > 0)
9271 BLOCK_INPUT;
9272 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9273 left, top, width, height, False);
9274 UNBLOCK_INPUT;
9277 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9279 else
9281 /* It may just need to be moved and resized. */
9282 unsigned int mask = 0;
9284 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9286 BLOCK_INPUT;
9288 if (sb_left != XINT (bar->left))
9289 mask |= CWX;
9290 if (top != XINT (bar->top))
9291 mask |= CWY;
9292 if (sb_width != XINT (bar->width))
9293 mask |= CWWidth;
9294 if (height != XINT (bar->height))
9295 mask |= CWHeight;
9297 #ifdef USE_TOOLKIT_SCROLL_BARS
9299 /* Since toolkit scroll bars are smaller than the space reserved
9300 for them on the frame, we have to clear "under" them. */
9301 if (width > 0 && height > 0)
9302 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9303 left, top, width, height, False);
9305 /* Move/size the scroll bar widget. */
9306 if (mask)
9307 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9308 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9309 top,
9310 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9311 max (height, 1), 0);
9313 #else /* not USE_TOOLKIT_SCROLL_BARS */
9315 /* Clear areas not covered by the scroll bar because of
9316 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9317 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9319 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9320 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9321 height, False);
9322 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9323 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9324 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9325 height, False);
9328 /* Clear areas not covered by the scroll bar because it's not as
9329 wide as the area reserved for it . This makes sure a
9330 previous mode line display is cleared after C-x 2 C-x 1, for
9331 example. */
9333 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9334 int rest = area_width - sb_width;
9335 if (rest > 0 && height > 0)
9337 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9338 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9339 left + area_width - rest, top,
9340 rest, height, False);
9341 else
9342 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9343 left, top, rest, height, False);
9347 /* Move/size the scroll bar window. */
9348 if (mask)
9350 XWindowChanges wc;
9352 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9353 wc.y = top;
9354 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9355 wc.height = height;
9356 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9357 mask, &wc);
9360 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9362 /* Remember new settings. */
9363 XSETINT (bar->left, sb_left);
9364 XSETINT (bar->top, top);
9365 XSETINT (bar->width, sb_width);
9366 XSETINT (bar->height, height);
9368 UNBLOCK_INPUT;
9371 #ifdef USE_TOOLKIT_SCROLL_BARS
9372 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9373 #else /* not USE_TOOLKIT_SCROLL_BARS */
9374 /* Set the scroll bar's current state, unless we're currently being
9375 dragged. */
9376 if (NILP (bar->dragging))
9378 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9380 if (whole == 0)
9381 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9382 else
9384 int start = ((double) position * top_range) / whole;
9385 int end = ((double) (position + portion) * top_range) / whole;
9386 x_scroll_bar_set_handle (bar, start, end, 0);
9389 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9391 XSETVECTOR (w->vertical_scroll_bar, bar);
9395 /* The following three hooks are used when we're doing a thorough
9396 redisplay of the frame. We don't explicitly know which scroll bars
9397 are going to be deleted, because keeping track of when windows go
9398 away is a real pain - "Can you say set-window-configuration, boys
9399 and girls?" Instead, we just assert at the beginning of redisplay
9400 that *all* scroll bars are to be removed, and then save a scroll bar
9401 from the fiery pit when we actually redisplay its window. */
9403 /* Arrange for all scroll bars on FRAME to be removed at the next call
9404 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9405 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9407 static void
9408 XTcondemn_scroll_bars (frame)
9409 FRAME_PTR frame;
9411 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9412 while (! NILP (FRAME_SCROLL_BARS (frame)))
9414 Lisp_Object bar;
9415 bar = FRAME_SCROLL_BARS (frame);
9416 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9417 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9418 XSCROLL_BAR (bar)->prev = Qnil;
9419 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9420 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9421 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9426 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9427 Note that WINDOW isn't necessarily condemned at all. */
9429 static void
9430 XTredeem_scroll_bar (window)
9431 struct window *window;
9433 struct scroll_bar *bar;
9434 struct frame *f;
9436 /* We can't redeem this window's scroll bar if it doesn't have one. */
9437 if (NILP (window->vertical_scroll_bar))
9438 abort ();
9440 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9442 /* Unlink it from the condemned list. */
9443 f = XFRAME (WINDOW_FRAME (window));
9444 if (NILP (bar->prev))
9446 /* If the prev pointer is nil, it must be the first in one of
9447 the lists. */
9448 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9449 /* It's not condemned. Everything's fine. */
9450 return;
9451 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9452 window->vertical_scroll_bar))
9453 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9454 else
9455 /* If its prev pointer is nil, it must be at the front of
9456 one or the other! */
9457 abort ();
9459 else
9460 XSCROLL_BAR (bar->prev)->next = bar->next;
9462 if (! NILP (bar->next))
9463 XSCROLL_BAR (bar->next)->prev = bar->prev;
9465 bar->next = FRAME_SCROLL_BARS (f);
9466 bar->prev = Qnil;
9467 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9468 if (! NILP (bar->next))
9469 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9472 /* Remove all scroll bars on FRAME that haven't been saved since the
9473 last call to `*condemn_scroll_bars_hook'. */
9475 static void
9476 XTjudge_scroll_bars (f)
9477 FRAME_PTR f;
9479 Lisp_Object bar, next;
9481 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9483 /* Clear out the condemned list now so we won't try to process any
9484 more events on the hapless scroll bars. */
9485 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9487 for (; ! NILP (bar); bar = next)
9489 struct scroll_bar *b = XSCROLL_BAR (bar);
9491 x_scroll_bar_remove (b);
9493 next = b->next;
9494 b->next = b->prev = Qnil;
9497 /* Now there should be no references to the condemned scroll bars,
9498 and they should get garbage-collected. */
9502 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9503 is a no-op when using toolkit scroll bars.
9505 This may be called from a signal handler, so we have to ignore GC
9506 mark bits. */
9508 static void
9509 x_scroll_bar_expose (bar, event)
9510 struct scroll_bar *bar;
9511 XEvent *event;
9513 #ifndef USE_TOOLKIT_SCROLL_BARS
9515 Window w = SCROLL_BAR_X_WINDOW (bar);
9516 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9517 GC gc = f->output_data.x->normal_gc;
9518 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9520 BLOCK_INPUT;
9522 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9524 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9525 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9527 /* x, y, width, height */
9528 0, 0,
9529 XINT (bar->width) - 1 - width_trim - width_trim,
9530 XINT (bar->height) - 1);
9532 UNBLOCK_INPUT;
9534 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9537 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9538 is set to something other than no_event, it is enqueued.
9540 This may be called from a signal handler, so we have to ignore GC
9541 mark bits. */
9543 #ifndef USE_TOOLKIT_SCROLL_BARS
9545 static void
9546 x_scroll_bar_handle_click (bar, event, emacs_event)
9547 struct scroll_bar *bar;
9548 XEvent *event;
9549 struct input_event *emacs_event;
9551 if (! GC_WINDOWP (bar->window))
9552 abort ();
9554 emacs_event->kind = scroll_bar_click;
9555 emacs_event->code = event->xbutton.button - Button1;
9556 emacs_event->modifiers
9557 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9558 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9559 event->xbutton.state)
9560 | (event->type == ButtonRelease
9561 ? up_modifier
9562 : down_modifier));
9563 emacs_event->frame_or_window = bar->window;
9564 emacs_event->arg = Qnil;
9565 emacs_event->timestamp = event->xbutton.time;
9567 #if 0
9568 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9569 int internal_height
9570 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9571 #endif
9572 int top_range
9573 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9574 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9576 if (y < 0) y = 0;
9577 if (y > top_range) y = top_range;
9579 if (y < XINT (bar->start))
9580 emacs_event->part = scroll_bar_above_handle;
9581 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9582 emacs_event->part = scroll_bar_handle;
9583 else
9584 emacs_event->part = scroll_bar_below_handle;
9586 /* Just because the user has clicked on the handle doesn't mean
9587 they want to drag it. Lisp code needs to be able to decide
9588 whether or not we're dragging. */
9589 #if 0
9590 /* If the user has just clicked on the handle, record where they're
9591 holding it. */
9592 if (event->type == ButtonPress
9593 && emacs_event->part == scroll_bar_handle)
9594 XSETINT (bar->dragging, y - XINT (bar->start));
9595 #endif
9597 /* If the user has released the handle, set it to its final position. */
9598 if (event->type == ButtonRelease
9599 && ! NILP (bar->dragging))
9601 int new_start = y - XINT (bar->dragging);
9602 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9604 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9605 bar->dragging = Qnil;
9608 /* Same deal here as the other #if 0. */
9609 #if 0
9610 /* Clicks on the handle are always reported as occurring at the top of
9611 the handle. */
9612 if (emacs_event->part == scroll_bar_handle)
9613 emacs_event->x = bar->start;
9614 else
9615 XSETINT (emacs_event->x, y);
9616 #else
9617 XSETINT (emacs_event->x, y);
9618 #endif
9620 XSETINT (emacs_event->y, top_range);
9624 /* Handle some mouse motion while someone is dragging the scroll bar.
9626 This may be called from a signal handler, so we have to ignore GC
9627 mark bits. */
9629 static void
9630 x_scroll_bar_note_movement (bar, event)
9631 struct scroll_bar *bar;
9632 XEvent *event;
9634 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9636 last_mouse_movement_time = event->xmotion.time;
9638 f->mouse_moved = 1;
9639 XSETVECTOR (last_mouse_scroll_bar, bar);
9641 /* If we're dragging the bar, display it. */
9642 if (! GC_NILP (bar->dragging))
9644 /* Where should the handle be now? */
9645 int new_start = event->xmotion.y - XINT (bar->dragging);
9647 if (new_start != XINT (bar->start))
9649 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9651 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9656 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9658 /* Return information to the user about the current position of the mouse
9659 on the scroll bar. */
9661 static void
9662 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9663 FRAME_PTR *fp;
9664 Lisp_Object *bar_window;
9665 enum scroll_bar_part *part;
9666 Lisp_Object *x, *y;
9667 unsigned long *time;
9669 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9670 Window w = SCROLL_BAR_X_WINDOW (bar);
9671 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9672 int win_x, win_y;
9673 Window dummy_window;
9674 int dummy_coord;
9675 unsigned int dummy_mask;
9677 BLOCK_INPUT;
9679 /* Get the mouse's position relative to the scroll bar window, and
9680 report that. */
9681 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9683 /* Root, child, root x and root y. */
9684 &dummy_window, &dummy_window,
9685 &dummy_coord, &dummy_coord,
9687 /* Position relative to scroll bar. */
9688 &win_x, &win_y,
9690 /* Mouse buttons and modifier keys. */
9691 &dummy_mask))
9693 else
9695 #if 0
9696 int inside_height
9697 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9698 #endif
9699 int top_range
9700 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9702 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9704 if (! NILP (bar->dragging))
9705 win_y -= XINT (bar->dragging);
9707 if (win_y < 0)
9708 win_y = 0;
9709 if (win_y > top_range)
9710 win_y = top_range;
9712 *fp = f;
9713 *bar_window = bar->window;
9715 if (! NILP (bar->dragging))
9716 *part = scroll_bar_handle;
9717 else if (win_y < XINT (bar->start))
9718 *part = scroll_bar_above_handle;
9719 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9720 *part = scroll_bar_handle;
9721 else
9722 *part = scroll_bar_below_handle;
9724 XSETINT (*x, win_y);
9725 XSETINT (*y, top_range);
9727 f->mouse_moved = 0;
9728 last_mouse_scroll_bar = Qnil;
9731 *time = last_mouse_movement_time;
9733 UNBLOCK_INPUT;
9737 /* The screen has been cleared so we may have changed foreground or
9738 background colors, and the scroll bars may need to be redrawn.
9739 Clear out the scroll bars, and ask for expose events, so we can
9740 redraw them. */
9742 void
9743 x_scroll_bar_clear (f)
9744 FRAME_PTR f;
9746 #ifndef USE_TOOLKIT_SCROLL_BARS
9747 Lisp_Object bar;
9749 /* We can have scroll bars even if this is 0,
9750 if we just turned off scroll bar mode.
9751 But in that case we should not clear them. */
9752 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9753 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9754 bar = XSCROLL_BAR (bar)->next)
9755 XClearArea (FRAME_X_DISPLAY (f),
9756 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9757 0, 0, 0, 0, True);
9758 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9761 /* This processes Expose events from the menu-bar specific X event
9762 loop in xmenu.c. This allows to redisplay the frame if necessary
9763 when handling menu-bar or pop-up items. */
9766 process_expose_from_menu (event)
9767 XEvent event;
9769 FRAME_PTR f;
9770 struct x_display_info *dpyinfo;
9771 int frame_exposed_p = 0;
9773 BLOCK_INPUT;
9775 dpyinfo = x_display_info_for_display (event.xexpose.display);
9776 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9777 if (f)
9779 if (f->async_visible == 0)
9781 f->async_visible = 1;
9782 f->async_iconified = 0;
9783 f->output_data.x->has_been_visible = 1;
9784 SET_FRAME_GARBAGED (f);
9786 else
9788 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9789 event.xexpose.x, event.xexpose.y,
9790 event.xexpose.width, event.xexpose.height);
9791 frame_exposed_p = 1;
9794 else
9796 struct scroll_bar *bar
9797 = x_window_to_scroll_bar (event.xexpose.window);
9799 if (bar)
9800 x_scroll_bar_expose (bar, &event);
9803 UNBLOCK_INPUT;
9804 return frame_exposed_p;
9807 /* Define a queue to save up SelectionRequest events for later handling. */
9809 struct selection_event_queue
9811 XEvent event;
9812 struct selection_event_queue *next;
9815 static struct selection_event_queue *queue;
9817 /* Nonzero means queue up certain events--don't process them yet. */
9819 static int x_queue_selection_requests;
9821 /* Queue up an X event *EVENT, to be processed later. */
9823 static void
9824 x_queue_event (f, event)
9825 FRAME_PTR f;
9826 XEvent *event;
9828 struct selection_event_queue *queue_tmp
9829 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9831 if (queue_tmp != NULL)
9833 queue_tmp->event = *event;
9834 queue_tmp->next = queue;
9835 queue = queue_tmp;
9839 /* Take all the queued events and put them back
9840 so that they get processed afresh. */
9842 static void
9843 x_unqueue_events (display)
9844 Display *display;
9846 while (queue != NULL)
9848 struct selection_event_queue *queue_tmp = queue;
9849 XPutBackEvent (display, &queue_tmp->event);
9850 queue = queue_tmp->next;
9851 xfree ((char *)queue_tmp);
9855 /* Start queuing SelectionRequest events. */
9857 void
9858 x_start_queuing_selection_requests (display)
9859 Display *display;
9861 x_queue_selection_requests++;
9864 /* Stop queuing SelectionRequest events. */
9866 void
9867 x_stop_queuing_selection_requests (display)
9868 Display *display;
9870 x_queue_selection_requests--;
9871 x_unqueue_events (display);
9874 /* The main X event-reading loop - XTread_socket. */
9876 #if 0
9877 /* Time stamp of enter window event. This is only used by XTread_socket,
9878 but we have to put it out here, since static variables within functions
9879 sometimes don't work. */
9881 static Time enter_timestamp;
9882 #endif
9884 /* This holds the state XLookupString needs to implement dead keys
9885 and other tricks known as "compose processing". _X Window System_
9886 says that a portable program can't use this, but Stephen Gildea assures
9887 me that letting the compiler initialize it to zeros will work okay.
9889 This must be defined outside of XTread_socket, for the same reasons
9890 given for enter_timestamp, above. */
9892 static XComposeStatus compose_status;
9894 /* Record the last 100 characters stored
9895 to help debug the loss-of-chars-during-GC problem. */
9897 static int temp_index;
9898 static short temp_buffer[100];
9900 /* Set this to nonzero to fake an "X I/O error"
9901 on a particular display. */
9903 struct x_display_info *XTread_socket_fake_io_error;
9905 /* When we find no input here, we occasionally do a no-op command
9906 to verify that the X server is still running and we can still talk with it.
9907 We try all the open displays, one by one.
9908 This variable is used for cycling thru the displays. */
9910 static struct x_display_info *next_noop_dpyinfo;
9912 #define SET_SAVED_MENU_EVENT(size) \
9913 do \
9915 if (f->output_data.x->saved_menu_event == 0) \
9916 f->output_data.x->saved_menu_event \
9917 = (XEvent *) xmalloc (sizeof (XEvent)); \
9918 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9919 if (numchars >= 1) \
9921 bufp->kind = menu_bar_activate_event; \
9922 XSETFRAME (bufp->frame_or_window, f); \
9923 bufp->arg = Qnil; \
9924 bufp++; \
9925 count++; \
9926 numchars--; \
9929 while (0)
9931 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9932 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9934 /* Read events coming from the X server.
9935 This routine is called by the SIGIO handler.
9936 We return as soon as there are no more events to be read.
9938 Events representing keys are stored in buffer BUFP,
9939 which can hold up to NUMCHARS characters.
9940 We return the number of characters stored into the buffer,
9941 thus pretending to be `read'.
9943 EXPECTED is nonzero if the caller knows input is available. */
9946 XTread_socket (sd, bufp, numchars, expected)
9947 register int sd;
9948 /* register */ struct input_event *bufp;
9949 /* register */ int numchars;
9950 int expected;
9952 int count = 0;
9953 int nbytes = 0;
9954 XEvent event;
9955 struct frame *f;
9956 int event_found = 0;
9957 struct x_display_info *dpyinfo;
9958 struct coding_system coding;
9960 if (interrupt_input_blocked)
9962 interrupt_input_pending = 1;
9963 return -1;
9966 interrupt_input_pending = 0;
9967 BLOCK_INPUT;
9969 /* So people can tell when we have read the available input. */
9970 input_signal_count++;
9972 if (numchars <= 0)
9973 abort (); /* Don't think this happens. */
9975 ++handling_signal;
9977 /* The input should be decoded if it is from XIM. Currently the
9978 locale of XIM is the same as that of the system. So, we can use
9979 Vlocale_coding_system which is initialized properly at Emacs
9980 startup time. */
9981 setup_coding_system (Vlocale_coding_system, &coding);
9982 coding.src_multibyte = 0;
9983 coding.dst_multibyte = 1;
9984 /* The input is converted to events, thus we can't handle
9985 composition. Anyway, there's no XIM that gives us composition
9986 information. */
9987 coding.common_flags &= ~CODING_ANNOTATION_MASK;
9989 /* Find the display we are supposed to read input for.
9990 It's the one communicating on descriptor SD. */
9991 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9993 #if 0 /* This ought to be unnecessary; let's verify it. */
9994 #ifdef FIOSNBIO
9995 /* If available, Xlib uses FIOSNBIO to make the socket
9996 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9997 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9998 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9999 fcntl (dpyinfo->connection, F_SETFL, 0);
10000 #endif /* ! defined (FIOSNBIO) */
10001 #endif
10003 #if 0 /* This code can't be made to work, with multiple displays,
10004 and appears not to be used on any system any more.
10005 Also keyboard.c doesn't turn O_NDELAY on and off
10006 for X connections. */
10007 #ifndef SIGIO
10008 #ifndef HAVE_SELECT
10009 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
10011 extern int read_alarm_should_throw;
10012 read_alarm_should_throw = 1;
10013 XPeekEvent (dpyinfo->display, &event);
10014 read_alarm_should_throw = 0;
10016 #endif /* HAVE_SELECT */
10017 #endif /* SIGIO */
10018 #endif
10020 /* For debugging, this gives a way to fake an I/O error. */
10021 if (dpyinfo == XTread_socket_fake_io_error)
10023 XTread_socket_fake_io_error = 0;
10024 x_io_error_quitter (dpyinfo->display);
10027 while (XPending (dpyinfo->display))
10029 XNextEvent (dpyinfo->display, &event);
10031 #ifdef HAVE_X_I18N
10033 /* Filter events for the current X input method.
10034 XFilterEvent returns non-zero if the input method has
10035 consumed the event. We pass the frame's X window to
10036 XFilterEvent because that's the one for which the IC
10037 was created. */
10038 struct frame *f1 = x_any_window_to_frame (dpyinfo,
10039 event.xclient.window);
10040 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
10041 break;
10043 #endif
10044 event_found = 1;
10046 switch (event.type)
10048 case ClientMessage:
10050 if (event.xclient.message_type
10051 == dpyinfo->Xatom_wm_protocols
10052 && event.xclient.format == 32)
10054 if (event.xclient.data.l[0]
10055 == dpyinfo->Xatom_wm_take_focus)
10057 /* Use x_any_window_to_frame because this
10058 could be the shell widget window
10059 if the frame has no title bar. */
10060 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10061 #ifdef HAVE_X_I18N
10062 /* Not quite sure this is needed -pd */
10063 if (f && FRAME_XIC (f))
10064 XSetICFocus (FRAME_XIC (f));
10065 #endif
10066 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10067 instructs the WM to set the input focus automatically for
10068 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10069 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10070 it has set the focus. So, XSetInputFocus below is not
10071 needed.
10073 The call to XSetInputFocus below has also caused trouble. In
10074 cases where the XSetInputFocus done by the WM and the one
10075 below are temporally close (on a fast machine), the call
10076 below can generate additional FocusIn events which confuse
10077 Emacs. */
10079 /* Since we set WM_TAKE_FOCUS, we must call
10080 XSetInputFocus explicitly. But not if f is null,
10081 since that might be an event for a deleted frame. */
10082 if (f)
10084 Display *d = event.xclient.display;
10085 /* Catch and ignore errors, in case window has been
10086 iconified by a window manager such as GWM. */
10087 int count = x_catch_errors (d);
10088 XSetInputFocus (d, event.xclient.window,
10089 /* The ICCCM says this is
10090 the only valid choice. */
10091 RevertToParent,
10092 event.xclient.data.l[1]);
10093 /* This is needed to detect the error
10094 if there is an error. */
10095 XSync (d, False);
10096 x_uncatch_errors (d, count);
10098 /* Not certain about handling scroll bars here */
10099 #endif /* 0 */
10101 else if (event.xclient.data.l[0]
10102 == dpyinfo->Xatom_wm_save_yourself)
10104 /* Save state modify the WM_COMMAND property to
10105 something which can reinstate us. This notifies
10106 the session manager, who's looking for such a
10107 PropertyNotify. Can restart processing when
10108 a keyboard or mouse event arrives. */
10109 if (numchars > 0)
10111 f = x_top_window_to_frame (dpyinfo,
10112 event.xclient.window);
10114 /* This is just so we only give real data once
10115 for a single Emacs process. */
10116 if (f == SELECTED_FRAME ())
10117 XSetCommand (FRAME_X_DISPLAY (f),
10118 event.xclient.window,
10119 initial_argv, initial_argc);
10120 else if (f)
10121 XSetCommand (FRAME_X_DISPLAY (f),
10122 event.xclient.window,
10123 0, 0);
10126 else if (event.xclient.data.l[0]
10127 == dpyinfo->Xatom_wm_delete_window)
10129 struct frame *f
10130 = x_any_window_to_frame (dpyinfo,
10131 event.xclient.window);
10133 if (f)
10135 if (numchars == 0)
10136 abort ();
10138 bufp->kind = delete_window_event;
10139 XSETFRAME (bufp->frame_or_window, f);
10140 bufp->arg = Qnil;
10141 bufp++;
10143 count += 1;
10144 numchars -= 1;
10148 else if (event.xclient.message_type
10149 == dpyinfo->Xatom_wm_configure_denied)
10152 else if (event.xclient.message_type
10153 == dpyinfo->Xatom_wm_window_moved)
10155 int new_x, new_y;
10156 struct frame *f
10157 = x_window_to_frame (dpyinfo, event.xclient.window);
10159 new_x = event.xclient.data.s[0];
10160 new_y = event.xclient.data.s[1];
10162 if (f)
10164 f->output_data.x->left_pos = new_x;
10165 f->output_data.x->top_pos = new_y;
10168 #ifdef HACK_EDITRES
10169 else if (event.xclient.message_type
10170 == dpyinfo->Xatom_editres)
10172 struct frame *f
10173 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10174 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10175 &event, NULL);
10177 #endif /* HACK_EDITRES */
10178 else if ((event.xclient.message_type
10179 == dpyinfo->Xatom_DONE)
10180 || (event.xclient.message_type
10181 == dpyinfo->Xatom_PAGE))
10183 /* Ghostview job completed. Kill it. We could
10184 reply with "Next" if we received "Page", but we
10185 currently never do because we are interested in
10186 images, only, which should have 1 page. */
10187 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10188 struct frame *f
10189 = x_window_to_frame (dpyinfo, event.xclient.window);
10190 x_kill_gs_process (pixmap, f);
10191 expose_frame (f, 0, 0, 0, 0);
10193 #ifdef USE_TOOLKIT_SCROLL_BARS
10194 /* Scroll bar callbacks send a ClientMessage from which
10195 we construct an input_event. */
10196 else if (event.xclient.message_type
10197 == dpyinfo->Xatom_Scrollbar)
10199 x_scroll_bar_to_input_event (&event, bufp);
10200 ++bufp, ++count, --numchars;
10201 goto out;
10203 #endif /* USE_TOOLKIT_SCROLL_BARS */
10204 else
10205 goto OTHER;
10207 break;
10209 case SelectionNotify:
10210 #ifdef USE_X_TOOLKIT
10211 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10212 goto OTHER;
10213 #endif /* not USE_X_TOOLKIT */
10214 x_handle_selection_notify (&event.xselection);
10215 break;
10217 case SelectionClear: /* Someone has grabbed ownership. */
10218 #ifdef USE_X_TOOLKIT
10219 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10220 goto OTHER;
10221 #endif /* USE_X_TOOLKIT */
10223 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10225 if (numchars == 0)
10226 abort ();
10228 bufp->kind = selection_clear_event;
10229 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10230 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10231 SELECTION_EVENT_TIME (bufp) = eventp->time;
10232 bufp->frame_or_window = Qnil;
10233 bufp->arg = Qnil;
10234 bufp++;
10236 count += 1;
10237 numchars -= 1;
10239 break;
10241 case SelectionRequest: /* Someone wants our selection. */
10242 #ifdef USE_X_TOOLKIT
10243 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10244 goto OTHER;
10245 #endif /* USE_X_TOOLKIT */
10246 if (x_queue_selection_requests)
10247 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10248 &event);
10249 else
10251 XSelectionRequestEvent *eventp
10252 = (XSelectionRequestEvent *) &event;
10254 if (numchars == 0)
10255 abort ();
10257 bufp->kind = selection_request_event;
10258 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10259 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10260 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10261 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10262 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10263 SELECTION_EVENT_TIME (bufp) = eventp->time;
10264 bufp->frame_or_window = Qnil;
10265 bufp->arg = Qnil;
10266 bufp++;
10268 count += 1;
10269 numchars -= 1;
10271 break;
10273 case PropertyNotify:
10274 #if 0 /* This is plain wrong. In the case that we are waiting for a
10275 PropertyNotify used as an ACK in incremental selection
10276 transfer, the property will be on the receiver's window. */
10277 #if defined USE_X_TOOLKIT
10278 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10279 goto OTHER;
10280 #endif
10281 #endif
10282 x_handle_property_notify (&event.xproperty);
10283 goto OTHER;
10285 case ReparentNotify:
10286 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10287 if (f)
10289 int x, y;
10290 f->output_data.x->parent_desc = event.xreparent.parent;
10291 x_real_positions (f, &x, &y);
10292 f->output_data.x->left_pos = x;
10293 f->output_data.x->top_pos = y;
10295 break;
10297 case Expose:
10298 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10299 if (f)
10301 x_check_fullscreen (f);
10303 if (f->async_visible == 0)
10305 f->async_visible = 1;
10306 f->async_iconified = 0;
10307 f->output_data.x->has_been_visible = 1;
10308 SET_FRAME_GARBAGED (f);
10310 else
10311 expose_frame (x_window_to_frame (dpyinfo,
10312 event.xexpose.window),
10313 event.xexpose.x, event.xexpose.y,
10314 event.xexpose.width, event.xexpose.height);
10316 else
10318 #ifndef USE_TOOLKIT_SCROLL_BARS
10319 struct scroll_bar *bar;
10320 #endif
10321 #if defined USE_LUCID
10322 /* Submenus of the Lucid menu bar aren't widgets
10323 themselves, so there's no way to dispatch events
10324 to them. Recognize this case separately. */
10326 Widget widget
10327 = x_window_to_menu_bar (event.xexpose.window);
10328 if (widget)
10329 xlwmenu_redisplay (widget);
10331 #endif /* USE_LUCID */
10333 #ifdef USE_TOOLKIT_SCROLL_BARS
10334 /* Dispatch event to the widget. */
10335 goto OTHER;
10336 #else /* not USE_TOOLKIT_SCROLL_BARS */
10337 bar = x_window_to_scroll_bar (event.xexpose.window);
10339 if (bar)
10340 x_scroll_bar_expose (bar, &event);
10341 #ifdef USE_X_TOOLKIT
10342 else
10343 goto OTHER;
10344 #endif /* USE_X_TOOLKIT */
10345 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10347 break;
10349 case GraphicsExpose: /* This occurs when an XCopyArea's
10350 source area was obscured or not
10351 available. */
10352 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10353 if (f)
10355 expose_frame (f,
10356 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10357 event.xgraphicsexpose.width,
10358 event.xgraphicsexpose.height);
10360 #ifdef USE_X_TOOLKIT
10361 else
10362 goto OTHER;
10363 #endif /* USE_X_TOOLKIT */
10364 break;
10366 case NoExpose: /* This occurs when an XCopyArea's
10367 source area was completely
10368 available. */
10369 break;
10371 case UnmapNotify:
10372 /* Redo the mouse-highlight after the tooltip has gone. */
10373 if (event.xmap.window == tip_window)
10375 tip_window = 0;
10376 redo_mouse_highlight ();
10379 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10380 if (f) /* F may no longer exist if
10381 the frame was deleted. */
10383 /* While a frame is unmapped, display generation is
10384 disabled; you don't want to spend time updating a
10385 display that won't ever be seen. */
10386 f->async_visible = 0;
10387 /* We can't distinguish, from the event, whether the window
10388 has become iconified or invisible. So assume, if it
10389 was previously visible, than now it is iconified.
10390 But x_make_frame_invisible clears both
10391 the visible flag and the iconified flag;
10392 and that way, we know the window is not iconified now. */
10393 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10395 f->async_iconified = 1;
10397 bufp->kind = iconify_event;
10398 XSETFRAME (bufp->frame_or_window, f);
10399 bufp->arg = Qnil;
10400 bufp++;
10401 count++;
10402 numchars--;
10405 goto OTHER;
10407 case MapNotify:
10408 if (event.xmap.window == tip_window)
10409 /* The tooltip has been drawn already. Avoid
10410 the SET_FRAME_GARBAGED below. */
10411 goto OTHER;
10413 /* We use x_top_window_to_frame because map events can
10414 come for sub-windows and they don't mean that the
10415 frame is visible. */
10416 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10417 if (f)
10419 f->async_visible = 1;
10420 f->async_iconified = 0;
10421 f->output_data.x->has_been_visible = 1;
10423 /* wait_reading_process_input will notice this and update
10424 the frame's display structures. */
10425 SET_FRAME_GARBAGED (f);
10427 if (f->iconified)
10429 bufp->kind = deiconify_event;
10430 XSETFRAME (bufp->frame_or_window, f);
10431 bufp->arg = Qnil;
10432 bufp++;
10433 count++;
10434 numchars--;
10436 else if (! NILP (Vframe_list)
10437 && ! NILP (XCDR (Vframe_list)))
10438 /* Force a redisplay sooner or later
10439 to update the frame titles
10440 in case this is the second frame. */
10441 record_asynch_buffer_change ();
10443 goto OTHER;
10445 case KeyPress:
10446 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10448 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10450 dpyinfo->mouse_face_hidden = 1;
10451 clear_mouse_face (dpyinfo);
10454 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10455 if (f == 0)
10457 /* Scroll bars consume key events, but we want
10458 the keys to go to the scroll bar's frame. */
10459 Widget widget = XtWindowToWidget (dpyinfo->display,
10460 event.xkey.window);
10461 if (widget && XmIsScrollBar (widget))
10463 widget = XtParent (widget);
10464 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10467 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10469 if (f != 0)
10471 KeySym keysym, orig_keysym;
10472 /* al%imercury@uunet.uu.net says that making this 81
10473 instead of 80 fixed a bug whereby meta chars made
10474 his Emacs hang.
10476 It seems that some version of XmbLookupString has
10477 a bug of not returning XBufferOverflow in
10478 status_return even if the input is too long to
10479 fit in 81 bytes. So, we must prepare sufficient
10480 bytes for copy_buffer. 513 bytes (256 chars for
10481 two-byte character set) seems to be a fairly good
10482 approximation. -- 2000.8.10 handa@etl.go.jp */
10483 unsigned char copy_buffer[513];
10484 unsigned char *copy_bufptr = copy_buffer;
10485 int copy_bufsiz = sizeof (copy_buffer);
10486 int modifiers;
10488 event.xkey.state
10489 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10490 extra_keyboard_modifiers);
10491 modifiers = event.xkey.state;
10493 /* This will have to go some day... */
10495 /* make_lispy_event turns chars into control chars.
10496 Don't do it here because XLookupString is too eager. */
10497 event.xkey.state &= ~ControlMask;
10498 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10499 | dpyinfo->super_mod_mask
10500 | dpyinfo->hyper_mod_mask
10501 | dpyinfo->alt_mod_mask);
10503 /* In case Meta is ComposeCharacter,
10504 clear its status. According to Markus Ehrnsperger
10505 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10506 this enables ComposeCharacter to work whether or
10507 not it is combined with Meta. */
10508 if (modifiers & dpyinfo->meta_mod_mask)
10509 bzero (&compose_status, sizeof (compose_status));
10511 #ifdef HAVE_X_I18N
10512 if (FRAME_XIC (f))
10514 Status status_return;
10516 nbytes = XmbLookupString (FRAME_XIC (f),
10517 &event.xkey, copy_bufptr,
10518 copy_bufsiz, &keysym,
10519 &status_return);
10520 if (status_return == XBufferOverflow)
10522 copy_bufsiz = nbytes + 1;
10523 copy_bufptr = (char *) alloca (copy_bufsiz);
10524 nbytes = XmbLookupString (FRAME_XIC (f),
10525 &event.xkey, copy_bufptr,
10526 copy_bufsiz, &keysym,
10527 &status_return);
10530 if (status_return == XLookupNone)
10531 break;
10532 else if (status_return == XLookupChars)
10534 keysym = NoSymbol;
10535 modifiers = 0;
10537 else if (status_return != XLookupKeySym
10538 && status_return != XLookupBoth)
10539 abort ();
10541 else
10542 nbytes = XLookupString (&event.xkey, copy_bufptr,
10543 copy_bufsiz, &keysym,
10544 &compose_status);
10545 #else
10546 nbytes = XLookupString (&event.xkey, copy_bufptr,
10547 copy_bufsiz, &keysym,
10548 &compose_status);
10549 #endif
10551 orig_keysym = keysym;
10553 if (numchars > 1)
10555 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10556 || keysym == XK_Delete
10557 #ifdef XK_ISO_Left_Tab
10558 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10559 #endif
10560 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10561 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10562 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10563 #ifdef HPUX
10564 /* This recognizes the "extended function keys".
10565 It seems there's no cleaner way.
10566 Test IsModifierKey to avoid handling mode_switch
10567 incorrectly. */
10568 || ((unsigned) (keysym) >= XK_Select
10569 && (unsigned)(keysym) < XK_KP_Space)
10570 #endif
10571 #ifdef XK_dead_circumflex
10572 || orig_keysym == XK_dead_circumflex
10573 #endif
10574 #ifdef XK_dead_grave
10575 || orig_keysym == XK_dead_grave
10576 #endif
10577 #ifdef XK_dead_tilde
10578 || orig_keysym == XK_dead_tilde
10579 #endif
10580 #ifdef XK_dead_diaeresis
10581 || orig_keysym == XK_dead_diaeresis
10582 #endif
10583 #ifdef XK_dead_macron
10584 || orig_keysym == XK_dead_macron
10585 #endif
10586 #ifdef XK_dead_degree
10587 || orig_keysym == XK_dead_degree
10588 #endif
10589 #ifdef XK_dead_acute
10590 || orig_keysym == XK_dead_acute
10591 #endif
10592 #ifdef XK_dead_cedilla
10593 || orig_keysym == XK_dead_cedilla
10594 #endif
10595 #ifdef XK_dead_breve
10596 || orig_keysym == XK_dead_breve
10597 #endif
10598 #ifdef XK_dead_ogonek
10599 || orig_keysym == XK_dead_ogonek
10600 #endif
10601 #ifdef XK_dead_caron
10602 || orig_keysym == XK_dead_caron
10603 #endif
10604 #ifdef XK_dead_doubleacute
10605 || orig_keysym == XK_dead_doubleacute
10606 #endif
10607 #ifdef XK_dead_abovedot
10608 || orig_keysym == XK_dead_abovedot
10609 #endif
10610 #ifdef XK_dead_abovering
10611 || orig_keysym == XK_dead_abovering
10612 #endif
10613 #ifdef XK_dead_iota
10614 || orig_keysym == XK_dead_iota
10615 #endif
10616 #ifdef XK_dead_belowdot
10617 || orig_keysym == XK_dead_belowdot
10618 #endif
10619 #ifdef XK_dead_voiced_sound
10620 || orig_keysym == XK_dead_voiced_sound
10621 #endif
10622 #ifdef XK_dead_semivoiced_sound
10623 || orig_keysym == XK_dead_semivoiced_sound
10624 #endif
10625 #ifdef XK_dead_hook
10626 || orig_keysym == XK_dead_hook
10627 #endif
10628 #ifdef XK_dead_horn
10629 || orig_keysym == XK_dead_horn
10630 #endif
10631 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10632 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10633 /* Any "vendor-specific" key is ok. */
10634 || (orig_keysym & (1 << 28))
10635 || (keysym != NoSymbol && nbytes == 0))
10636 && ! (IsModifierKey (orig_keysym)
10637 #ifndef HAVE_X11R5
10638 #ifdef XK_Mode_switch
10639 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10640 #endif
10641 #ifdef XK_Num_Lock
10642 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10643 #endif
10644 #endif /* not HAVE_X11R5 */
10647 if (temp_index == sizeof temp_buffer / sizeof (short))
10648 temp_index = 0;
10649 temp_buffer[temp_index++] = keysym;
10650 bufp->kind = non_ascii_keystroke;
10651 bufp->code = keysym;
10652 XSETFRAME (bufp->frame_or_window, f);
10653 bufp->arg = Qnil;
10654 bufp->modifiers
10655 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10656 modifiers);
10657 bufp->timestamp = event.xkey.time;
10658 bufp++;
10659 count++;
10660 numchars--;
10662 else if (numchars > nbytes)
10664 register int i;
10665 register int c;
10666 int nchars, len;
10668 for (i = 0; i < nbytes; i++)
10670 if (temp_index == (sizeof temp_buffer
10671 / sizeof (short)))
10672 temp_index = 0;
10673 temp_buffer[temp_index++] = copy_bufptr[i];
10676 if (/* If the event is not from XIM, */
10677 event.xkey.keycode != 0
10678 /* or the current locale doesn't request
10679 decoding of the input data, ... */
10680 || ! CODING_REQUIRE_DECODING (&coding))
10682 /* ... we can use the input data as is. */
10683 nchars = nbytes;
10685 else
10687 /* We have to decode the input data. */
10688 coding.destination
10689 = (unsigned char *) malloc (nbytes);
10690 if (! coding.destination)
10691 break;
10692 coding.dst_bytes = nbytes;
10693 coding.mode |= CODING_MODE_LAST_BLOCK;
10694 decode_coding_c_string (&coding, copy_bufptr,
10695 nbytes, Qnil);
10696 nbytes = coding.produced;
10697 nchars = coding.produced_char;
10698 if (copy_bufsiz < nbytes)
10700 copy_bufsiz = nbytes;
10701 copy_bufptr = (char *) alloca (nbytes);
10703 bcopy (coding.destination, copy_bufptr, nbytes);
10704 free (coding.destination);
10707 /* Convert the input data to a sequence of
10708 character events. */
10709 for (i = 0; i < nbytes; i += len)
10711 if (nchars == nbytes)
10712 c = copy_bufptr[i], len = 1;
10713 else
10714 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10715 nbytes - i, len);
10717 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10718 ? ascii_keystroke
10719 : multibyte_char_keystroke);
10720 bufp->code = c;
10721 XSETFRAME (bufp->frame_or_window, f);
10722 bufp->arg = Qnil;
10723 bufp->modifiers
10724 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10725 modifiers);
10726 bufp->timestamp = event.xkey.time;
10727 bufp++;
10730 count += nchars;
10731 numchars -= nchars;
10733 if (keysym == NoSymbol)
10734 break;
10736 else
10737 abort ();
10739 else
10740 abort ();
10742 #ifdef HAVE_X_I18N
10743 /* Don't dispatch this event since XtDispatchEvent calls
10744 XFilterEvent, and two calls in a row may freeze the
10745 client. */
10746 break;
10747 #else
10748 goto OTHER;
10749 #endif
10751 case KeyRelease:
10752 #ifdef HAVE_X_I18N
10753 /* Don't dispatch this event since XtDispatchEvent calls
10754 XFilterEvent, and two calls in a row may freeze the
10755 client. */
10756 break;
10757 #else
10758 goto OTHER;
10759 #endif
10761 /* Here's a possible interpretation of the whole
10762 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10763 you get a FocusIn event, you have to get a FocusOut
10764 event before you relinquish the focus. If you
10765 haven't received a FocusIn event, then a mere
10766 LeaveNotify is enough to free you. */
10768 case EnterNotify:
10770 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10772 #if 0
10773 if (event.xcrossing.focus)
10775 /* Avoid nasty pop/raise loops. */
10776 if (f && (!(f->auto_raise)
10777 || !(f->auto_lower)
10778 || (event.xcrossing.time - enter_timestamp) > 500))
10780 x_new_focus_frame (dpyinfo, f);
10781 enter_timestamp = event.xcrossing.time;
10784 else if (f == dpyinfo->x_focus_frame)
10785 x_new_focus_frame (dpyinfo, 0);
10786 #endif
10788 /* EnterNotify counts as mouse movement,
10789 so update things that depend on mouse position. */
10790 if (f && !f->output_data.x->hourglass_p)
10791 note_mouse_movement (f, &event.xmotion);
10792 goto OTHER;
10795 case FocusIn:
10796 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10797 if (event.xfocus.detail != NotifyPointer)
10798 dpyinfo->x_focus_event_frame = f;
10799 if (f)
10801 x_new_focus_frame (dpyinfo, f);
10803 /* Don't stop displaying the initial startup message
10804 for a switch-frame event we don't need. */
10805 if (GC_NILP (Vterminal_frame)
10806 && GC_CONSP (Vframe_list)
10807 && !GC_NILP (XCDR (Vframe_list)))
10809 bufp->kind = FOCUS_IN_EVENT;
10810 XSETFRAME (bufp->frame_or_window, f);
10811 bufp->arg = Qnil;
10812 ++bufp, ++count, --numchars;
10816 #ifdef HAVE_X_I18N
10817 if (f && FRAME_XIC (f))
10818 XSetICFocus (FRAME_XIC (f));
10819 #endif
10821 goto OTHER;
10823 case LeaveNotify:
10824 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10825 if (f)
10827 if (f == dpyinfo->mouse_face_mouse_frame)
10829 /* If we move outside the frame, then we're
10830 certainly no longer on any text in the frame. */
10831 clear_mouse_face (dpyinfo);
10832 dpyinfo->mouse_face_mouse_frame = 0;
10835 /* Generate a nil HELP_EVENT to cancel a help-echo.
10836 Do it only if there's something to cancel.
10837 Otherwise, the startup message is cleared when
10838 the mouse leaves the frame. */
10839 if (any_help_event_p)
10841 Lisp_Object frame;
10842 int n;
10844 XSETFRAME (frame, f);
10845 help_echo = Qnil;
10846 n = gen_help_event (bufp, numchars,
10847 Qnil, frame, Qnil, Qnil, 0);
10848 bufp += n, count += n, numchars -= n;
10851 #if 0
10852 if (event.xcrossing.focus)
10853 x_mouse_leave (dpyinfo);
10854 else
10856 if (f == dpyinfo->x_focus_event_frame)
10857 dpyinfo->x_focus_event_frame = 0;
10858 if (f == dpyinfo->x_focus_frame)
10859 x_new_focus_frame (dpyinfo, 0);
10861 #endif
10863 goto OTHER;
10865 case FocusOut:
10866 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10867 if (event.xfocus.detail != NotifyPointer
10868 && f == dpyinfo->x_focus_event_frame)
10869 dpyinfo->x_focus_event_frame = 0;
10870 if (f && f == dpyinfo->x_focus_frame)
10871 x_new_focus_frame (dpyinfo, 0);
10873 #ifdef HAVE_X_I18N
10874 if (f && FRAME_XIC (f))
10875 XUnsetICFocus (FRAME_XIC (f));
10876 #endif
10878 goto OTHER;
10880 case MotionNotify:
10882 previous_help_echo = help_echo;
10883 help_echo = help_echo_object = help_echo_window = Qnil;
10884 help_echo_pos = -1;
10886 if (dpyinfo->grabbed && last_mouse_frame
10887 && FRAME_LIVE_P (last_mouse_frame))
10888 f = last_mouse_frame;
10889 else
10890 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10892 if (dpyinfo->mouse_face_hidden)
10894 dpyinfo->mouse_face_hidden = 0;
10895 clear_mouse_face (dpyinfo);
10898 if (f)
10899 note_mouse_movement (f, &event.xmotion);
10900 else
10902 #ifndef USE_TOOLKIT_SCROLL_BARS
10903 struct scroll_bar *bar
10904 = x_window_to_scroll_bar (event.xmotion.window);
10906 if (bar)
10907 x_scroll_bar_note_movement (bar, &event);
10908 #endif /* USE_TOOLKIT_SCROLL_BARS */
10910 /* If we move outside the frame, then we're
10911 certainly no longer on any text in the frame. */
10912 clear_mouse_face (dpyinfo);
10915 /* If the contents of the global variable help_echo
10916 has changed, generate a HELP_EVENT. */
10917 if (!NILP (help_echo)
10918 || !NILP (previous_help_echo))
10920 Lisp_Object frame;
10921 int n;
10923 if (f)
10924 XSETFRAME (frame, f);
10925 else
10926 frame = Qnil;
10928 any_help_event_p = 1;
10929 n = gen_help_event (bufp, numchars, help_echo, frame,
10930 help_echo_window, help_echo_object,
10931 help_echo_pos);
10932 bufp += n, count += n, numchars -= n;
10935 goto OTHER;
10938 case ConfigureNotify:
10939 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10940 if (f)
10942 #ifndef USE_X_TOOLKIT
10943 /* If there is a pending resize for fullscreen, don't
10944 do this one, the right one will come later.
10945 The toolkit version doesn't seem to need this, but we
10946 need to reset it below. */
10947 int dont_resize =
10948 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
10949 && FRAME_NEW_WIDTH (f) != 0);
10950 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10951 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10952 if (dont_resize)
10953 goto OTHER;
10955 /* In the toolkit version, change_frame_size
10956 is called by the code that handles resizing
10957 of the EmacsFrame widget. */
10959 /* Even if the number of character rows and columns has
10960 not changed, the font size may have changed, so we need
10961 to check the pixel dimensions as well. */
10962 if (columns != f->width
10963 || rows != f->height
10964 || event.xconfigure.width != f->output_data.x->pixel_width
10965 || event.xconfigure.height != f->output_data.x->pixel_height)
10967 change_frame_size (f, rows, columns, 0, 1, 0);
10968 SET_FRAME_GARBAGED (f);
10969 cancel_mouse_face (f);
10971 #endif
10973 f->output_data.x->pixel_width = event.xconfigure.width;
10974 f->output_data.x->pixel_height = event.xconfigure.height;
10976 /* What we have now is the position of Emacs's own window.
10977 Convert that to the position of the window manager window. */
10978 x_real_positions (f, &f->output_data.x->left_pos,
10979 &f->output_data.x->top_pos);
10981 x_check_fullscreen_move(f);
10982 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
10983 f->output_data.x->want_fullscreen &=
10984 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
10985 #ifdef HAVE_X_I18N
10986 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10987 xic_set_statusarea (f);
10988 #endif
10990 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10992 /* Since the WM decorations come below top_pos now,
10993 we must put them below top_pos in the future. */
10994 f->output_data.x->win_gravity = NorthWestGravity;
10995 x_wm_set_size_hint (f, (long) 0, 0);
10997 #ifdef USE_MOTIF
10998 /* Some window managers pass (0,0) as the location of
10999 the window, and the Motif event handler stores it
11000 in the emacs widget, which messes up Motif menus. */
11001 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
11003 event.xconfigure.x = f->output_data.x->widget->core.x;
11004 event.xconfigure.y = f->output_data.x->widget->core.y;
11006 #endif /* USE_MOTIF */
11008 goto OTHER;
11010 case ButtonPress:
11011 case ButtonRelease:
11013 /* If we decide we want to generate an event to be seen
11014 by the rest of Emacs, we put it here. */
11015 struct input_event emacs_event;
11016 int tool_bar_p = 0;
11018 emacs_event.kind = no_event;
11019 bzero (&compose_status, sizeof (compose_status));
11021 if (dpyinfo->grabbed
11022 && last_mouse_frame
11023 && FRAME_LIVE_P (last_mouse_frame))
11024 f = last_mouse_frame;
11025 else
11026 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11028 if (f)
11030 /* Is this in the tool-bar? */
11031 if (WINDOWP (f->tool_bar_window)
11032 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11034 Lisp_Object window;
11035 int p, x, y;
11037 x = event.xbutton.x;
11038 y = event.xbutton.y;
11040 /* Set x and y. */
11041 window = window_from_coordinates (f, x, y, &p, 1);
11042 if (EQ (window, f->tool_bar_window))
11044 x_handle_tool_bar_click (f, &event.xbutton);
11045 tool_bar_p = 1;
11049 if (!tool_bar_p)
11050 if (!dpyinfo->x_focus_frame
11051 || f == dpyinfo->x_focus_frame)
11052 construct_mouse_click (&emacs_event, &event, f);
11054 else
11056 #ifndef USE_TOOLKIT_SCROLL_BARS
11057 struct scroll_bar *bar
11058 = x_window_to_scroll_bar (event.xbutton.window);
11060 if (bar)
11061 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11062 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11065 if (event.type == ButtonPress)
11067 dpyinfo->grabbed |= (1 << event.xbutton.button);
11068 last_mouse_frame = f;
11069 /* Ignore any mouse motion that happened
11070 before this event; any subsequent mouse-movement
11071 Emacs events should reflect only motion after
11072 the ButtonPress. */
11073 if (f != 0)
11074 f->mouse_moved = 0;
11076 if (!tool_bar_p)
11077 last_tool_bar_item = -1;
11079 else
11081 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11084 if (numchars >= 1 && emacs_event.kind != no_event)
11086 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11087 bufp++;
11088 count++;
11089 numchars--;
11092 #ifdef USE_X_TOOLKIT
11093 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11094 /* For a down-event in the menu bar,
11095 don't pass it to Xt right now.
11096 Instead, save it away
11097 and we will pass it to Xt from kbd_buffer_get_event.
11098 That way, we can run some Lisp code first. */
11099 if (f && event.type == ButtonPress
11100 /* Verify the event is really within the menu bar
11101 and not just sent to it due to grabbing. */
11102 && event.xbutton.x >= 0
11103 && event.xbutton.x < f->output_data.x->pixel_width
11104 && event.xbutton.y >= 0
11105 && event.xbutton.y < f->output_data.x->menubar_height
11106 && event.xbutton.same_screen)
11108 SET_SAVED_BUTTON_EVENT;
11109 XSETFRAME (last_mouse_press_frame, f);
11111 else if (event.type == ButtonPress)
11113 last_mouse_press_frame = Qnil;
11114 goto OTHER;
11117 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11118 but I am trying to be cautious. */
11119 else if (event.type == ButtonRelease)
11121 if (!NILP (last_mouse_press_frame))
11123 f = XFRAME (last_mouse_press_frame);
11124 if (f->output_data.x)
11125 SET_SAVED_BUTTON_EVENT;
11127 else
11128 goto OTHER;
11130 #endif /* USE_MOTIF */
11131 else
11132 goto OTHER;
11133 #endif /* USE_X_TOOLKIT */
11135 break;
11137 case CirculateNotify:
11138 goto OTHER;
11140 case CirculateRequest:
11141 goto OTHER;
11143 case VisibilityNotify:
11144 goto OTHER;
11146 case MappingNotify:
11147 /* Someone has changed the keyboard mapping - update the
11148 local cache. */
11149 switch (event.xmapping.request)
11151 case MappingModifier:
11152 x_find_modifier_meanings (dpyinfo);
11153 /* This is meant to fall through. */
11154 case MappingKeyboard:
11155 XRefreshKeyboardMapping (&event.xmapping);
11157 goto OTHER;
11159 default:
11160 OTHER:
11161 #ifdef USE_X_TOOLKIT
11162 BLOCK_INPUT;
11163 XtDispatchEvent (&event);
11164 UNBLOCK_INPUT;
11165 #endif /* USE_X_TOOLKIT */
11166 break;
11171 out:;
11173 /* On some systems, an X bug causes Emacs to get no more events
11174 when the window is destroyed. Detect that. (1994.) */
11175 if (! event_found)
11177 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11178 One XNOOP in 100 loops will make Emacs terminate.
11179 B. Bretthauer, 1994 */
11180 x_noop_count++;
11181 if (x_noop_count >= 100)
11183 x_noop_count=0;
11185 if (next_noop_dpyinfo == 0)
11186 next_noop_dpyinfo = x_display_list;
11188 XNoOp (next_noop_dpyinfo->display);
11190 /* Each time we get here, cycle through the displays now open. */
11191 next_noop_dpyinfo = next_noop_dpyinfo->next;
11195 /* If the focus was just given to an auto-raising frame,
11196 raise it now. */
11197 /* ??? This ought to be able to handle more than one such frame. */
11198 if (pending_autoraise_frame)
11200 x_raise_frame (pending_autoraise_frame);
11201 pending_autoraise_frame = 0;
11204 UNBLOCK_INPUT;
11205 --handling_signal;
11206 return count;
11212 /***********************************************************************
11213 Text Cursor
11214 ***********************************************************************/
11216 /* Notice when the text cursor of window W has been completely
11217 overwritten by a drawing operation that outputs glyphs in AREA
11218 starting at X0 and ending at X1 in the line starting at Y0 and
11219 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11220 the rest of the line after X0 has been written. Y coordinates
11221 are window-relative. */
11223 static void
11224 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
11225 struct window *w;
11226 enum glyph_row_area area;
11227 int x0, y0, x1, y1;
11229 if (area == TEXT_AREA
11230 && w->phys_cursor_on_p
11231 && y0 <= w->phys_cursor.y
11232 && y1 >= w->phys_cursor.y + w->phys_cursor_height
11233 && x0 <= w->phys_cursor.x
11234 && (x1 < 0 || x1 > w->phys_cursor.x))
11235 w->phys_cursor_on_p = 0;
11239 /* Set clipping for output in glyph row ROW. W is the window in which
11240 we operate. GC is the graphics context to set clipping in.
11241 WHOLE_LINE_P non-zero means include the areas used for truncation
11242 mark display and alike in the clipping rectangle.
11244 ROW may be a text row or, e.g., a mode line. Text rows must be
11245 clipped to the interior of the window dedicated to text display,
11246 mode lines must be clipped to the whole window. */
11248 static void
11249 x_clip_to_row (w, row, gc, whole_line_p)
11250 struct window *w;
11251 struct glyph_row *row;
11252 GC gc;
11253 int whole_line_p;
11255 struct frame *f = XFRAME (WINDOW_FRAME (w));
11256 XRectangle clip_rect;
11257 int window_x, window_y, window_width, window_height;
11259 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11261 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11262 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11263 clip_rect.y = max (clip_rect.y, window_y);
11264 clip_rect.width = window_width;
11265 clip_rect.height = row->visible_height;
11267 /* If clipping to the whole line, including trunc marks, extend
11268 the rectangle to the left and increase its width. */
11269 if (whole_line_p)
11271 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11272 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11275 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11279 /* Draw a hollow box cursor on window W in glyph row ROW. */
11281 static void
11282 x_draw_hollow_cursor (w, row)
11283 struct window *w;
11284 struct glyph_row *row;
11286 struct frame *f = XFRAME (WINDOW_FRAME (w));
11287 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11288 Display *dpy = FRAME_X_DISPLAY (f);
11289 int x, y, wd, h;
11290 XGCValues xgcv;
11291 struct glyph *cursor_glyph;
11292 GC gc;
11294 /* Compute frame-relative coordinates from window-relative
11295 coordinates. */
11296 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11297 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11298 + row->ascent - w->phys_cursor_ascent);
11299 h = row->height - 1;
11301 /* Get the glyph the cursor is on. If we can't tell because
11302 the current matrix is invalid or such, give up. */
11303 cursor_glyph = get_phys_cursor_glyph (w);
11304 if (cursor_glyph == NULL)
11305 return;
11307 /* Compute the width of the rectangle to draw. If on a stretch
11308 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11309 rectangle as wide as the glyph, but use a canonical character
11310 width instead. */
11311 wd = cursor_glyph->pixel_width - 1;
11312 if (cursor_glyph->type == STRETCH_GLYPH
11313 && !x_stretch_cursor_p)
11314 wd = min (CANON_X_UNIT (f), wd);
11316 /* The foreground of cursor_gc is typically the same as the normal
11317 background color, which can cause the cursor box to be invisible. */
11318 xgcv.foreground = f->output_data.x->cursor_pixel;
11319 if (dpyinfo->scratch_cursor_gc)
11320 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11321 else
11322 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11323 GCForeground, &xgcv);
11324 gc = dpyinfo->scratch_cursor_gc;
11326 /* Set clipping, draw the rectangle, and reset clipping again. */
11327 x_clip_to_row (w, row, gc, 0);
11328 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11329 XSetClipMask (dpy, gc, None);
11333 /* Draw a bar cursor on window W in glyph row ROW.
11335 Implementation note: One would like to draw a bar cursor with an
11336 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11337 Unfortunately, I didn't find a font yet that has this property set.
11338 --gerd. */
11340 static void
11341 x_draw_bar_cursor (w, row, width)
11342 struct window *w;
11343 struct glyph_row *row;
11344 int width;
11346 struct frame *f = XFRAME (w->frame);
11347 struct glyph *cursor_glyph;
11349 /* If cursor is out of bounds, don't draw garbage. This can happen
11350 in mini-buffer windows when switching between echo area glyphs
11351 and mini-buffer. */
11352 cursor_glyph = get_phys_cursor_glyph (w);
11353 if (cursor_glyph == NULL)
11354 return;
11356 /* If on an image, draw like a normal cursor. That's usually better
11357 visible than drawing a bar, esp. if the image is large so that
11358 the bar might not be in the window. */
11359 if (cursor_glyph->type == IMAGE_GLYPH)
11361 struct glyph_row *row;
11362 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11363 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11365 else
11367 Display *dpy = FRAME_X_DISPLAY (f);
11368 Window window = FRAME_X_WINDOW (f);
11369 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11370 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11371 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11372 XGCValues xgcv;
11374 /* If the glyph's background equals the color we normally draw
11375 the bar cursor in, the bar cursor in its normal color is
11376 invisible. Use the glyph's foreground color instead in this
11377 case, on the assumption that the glyph's colors are chosen so
11378 that the glyph is legible. */
11379 if (face->background == f->output_data.x->cursor_pixel)
11380 xgcv.background = xgcv.foreground = face->foreground;
11381 else
11382 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11383 xgcv.graphics_exposures = 0;
11385 if (gc)
11386 XChangeGC (dpy, gc, mask, &xgcv);
11387 else
11389 gc = XCreateGC (dpy, window, mask, &xgcv);
11390 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11393 if (width < 0)
11394 width = f->output_data.x->cursor_width;
11395 width = min (cursor_glyph->pixel_width, width);
11397 x_clip_to_row (w, row, gc, 0);
11398 XFillRectangle (dpy, window, gc,
11399 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11400 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11401 width, row->height);
11402 XSetClipMask (dpy, gc, None);
11407 /* Clear the cursor of window W to background color, and mark the
11408 cursor as not shown. This is used when the text where the cursor
11409 is is about to be rewritten. */
11411 static void
11412 x_clear_cursor (w)
11413 struct window *w;
11415 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11416 x_update_window_cursor (w, 0);
11420 /* Draw the cursor glyph of window W in glyph row ROW. See the
11421 comment of x_draw_glyphs for the meaning of HL. */
11423 static void
11424 x_draw_phys_cursor_glyph (w, row, hl)
11425 struct window *w;
11426 struct glyph_row *row;
11427 enum draw_glyphs_face hl;
11429 /* If cursor hpos is out of bounds, don't draw garbage. This can
11430 happen in mini-buffer windows when switching between echo area
11431 glyphs and mini-buffer. */
11432 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11434 int on_p = w->phys_cursor_on_p;
11436 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11437 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11438 hl, 0);
11439 w->phys_cursor_on_p = on_p;
11441 /* When we erase the cursor, and ROW is overlapped by other
11442 rows, make sure that these overlapping parts of other rows
11443 are redrawn. */
11444 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11446 if (row > w->current_matrix->rows
11447 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11448 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11450 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11451 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11452 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11458 /* Erase the image of a cursor of window W from the screen. */
11460 static void
11461 x_erase_phys_cursor (w)
11462 struct window *w;
11464 struct frame *f = XFRAME (w->frame);
11465 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11466 int hpos = w->phys_cursor.hpos;
11467 int vpos = w->phys_cursor.vpos;
11468 int mouse_face_here_p = 0;
11469 struct glyph_matrix *active_glyphs = w->current_matrix;
11470 struct glyph_row *cursor_row;
11471 struct glyph *cursor_glyph;
11472 enum draw_glyphs_face hl;
11474 /* No cursor displayed or row invalidated => nothing to do on the
11475 screen. */
11476 if (w->phys_cursor_type == NO_CURSOR)
11477 goto mark_cursor_off;
11479 /* VPOS >= active_glyphs->nrows means that window has been resized.
11480 Don't bother to erase the cursor. */
11481 if (vpos >= active_glyphs->nrows)
11482 goto mark_cursor_off;
11484 /* If row containing cursor is marked invalid, there is nothing we
11485 can do. */
11486 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11487 if (!cursor_row->enabled_p)
11488 goto mark_cursor_off;
11490 /* If row is completely invisible, don't attempt to delete a cursor which
11491 isn't there. This can happen if cursor is at top of a window, and
11492 we switch to a buffer with a header line in that window. */
11493 if (cursor_row->visible_height <= 0)
11494 goto mark_cursor_off;
11496 /* This can happen when the new row is shorter than the old one.
11497 In this case, either x_draw_glyphs or clear_end_of_line
11498 should have cleared the cursor. Note that we wouldn't be
11499 able to erase the cursor in this case because we don't have a
11500 cursor glyph at hand. */
11501 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11502 goto mark_cursor_off;
11504 /* If the cursor is in the mouse face area, redisplay that when
11505 we clear the cursor. */
11506 if (! NILP (dpyinfo->mouse_face_window)
11507 && w == XWINDOW (dpyinfo->mouse_face_window)
11508 && (vpos > dpyinfo->mouse_face_beg_row
11509 || (vpos == dpyinfo->mouse_face_beg_row
11510 && hpos >= dpyinfo->mouse_face_beg_col))
11511 && (vpos < dpyinfo->mouse_face_end_row
11512 || (vpos == dpyinfo->mouse_face_end_row
11513 && hpos < dpyinfo->mouse_face_end_col))
11514 /* Don't redraw the cursor's spot in mouse face if it is at the
11515 end of a line (on a newline). The cursor appears there, but
11516 mouse highlighting does not. */
11517 && cursor_row->used[TEXT_AREA] > hpos)
11518 mouse_face_here_p = 1;
11520 /* Maybe clear the display under the cursor. */
11521 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11523 int x;
11524 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11526 cursor_glyph = get_phys_cursor_glyph (w);
11527 if (cursor_glyph == NULL)
11528 goto mark_cursor_off;
11530 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11532 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11534 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11535 cursor_row->y)),
11536 cursor_glyph->pixel_width,
11537 cursor_row->visible_height,
11538 False);
11541 /* Erase the cursor by redrawing the character underneath it. */
11542 if (mouse_face_here_p)
11543 hl = DRAW_MOUSE_FACE;
11544 else
11545 hl = DRAW_NORMAL_TEXT;
11546 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11548 mark_cursor_off:
11549 w->phys_cursor_on_p = 0;
11550 w->phys_cursor_type = NO_CURSOR;
11554 /* Non-zero if physical cursor of window W is within mouse face. */
11556 static int
11557 cursor_in_mouse_face_p (w)
11558 struct window *w;
11560 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11561 int in_mouse_face = 0;
11563 if (WINDOWP (dpyinfo->mouse_face_window)
11564 && XWINDOW (dpyinfo->mouse_face_window) == w)
11566 int hpos = w->phys_cursor.hpos;
11567 int vpos = w->phys_cursor.vpos;
11569 if (vpos >= dpyinfo->mouse_face_beg_row
11570 && vpos <= dpyinfo->mouse_face_end_row
11571 && (vpos > dpyinfo->mouse_face_beg_row
11572 || hpos >= dpyinfo->mouse_face_beg_col)
11573 && (vpos < dpyinfo->mouse_face_end_row
11574 || hpos < dpyinfo->mouse_face_end_col
11575 || dpyinfo->mouse_face_past_end))
11576 in_mouse_face = 1;
11579 return in_mouse_face;
11583 /* Display or clear cursor of window W. If ON is zero, clear the
11584 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11585 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11587 void
11588 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11589 struct window *w;
11590 int on, hpos, vpos, x, y;
11592 struct frame *f = XFRAME (w->frame);
11593 int new_cursor_type;
11594 int new_cursor_width;
11595 struct glyph_matrix *current_glyphs;
11596 struct glyph_row *glyph_row;
11597 struct glyph *glyph;
11598 int cursor_non_selected;
11600 /* This is pointless on invisible frames, and dangerous on garbaged
11601 windows and frames; in the latter case, the frame or window may
11602 be in the midst of changing its size, and x and y may be off the
11603 window. */
11604 if (! FRAME_VISIBLE_P (f)
11605 || FRAME_GARBAGED_P (f)
11606 || vpos >= w->current_matrix->nrows
11607 || hpos >= w->current_matrix->matrix_w)
11608 return;
11610 /* If cursor is off and we want it off, return quickly. */
11611 if (!on && !w->phys_cursor_on_p)
11612 return;
11614 current_glyphs = w->current_matrix;
11615 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11616 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11618 /* If cursor row is not enabled, we don't really know where to
11619 display the cursor. */
11620 if (!glyph_row->enabled_p)
11622 w->phys_cursor_on_p = 0;
11623 return;
11626 xassert (interrupt_input_blocked);
11628 /* Set new_cursor_type to the cursor we want to be displayed. In a
11629 mini-buffer window, we want the cursor only to appear if we are
11630 reading input from this window. For the selected window, we want
11631 the cursor type given by the frame parameter. If explicitly
11632 marked off, draw no cursor. In all other cases, we want a hollow
11633 box cursor. */
11634 cursor_non_selected
11635 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
11636 w->buffer));
11637 new_cursor_width = -1;
11638 if (cursor_in_echo_area
11639 && FRAME_HAS_MINIBUF_P (f)
11640 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11642 if (w == XWINDOW (echo_area_window))
11643 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11644 else if (cursor_non_selected)
11645 new_cursor_type = HOLLOW_BOX_CURSOR;
11646 else
11647 new_cursor_type = NO_CURSOR;
11649 else
11651 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11652 || w != XWINDOW (f->selected_window))
11654 if ((MINI_WINDOW_P (w) && minibuf_level == 0)
11655 || !cursor_non_selected
11656 || NILP (XBUFFER (w->buffer)->cursor_type))
11657 new_cursor_type = NO_CURSOR;
11658 else
11659 new_cursor_type = HOLLOW_BOX_CURSOR;
11661 else if (w->cursor_off_p)
11662 new_cursor_type = NO_CURSOR;
11663 else
11665 struct buffer *b = XBUFFER (w->buffer);
11667 if (EQ (b->cursor_type, Qt))
11668 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11669 else
11670 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11671 &new_cursor_width);
11675 /* If cursor is currently being shown and we don't want it to be or
11676 it is in the wrong place, or the cursor type is not what we want,
11677 erase it. */
11678 if (w->phys_cursor_on_p
11679 && (!on
11680 || w->phys_cursor.x != x
11681 || w->phys_cursor.y != y
11682 || new_cursor_type != w->phys_cursor_type))
11683 x_erase_phys_cursor (w);
11685 /* If the cursor is now invisible and we want it to be visible,
11686 display it. */
11687 if (on && !w->phys_cursor_on_p)
11689 w->phys_cursor_ascent = glyph_row->ascent;
11690 w->phys_cursor_height = glyph_row->height;
11692 /* Set phys_cursor_.* before x_draw_.* is called because some
11693 of them may need the information. */
11694 w->phys_cursor.x = x;
11695 w->phys_cursor.y = glyph_row->y;
11696 w->phys_cursor.hpos = hpos;
11697 w->phys_cursor.vpos = vpos;
11698 w->phys_cursor_type = new_cursor_type;
11699 w->phys_cursor_on_p = 1;
11701 switch (new_cursor_type)
11703 case HOLLOW_BOX_CURSOR:
11704 x_draw_hollow_cursor (w, glyph_row);
11705 break;
11707 case FILLED_BOX_CURSOR:
11708 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11709 break;
11711 case BAR_CURSOR:
11712 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11713 break;
11715 case NO_CURSOR:
11716 break;
11718 default:
11719 abort ();
11722 #ifdef HAVE_X_I18N
11723 if (w == XWINDOW (f->selected_window))
11724 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11725 xic_set_preeditarea (w, x, y);
11726 #endif
11729 #ifndef XFlush
11730 if (updating_frame != f)
11731 XFlush (FRAME_X_DISPLAY (f));
11732 #endif
11736 /* Display the cursor on window W, or clear it. X and Y are window
11737 relative pixel coordinates. HPOS and VPOS are glyph matrix
11738 positions. If W is not the selected window, display a hollow
11739 cursor. ON non-zero means display the cursor at X, Y which
11740 correspond to HPOS, VPOS, otherwise it is cleared. */
11742 void
11743 x_display_cursor (w, on, hpos, vpos, x, y)
11744 struct window *w;
11745 int on, hpos, vpos, x, y;
11747 BLOCK_INPUT;
11748 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11749 UNBLOCK_INPUT;
11753 /* Display the cursor on window W, or clear it, according to ON_P.
11754 Don't change the cursor's position. */
11756 void
11757 x_update_cursor (f, on_p)
11758 struct frame *f;
11760 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11764 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11765 in the window tree rooted at W. */
11767 static void
11768 x_update_cursor_in_window_tree (w, on_p)
11769 struct window *w;
11770 int on_p;
11772 while (w)
11774 if (!NILP (w->hchild))
11775 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11776 else if (!NILP (w->vchild))
11777 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11778 else
11779 x_update_window_cursor (w, on_p);
11781 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11786 /* Switch the display of W's cursor on or off, according to the value
11787 of ON. */
11789 static void
11790 x_update_window_cursor (w, on)
11791 struct window *w;
11792 int on;
11794 /* Don't update cursor in windows whose frame is in the process
11795 of being deleted. */
11796 if (w->current_matrix)
11798 BLOCK_INPUT;
11799 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11800 w->phys_cursor.x, w->phys_cursor.y);
11801 UNBLOCK_INPUT;
11808 /* Icons. */
11810 /* Make the x-window of frame F use the gnu icon bitmap. */
11813 x_bitmap_icon (f, file)
11814 struct frame *f;
11815 Lisp_Object file;
11817 int bitmap_id;
11819 if (FRAME_X_WINDOW (f) == 0)
11820 return 1;
11822 /* Free up our existing icon bitmap if any. */
11823 if (f->output_data.x->icon_bitmap > 0)
11824 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11825 f->output_data.x->icon_bitmap = 0;
11827 if (STRINGP (file))
11828 bitmap_id = x_create_bitmap_from_file (f, file);
11829 else
11831 /* Create the GNU bitmap if necessary. */
11832 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11833 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11834 = x_create_bitmap_from_data (f, gnu_bits,
11835 gnu_width, gnu_height);
11837 /* The first time we create the GNU bitmap,
11838 this increments the ref-count one extra time.
11839 As a result, the GNU bitmap is never freed.
11840 That way, we don't have to worry about allocating it again. */
11841 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11843 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11846 x_wm_set_icon_pixmap (f, bitmap_id);
11847 f->output_data.x->icon_bitmap = bitmap_id;
11849 return 0;
11853 /* Make the x-window of frame F use a rectangle with text.
11854 Use ICON_NAME as the text. */
11857 x_text_icon (f, icon_name)
11858 struct frame *f;
11859 char *icon_name;
11861 if (FRAME_X_WINDOW (f) == 0)
11862 return 1;
11864 #ifdef HAVE_X11R4
11866 XTextProperty text;
11867 text.value = (unsigned char *) icon_name;
11868 text.encoding = XA_STRING;
11869 text.format = 8;
11870 text.nitems = strlen (icon_name);
11871 #ifdef USE_X_TOOLKIT
11872 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11873 &text);
11874 #else /* not USE_X_TOOLKIT */
11875 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11876 #endif /* not USE_X_TOOLKIT */
11878 #else /* not HAVE_X11R4 */
11879 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11880 #endif /* not HAVE_X11R4 */
11882 if (f->output_data.x->icon_bitmap > 0)
11883 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11884 f->output_data.x->icon_bitmap = 0;
11885 x_wm_set_icon_pixmap (f, 0);
11887 return 0;
11890 #define X_ERROR_MESSAGE_SIZE 200
11892 /* If non-nil, this should be a string.
11893 It means catch X errors and store the error message in this string. */
11895 static Lisp_Object x_error_message_string;
11897 /* An X error handler which stores the error message in
11898 x_error_message_string. This is called from x_error_handler if
11899 x_catch_errors is in effect. */
11901 static void
11902 x_error_catcher (display, error)
11903 Display *display;
11904 XErrorEvent *error;
11906 XGetErrorText (display, error->error_code,
11907 XSTRING (x_error_message_string)->data,
11908 X_ERROR_MESSAGE_SIZE);
11911 /* Begin trapping X errors for display DPY. Actually we trap X errors
11912 for all displays, but DPY should be the display you are actually
11913 operating on.
11915 After calling this function, X protocol errors no longer cause
11916 Emacs to exit; instead, they are recorded in the string
11917 stored in x_error_message_string.
11919 Calling x_check_errors signals an Emacs error if an X error has
11920 occurred since the last call to x_catch_errors or x_check_errors.
11922 Calling x_uncatch_errors resumes the normal error handling. */
11924 void x_check_errors ();
11925 static Lisp_Object x_catch_errors_unwind ();
11928 x_catch_errors (dpy)
11929 Display *dpy;
11931 int count = specpdl_ptr - specpdl;
11933 /* Make sure any errors from previous requests have been dealt with. */
11934 XSync (dpy, False);
11936 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11938 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11939 XSTRING (x_error_message_string)->data[0] = 0;
11941 return count;
11944 /* Unbind the binding that we made to check for X errors. */
11946 static Lisp_Object
11947 x_catch_errors_unwind (old_val)
11948 Lisp_Object old_val;
11950 x_error_message_string = old_val;
11951 return Qnil;
11954 /* If any X protocol errors have arrived since the last call to
11955 x_catch_errors or x_check_errors, signal an Emacs error using
11956 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11958 void
11959 x_check_errors (dpy, format)
11960 Display *dpy;
11961 char *format;
11963 /* Make sure to catch any errors incurred so far. */
11964 XSync (dpy, False);
11966 if (XSTRING (x_error_message_string)->data[0])
11967 error (format, XSTRING (x_error_message_string)->data);
11970 /* Nonzero if we had any X protocol errors
11971 since we did x_catch_errors on DPY. */
11974 x_had_errors_p (dpy)
11975 Display *dpy;
11977 /* Make sure to catch any errors incurred so far. */
11978 XSync (dpy, False);
11980 return XSTRING (x_error_message_string)->data[0] != 0;
11983 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11985 void
11986 x_clear_errors (dpy)
11987 Display *dpy;
11989 XSTRING (x_error_message_string)->data[0] = 0;
11992 /* Stop catching X protocol errors and let them make Emacs die.
11993 DPY should be the display that was passed to x_catch_errors.
11994 COUNT should be the value that was returned by
11995 the corresponding call to x_catch_errors. */
11997 void
11998 x_uncatch_errors (dpy, count)
11999 Display *dpy;
12000 int count;
12002 unbind_to (count, Qnil);
12005 #if 0
12006 static unsigned int x_wire_count;
12007 x_trace_wire ()
12009 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
12011 #endif /* ! 0 */
12014 /* Handle SIGPIPE, which can happen when the connection to a server
12015 simply goes away. SIGPIPE is handled by x_connection_signal.
12016 Don't need to do anything, because the write which caused the
12017 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12018 which will do the appropriate cleanup for us. */
12020 static SIGTYPE
12021 x_connection_signal (signalnum) /* If we don't have an argument, */
12022 int signalnum; /* some compilers complain in signal calls. */
12024 #ifdef USG
12025 /* USG systems forget handlers when they are used;
12026 must reestablish each time */
12027 signal (signalnum, x_connection_signal);
12028 #endif /* USG */
12032 /************************************************************************
12033 Handling X errors
12034 ************************************************************************/
12036 /* Error message passed to x_connection_closed. */
12038 static char *error_msg;
12040 /* Function installed as fatal_error_signal_hook in
12041 x_connection_closed. Print the X error message, and exit normally,
12042 instead of dumping core when XtCloseDisplay fails. */
12044 static void
12045 x_fatal_error_signal ()
12047 fprintf (stderr, "%s\n", error_msg);
12048 exit (70);
12051 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12052 the text of an error message that lead to the connection loss. */
12054 static SIGTYPE
12055 x_connection_closed (dpy, error_message)
12056 Display *dpy;
12057 char *error_message;
12059 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
12060 Lisp_Object frame, tail;
12061 int count;
12063 error_msg = (char *) alloca (strlen (error_message) + 1);
12064 strcpy (error_msg, error_message);
12065 handling_signal = 0;
12067 /* Prevent being called recursively because of an error condition
12068 below. Otherwise, we might end up with printing ``can't find per
12069 display information'' in the recursive call instead of printing
12070 the original message here. */
12071 count = x_catch_errors (dpy);
12073 /* We have to close the display to inform Xt that it doesn't
12074 exist anymore. If we don't, Xt will continue to wait for
12075 events from the display. As a consequence, a sequence of
12077 M-x make-frame-on-display RET :1 RET
12078 ...kill the new frame, so that we get an IO error...
12079 M-x make-frame-on-display RET :1 RET
12081 will indefinitely wait in Xt for events for display `:1', opened
12082 in the first class to make-frame-on-display.
12084 Closing the display is reported to lead to a bus error on
12085 OpenWindows in certain situations. I suspect that is a bug
12086 in OpenWindows. I don't know how to cicumvent it here. */
12088 #ifdef USE_X_TOOLKIT
12089 /* If DPYINFO is null, this means we didn't open the display
12090 in the first place, so don't try to close it. */
12091 if (dpyinfo)
12093 extern void (*fatal_error_signal_hook) P_ ((void));
12094 fatal_error_signal_hook = x_fatal_error_signal;
12095 XtCloseDisplay (dpy);
12096 fatal_error_signal_hook = NULL;
12098 #endif
12100 /* Indicate that this display is dead. */
12101 if (dpyinfo)
12102 dpyinfo->display = 0;
12104 /* First delete frames whose mini-buffers are on frames
12105 that are on the dead display. */
12106 FOR_EACH_FRAME (tail, frame)
12108 Lisp_Object minibuf_frame;
12109 minibuf_frame
12110 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
12111 if (FRAME_X_P (XFRAME (frame))
12112 && FRAME_X_P (XFRAME (minibuf_frame))
12113 && ! EQ (frame, minibuf_frame)
12114 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
12115 Fdelete_frame (frame, Qt);
12118 /* Now delete all remaining frames on the dead display.
12119 We are now sure none of these is used as the mini-buffer
12120 for another frame that we need to delete. */
12121 FOR_EACH_FRAME (tail, frame)
12122 if (FRAME_X_P (XFRAME (frame))
12123 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12125 /* Set this to t so that Fdelete_frame won't get confused
12126 trying to find a replacement. */
12127 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12128 Fdelete_frame (frame, Qt);
12131 if (dpyinfo)
12132 x_delete_display (dpyinfo);
12134 x_uncatch_errors (dpy, count);
12136 if (x_display_list == 0)
12138 fprintf (stderr, "%s\n", error_msg);
12139 shut_down_emacs (0, 0, Qnil);
12140 exit (70);
12143 /* Ordinary stack unwind doesn't deal with these. */
12144 #ifdef SIGIO
12145 sigunblock (sigmask (SIGIO));
12146 #endif
12147 sigunblock (sigmask (SIGALRM));
12148 TOTALLY_UNBLOCK_INPUT;
12150 clear_waiting_for_input ();
12151 error ("%s", error_msg);
12155 /* This is the usual handler for X protocol errors.
12156 It kills all frames on the display that we got the error for.
12157 If that was the only one, it prints an error message and kills Emacs. */
12159 static void
12160 x_error_quitter (display, error)
12161 Display *display;
12162 XErrorEvent *error;
12164 char buf[256], buf1[356];
12166 /* Note that there is no real way portable across R3/R4 to get the
12167 original error handler. */
12169 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12170 sprintf (buf1, "X protocol error: %s on protocol request %d",
12171 buf, error->request_code);
12172 x_connection_closed (display, buf1);
12176 /* This is the first-level handler for X protocol errors.
12177 It calls x_error_quitter or x_error_catcher. */
12179 static int
12180 x_error_handler (display, error)
12181 Display *display;
12182 XErrorEvent *error;
12184 if (! NILP (x_error_message_string))
12185 x_error_catcher (display, error);
12186 else
12187 x_error_quitter (display, error);
12188 return 0;
12191 /* This is the handler for X IO errors, always.
12192 It kills all frames on the display that we lost touch with.
12193 If that was the only one, it prints an error message and kills Emacs. */
12195 static int
12196 x_io_error_quitter (display)
12197 Display *display;
12199 char buf[256];
12201 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12202 x_connection_closed (display, buf);
12203 return 0;
12206 /* Changing the font of the frame. */
12208 /* Give frame F the font named FONTNAME as its default font, and
12209 return the full name of that font. FONTNAME may be a wildcard
12210 pattern; in that case, we choose some font that fits the pattern.
12211 The return value shows which font we chose. */
12213 Lisp_Object
12214 x_new_font (f, fontname)
12215 struct frame *f;
12216 register char *fontname;
12218 struct font_info *fontp
12219 = FS_LOAD_FONT (f, fontname);
12221 if (!fontp)
12222 return Qnil;
12224 f->output_data.x->font = (XFontStruct *) (fontp->font);
12225 f->output_data.x->baseline_offset = fontp->baseline_offset;
12226 f->output_data.x->fontset = -1;
12228 x_compute_fringe_widths (f, 1);
12230 /* Compute the scroll bar width in character columns. */
12231 if (f->scroll_bar_pixel_width > 0)
12233 int wid = FONT_WIDTH (f->output_data.x->font);
12234 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12236 else
12238 int wid = FONT_WIDTH (f->output_data.x->font);
12239 f->scroll_bar_cols = (14 + wid - 1) / wid;
12242 /* Now make the frame display the given font. */
12243 if (FRAME_X_WINDOW (f) != 0)
12245 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12246 f->output_data.x->font->fid);
12247 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12248 f->output_data.x->font->fid);
12249 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12250 f->output_data.x->font->fid);
12252 frame_update_line_height (f);
12254 /* Don't change the size of a tip frame; there's no point in
12255 doing it because it's done in Fx_show_tip, and it leads to
12256 problems because the tip frame has no widget. */
12257 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12258 x_set_window_size (f, 0, f->width, f->height);
12260 else
12261 /* If we are setting a new frame's font for the first time,
12262 there are no faces yet, so this font's height is the line height. */
12263 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12265 return build_string (fontp->full_name);
12268 /* Give frame F the fontset named FONTSETNAME as its default font, and
12269 return the full name of that fontset. FONTSETNAME may be a wildcard
12270 pattern; in that case, we choose some fontset that fits the pattern.
12271 The return value shows which fontset we chose. */
12273 Lisp_Object
12274 x_new_fontset (f, fontsetname)
12275 struct frame *f;
12276 char *fontsetname;
12278 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12279 Lisp_Object result;
12281 if (fontset < 0)
12282 return Qnil;
12284 if (f->output_data.x->fontset == fontset)
12285 /* This fontset is already set in frame F. There's nothing more
12286 to do. */
12287 return fontset_name (fontset);
12289 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
12291 if (!STRINGP (result))
12292 /* Can't load ASCII font. */
12293 return Qnil;
12295 /* Since x_new_font doesn't update any fontset information, do it now. */
12296 f->output_data.x->fontset = fontset;
12298 #ifdef HAVE_X_I18N
12299 if (FRAME_XIC (f)
12300 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12301 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
12302 #endif
12304 return build_string (fontsetname);
12307 /* Compute actual fringe widths */
12309 void
12310 x_compute_fringe_widths (f, redraw)
12311 struct frame *f;
12312 int redraw;
12314 int o_left = f->output_data.x->left_fringe_width;
12315 int o_right = f->output_data.x->right_fringe_width;
12316 int o_cols = f->output_data.x->fringe_cols;
12318 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12319 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12320 int left_fringe_width, right_fringe_width;
12322 if (!NILP (left_fringe))
12323 left_fringe = Fcdr (left_fringe);
12324 if (!NILP (right_fringe))
12325 right_fringe = Fcdr (right_fringe);
12327 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12328 XINT (left_fringe));
12329 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12330 XINT (right_fringe));
12332 if (left_fringe_width || right_fringe_width)
12334 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12335 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12336 int conf_wid = left_wid + right_wid;
12337 int font_wid = FONT_WIDTH (f->output_data.x->font);
12338 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12339 int real_wid = cols * font_wid;
12340 if (left_wid && right_wid)
12342 if (left_fringe_width < 0)
12344 /* Left fringe width is fixed, adjust right fringe if necessary */
12345 f->output_data.x->left_fringe_width = left_wid;
12346 f->output_data.x->right_fringe_width = real_wid - left_wid;
12348 else if (right_fringe_width < 0)
12350 /* Right fringe width is fixed, adjust left fringe if necessary */
12351 f->output_data.x->left_fringe_width = real_wid - right_wid;
12352 f->output_data.x->right_fringe_width = right_wid;
12354 else
12356 /* Adjust both fringes with an equal amount.
12357 Note that we are doing integer arithmetic here, so don't
12358 lose a pixel if the total width is an odd number. */
12359 int fill = real_wid - conf_wid;
12360 f->output_data.x->left_fringe_width = left_wid + fill/2;
12361 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12364 else if (left_fringe_width)
12366 f->output_data.x->left_fringe_width = real_wid;
12367 f->output_data.x->right_fringe_width = 0;
12369 else
12371 f->output_data.x->left_fringe_width = 0;
12372 f->output_data.x->right_fringe_width = real_wid;
12374 f->output_data.x->fringe_cols = cols;
12375 f->output_data.x->fringes_extra = real_wid;
12377 else
12379 f->output_data.x->left_fringe_width = 0;
12380 f->output_data.x->right_fringe_width = 0;
12381 f->output_data.x->fringe_cols = 0;
12382 f->output_data.x->fringes_extra = 0;
12385 if (redraw && FRAME_VISIBLE_P (f))
12386 if (o_left != f->output_data.x->left_fringe_width ||
12387 o_right != f->output_data.x->right_fringe_width ||
12388 o_cols != f->output_data.x->fringe_cols)
12389 redraw_frame (f);
12392 /***********************************************************************
12393 X Input Methods
12394 ***********************************************************************/
12396 #ifdef HAVE_X_I18N
12398 #ifdef HAVE_X11R6
12400 /* XIM destroy callback function, which is called whenever the
12401 connection to input method XIM dies. CLIENT_DATA contains a
12402 pointer to the x_display_info structure corresponding to XIM. */
12404 static void
12405 xim_destroy_callback (xim, client_data, call_data)
12406 XIM xim;
12407 XPointer client_data;
12408 XPointer call_data;
12410 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12411 Lisp_Object frame, tail;
12413 BLOCK_INPUT;
12415 /* No need to call XDestroyIC.. */
12416 FOR_EACH_FRAME (tail, frame)
12418 struct frame *f = XFRAME (frame);
12419 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12421 FRAME_XIC (f) = NULL;
12422 if (FRAME_XIC_FONTSET (f))
12424 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12425 FRAME_XIC_FONTSET (f) = NULL;
12430 /* No need to call XCloseIM. */
12431 dpyinfo->xim = NULL;
12432 XFree (dpyinfo->xim_styles);
12433 UNBLOCK_INPUT;
12436 #endif /* HAVE_X11R6 */
12438 /* Open the connection to the XIM server on display DPYINFO.
12439 RESOURCE_NAME is the resource name Emacs uses. */
12441 static void
12442 xim_open_dpy (dpyinfo, resource_name)
12443 struct x_display_info *dpyinfo;
12444 char *resource_name;
12446 #ifdef USE_XIM
12447 XIM xim;
12449 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12450 dpyinfo->xim = xim;
12452 if (xim)
12454 #ifdef HAVE_X11R6
12455 XIMCallback destroy;
12456 #endif
12458 /* Get supported styles and XIM values. */
12459 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12461 #ifdef HAVE_X11R6
12462 destroy.callback = xim_destroy_callback;
12463 destroy.client_data = (XPointer)dpyinfo;
12464 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12465 #endif
12468 #else /* not USE_XIM */
12469 dpyinfo->xim = NULL;
12470 #endif /* not USE_XIM */
12474 #ifdef HAVE_X11R6_XIM
12476 struct xim_inst_t
12478 struct x_display_info *dpyinfo;
12479 char *resource_name;
12482 /* XIM instantiate callback function, which is called whenever an XIM
12483 server is available. DISPLAY is teh display of the XIM.
12484 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12485 when the callback was registered. */
12487 static void
12488 xim_instantiate_callback (display, client_data, call_data)
12489 Display *display;
12490 XPointer client_data;
12491 XPointer call_data;
12493 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12494 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12496 /* We don't support multiple XIM connections. */
12497 if (dpyinfo->xim)
12498 return;
12500 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12502 /* Create XIC for the existing frames on the same display, as long
12503 as they have no XIC. */
12504 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12506 Lisp_Object tail, frame;
12508 BLOCK_INPUT;
12509 FOR_EACH_FRAME (tail, frame)
12511 struct frame *f = XFRAME (frame);
12513 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12514 if (FRAME_XIC (f) == NULL)
12516 create_frame_xic (f);
12517 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12518 xic_set_statusarea (f);
12519 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12521 struct window *w = XWINDOW (f->selected_window);
12522 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12527 UNBLOCK_INPUT;
12531 #endif /* HAVE_X11R6_XIM */
12534 /* Open a connection to the XIM server on display DPYINFO.
12535 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12536 connection only at the first time. On X11R6, open the connection
12537 in the XIM instantiate callback function. */
12539 static void
12540 xim_initialize (dpyinfo, resource_name)
12541 struct x_display_info *dpyinfo;
12542 char *resource_name;
12544 #ifdef USE_XIM
12545 #ifdef HAVE_X11R6_XIM
12546 struct xim_inst_t *xim_inst;
12547 int len;
12549 dpyinfo->xim = NULL;
12550 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12551 xim_inst->dpyinfo = dpyinfo;
12552 len = strlen (resource_name);
12553 xim_inst->resource_name = (char *) xmalloc (len + 1);
12554 bcopy (resource_name, xim_inst->resource_name, len + 1);
12555 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12556 resource_name, EMACS_CLASS,
12557 xim_instantiate_callback,
12558 /* Fixme: This is XPointer in
12559 XFree86 but (XPointer *) on
12560 Tru64, at least. */
12561 (XPointer) xim_inst);
12562 #else /* not HAVE_X11R6_XIM */
12563 dpyinfo->xim = NULL;
12564 xim_open_dpy (dpyinfo, resource_name);
12565 #endif /* not HAVE_X11R6_XIM */
12567 #else /* not USE_XIM */
12568 dpyinfo->xim = NULL;
12569 #endif /* not USE_XIM */
12573 /* Close the connection to the XIM server on display DPYINFO. */
12575 static void
12576 xim_close_dpy (dpyinfo)
12577 struct x_display_info *dpyinfo;
12579 #ifdef USE_XIM
12580 #ifdef HAVE_X11R6_XIM
12581 if (dpyinfo->display)
12582 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12583 NULL, EMACS_CLASS,
12584 xim_instantiate_callback, NULL);
12585 #endif /* not HAVE_X11R6_XIM */
12586 if (dpyinfo->display)
12587 XCloseIM (dpyinfo->xim);
12588 dpyinfo->xim = NULL;
12589 XFree (dpyinfo->xim_styles);
12590 #endif /* USE_XIM */
12593 #endif /* not HAVE_X11R6_XIM */
12597 /* Calculate the absolute position in frame F
12598 from its current recorded position values and gravity. */
12600 void
12601 x_calc_absolute_position (f)
12602 struct frame *f;
12604 Window child;
12605 int win_x = 0, win_y = 0;
12606 int flags = f->output_data.x->size_hint_flags;
12607 int this_window;
12609 /* We have nothing to do if the current position
12610 is already for the top-left corner. */
12611 if (! ((flags & XNegative) || (flags & YNegative)))
12612 return;
12614 #ifdef USE_X_TOOLKIT
12615 this_window = XtWindow (f->output_data.x->widget);
12616 #else
12617 this_window = FRAME_X_WINDOW (f);
12618 #endif
12620 /* Find the position of the outside upper-left corner of
12621 the inner window, with respect to the outer window.
12622 But do this only if we will need the results. */
12623 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12625 int count;
12627 BLOCK_INPUT;
12628 count = x_catch_errors (FRAME_X_DISPLAY (f));
12629 while (1)
12631 x_clear_errors (FRAME_X_DISPLAY (f));
12632 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12634 /* From-window, to-window. */
12635 this_window,
12636 f->output_data.x->parent_desc,
12638 /* From-position, to-position. */
12639 0, 0, &win_x, &win_y,
12641 /* Child of win. */
12642 &child);
12643 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12645 Window newroot, newparent = 0xdeadbeef;
12646 Window *newchildren;
12647 unsigned int nchildren;
12649 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12650 &newparent, &newchildren, &nchildren))
12651 break;
12653 XFree ((char *) newchildren);
12655 f->output_data.x->parent_desc = newparent;
12657 else
12658 break;
12661 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12662 UNBLOCK_INPUT;
12665 /* Treat negative positions as relative to the leftmost bottommost
12666 position that fits on the screen. */
12667 if (flags & XNegative)
12668 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12669 - 2 * f->output_data.x->border_width - win_x
12670 - PIXEL_WIDTH (f)
12671 + f->output_data.x->left_pos);
12674 int height = PIXEL_HEIGHT (f);
12676 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12677 /* Something is fishy here. When using Motif, starting Emacs with
12678 `-g -0-0', the frame appears too low by a few pixels.
12680 This seems to be so because initially, while Emacs is starting,
12681 the column widget's height and the frame's pixel height are
12682 different. The column widget's height is the right one. In
12683 later invocations, when Emacs is up, the frame's pixel height
12684 is right, though.
12686 It's not obvious where the initial small difference comes from.
12687 2000-12-01, gerd. */
12689 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12690 #endif
12692 if (flags & YNegative)
12693 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12694 - 2 * f->output_data.x->border_width
12695 - win_y
12696 - height
12697 + f->output_data.x->top_pos);
12700 /* The left_pos and top_pos
12701 are now relative to the top and left screen edges,
12702 so the flags should correspond. */
12703 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12706 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12707 to really change the position, and 0 when calling from
12708 x_make_frame_visible (in that case, XOFF and YOFF are the current
12709 position values). It is -1 when calling from x_set_frame_parameters,
12710 which means, do adjust for borders but don't change the gravity. */
12712 void
12713 x_set_offset (f, xoff, yoff, change_gravity)
12714 struct frame *f;
12715 register int xoff, yoff;
12716 int change_gravity;
12718 int modified_top, modified_left;
12720 if (change_gravity > 0)
12722 f->output_data.x->top_pos = yoff;
12723 f->output_data.x->left_pos = xoff;
12724 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12725 if (xoff < 0)
12726 f->output_data.x->size_hint_flags |= XNegative;
12727 if (yoff < 0)
12728 f->output_data.x->size_hint_flags |= YNegative;
12729 f->output_data.x->win_gravity = NorthWestGravity;
12731 x_calc_absolute_position (f);
12733 BLOCK_INPUT;
12734 x_wm_set_size_hint (f, (long) 0, 0);
12736 modified_left = f->output_data.x->left_pos;
12737 modified_top = f->output_data.x->top_pos;
12738 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12739 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12740 /* It is a mystery why we need to add the border_width here
12741 when the frame is already visible, but experiment says we do. */
12742 if (change_gravity != 0)
12744 modified_left += f->output_data.x->border_width;
12745 modified_top += f->output_data.x->border_width;
12747 #endif
12749 #ifdef USE_X_TOOLKIT
12750 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12751 modified_left, modified_top);
12752 #else /* not USE_X_TOOLKIT */
12753 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12754 modified_left, modified_top);
12755 #endif /* not USE_X_TOOLKIT */
12756 UNBLOCK_INPUT;
12759 /* Check if we need to resize the frame due to a fullscreen request.
12760 If so needed, resize the frame. */
12761 static void
12762 x_check_fullscreen (f)
12763 struct frame *f;
12765 if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
12767 int width, height, ign;
12769 x_real_positions (f, &f->output_data.x->left_pos,
12770 &f->output_data.x->top_pos);
12772 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
12774 /* We do not need to move the window, it shall be taken care of
12775 when setting WM manager hints.
12776 If the frame is visible already, the position is checked by
12777 x_check_fullscreen_move. */
12778 if (f->width != width || f->height != height)
12780 change_frame_size (f, height, width, 0, 1, 0);
12781 SET_FRAME_GARBAGED (f);
12782 cancel_mouse_face (f);
12784 /* Wait for the change of frame size to occur */
12785 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
12791 /* If frame parameters are set after the frame is mapped, we need to move
12792 the window. This is done in xfns.c.
12793 Some window managers moves the window to the right position, some
12794 moves the outer window manager window to the specified position.
12795 Here we check that we are in the right spot. If not, make a second
12796 move, assuming we are dealing with the second kind of window manager. */
12797 static void
12798 x_check_fullscreen_move (f)
12799 struct frame *f;
12801 if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
12803 int expect_top = f->output_data.x->top_pos;
12804 int expect_left = f->output_data.x->left_pos;
12806 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
12807 expect_top = 0;
12808 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
12809 expect_left = 0;
12811 if (expect_top != f->output_data.x->top_pos
12812 || expect_left != f->output_data.x->left_pos)
12813 x_set_offset (f, expect_left, expect_top, 1);
12815 /* Just do this once */
12816 f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
12821 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
12822 wanted positions of the WM window (not emacs window).
12823 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
12824 window (FRAME_X_WINDOW).
12826 void
12827 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
12828 struct frame *f;
12829 int *width;
12830 int *height;
12831 int *top_pos;
12832 int *left_pos;
12834 int newwidth = f->width, newheight = f->height;
12836 *top_pos = f->output_data.x->top_pos;
12837 *left_pos = f->output_data.x->left_pos;
12839 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
12841 int ph;
12843 ph = FRAME_X_DISPLAY_INFO (f)->height;
12844 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
12845 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
12846 - f->output_data.x->y_pixels_diff;
12847 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
12848 *top_pos = 0;
12851 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
12853 int pw;
12855 pw = FRAME_X_DISPLAY_INFO (f)->width;
12856 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
12857 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
12858 - f->output_data.x->x_pixels_diff;
12859 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
12860 *left_pos = 0;
12863 *width = newwidth;
12864 *height = newheight;
12868 /* Change the size of frame F's X window to COLS/ROWS in the case F
12869 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12870 top-left-corner window gravity for this size change and subsequent
12871 size changes. Otherwise we leave the window gravity unchanged. */
12873 static void
12874 x_set_window_size_1 (f, change_gravity, cols, rows)
12875 struct frame *f;
12876 int change_gravity;
12877 int cols, rows;
12879 int pixelwidth, pixelheight;
12881 check_frame_size (f, &rows, &cols);
12882 f->output_data.x->vertical_scroll_bar_extra
12883 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12885 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12886 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12887 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12889 x_compute_fringe_widths (f, 0);
12891 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12892 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12894 f->output_data.x->win_gravity = NorthWestGravity;
12895 x_wm_set_size_hint (f, (long) 0, 0);
12897 XSync (FRAME_X_DISPLAY (f), False);
12898 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12899 pixelwidth, pixelheight);
12901 /* Now, strictly speaking, we can't be sure that this is accurate,
12902 but the window manager will get around to dealing with the size
12903 change request eventually, and we'll hear how it went when the
12904 ConfigureNotify event gets here.
12906 We could just not bother storing any of this information here,
12907 and let the ConfigureNotify event set everything up, but that
12908 might be kind of confusing to the Lisp code, since size changes
12909 wouldn't be reported in the frame parameters until some random
12910 point in the future when the ConfigureNotify event arrives.
12912 We pass 1 for DELAY since we can't run Lisp code inside of
12913 a BLOCK_INPUT. */
12914 change_frame_size (f, rows, cols, 0, 1, 0);
12915 PIXEL_WIDTH (f) = pixelwidth;
12916 PIXEL_HEIGHT (f) = pixelheight;
12918 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12919 receive in the ConfigureNotify event; if we get what we asked
12920 for, then the event won't cause the screen to become garbaged, so
12921 we have to make sure to do it here. */
12922 SET_FRAME_GARBAGED (f);
12924 XFlush (FRAME_X_DISPLAY (f));
12928 /* Call this to change the size of frame F's x-window.
12929 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12930 for this size change and subsequent size changes.
12931 Otherwise we leave the window gravity unchanged. */
12933 void
12934 x_set_window_size (f, change_gravity, cols, rows)
12935 struct frame *f;
12936 int change_gravity;
12937 int cols, rows;
12939 BLOCK_INPUT;
12941 #ifdef USE_X_TOOLKIT
12943 if (f->output_data.x->widget != NULL)
12945 /* The x and y position of the widget is clobbered by the
12946 call to XtSetValues within EmacsFrameSetCharSize.
12947 This is a real kludge, but I don't understand Xt so I can't
12948 figure out a correct fix. Can anyone else tell me? -- rms. */
12949 int xpos = f->output_data.x->widget->core.x;
12950 int ypos = f->output_data.x->widget->core.y;
12951 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12952 f->output_data.x->widget->core.x = xpos;
12953 f->output_data.x->widget->core.y = ypos;
12955 else
12956 x_set_window_size_1 (f, change_gravity, cols, rows);
12958 #else /* not USE_X_TOOLKIT */
12960 x_set_window_size_1 (f, change_gravity, cols, rows);
12962 #endif /* not USE_X_TOOLKIT */
12964 /* If cursor was outside the new size, mark it as off. */
12965 mark_window_cursors_off (XWINDOW (f->root_window));
12967 /* Clear out any recollection of where the mouse highlighting was,
12968 since it might be in a place that's outside the new frame size.
12969 Actually checking whether it is outside is a pain in the neck,
12970 so don't try--just let the highlighting be done afresh with new size. */
12971 cancel_mouse_face (f);
12973 UNBLOCK_INPUT;
12976 /* Mouse warping. */
12978 void
12979 x_set_mouse_position (f, x, y)
12980 struct frame *f;
12981 int x, y;
12983 int pix_x, pix_y;
12985 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12986 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12988 if (pix_x < 0) pix_x = 0;
12989 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12991 if (pix_y < 0) pix_y = 0;
12992 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12994 BLOCK_INPUT;
12996 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12997 0, 0, 0, 0, pix_x, pix_y);
12998 UNBLOCK_INPUT;
13001 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13003 void
13004 x_set_mouse_pixel_position (f, pix_x, pix_y)
13005 struct frame *f;
13006 int pix_x, pix_y;
13008 BLOCK_INPUT;
13010 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13011 0, 0, 0, 0, pix_x, pix_y);
13012 UNBLOCK_INPUT;
13015 /* focus shifting, raising and lowering. */
13017 void
13018 x_focus_on_frame (f)
13019 struct frame *f;
13021 #if 0 /* This proves to be unpleasant. */
13022 x_raise_frame (f);
13023 #endif
13024 #if 0
13025 /* I don't think that the ICCCM allows programs to do things like this
13026 without the interaction of the window manager. Whatever you end up
13027 doing with this code, do it to x_unfocus_frame too. */
13028 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13029 RevertToPointerRoot, CurrentTime);
13030 #endif /* ! 0 */
13033 void
13034 x_unfocus_frame (f)
13035 struct frame *f;
13037 #if 0
13038 /* Look at the remarks in x_focus_on_frame. */
13039 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
13040 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
13041 RevertToPointerRoot, CurrentTime);
13042 #endif /* ! 0 */
13045 /* Raise frame F. */
13047 void
13048 x_raise_frame (f)
13049 struct frame *f;
13051 if (f->async_visible)
13053 BLOCK_INPUT;
13054 #ifdef USE_X_TOOLKIT
13055 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13056 #else /* not USE_X_TOOLKIT */
13057 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13058 #endif /* not USE_X_TOOLKIT */
13059 XFlush (FRAME_X_DISPLAY (f));
13060 UNBLOCK_INPUT;
13064 /* Lower frame F. */
13066 void
13067 x_lower_frame (f)
13068 struct frame *f;
13070 if (f->async_visible)
13072 BLOCK_INPUT;
13073 #ifdef USE_X_TOOLKIT
13074 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13075 #else /* not USE_X_TOOLKIT */
13076 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13077 #endif /* not USE_X_TOOLKIT */
13078 XFlush (FRAME_X_DISPLAY (f));
13079 UNBLOCK_INPUT;
13083 static void
13084 XTframe_raise_lower (f, raise_flag)
13085 FRAME_PTR f;
13086 int raise_flag;
13088 if (raise_flag)
13089 x_raise_frame (f);
13090 else
13091 x_lower_frame (f);
13094 /* Change of visibility. */
13096 /* This tries to wait until the frame is really visible.
13097 However, if the window manager asks the user where to position
13098 the frame, this will return before the user finishes doing that.
13099 The frame will not actually be visible at that time,
13100 but it will become visible later when the window manager
13101 finishes with it. */
13103 void
13104 x_make_frame_visible (f)
13105 struct frame *f;
13107 Lisp_Object type;
13108 int original_top, original_left;
13109 int retry_count = 2;
13111 retry:
13113 BLOCK_INPUT;
13115 type = x_icon_type (f);
13116 if (!NILP (type))
13117 x_bitmap_icon (f, type);
13119 if (! FRAME_VISIBLE_P (f))
13121 /* We test FRAME_GARBAGED_P here to make sure we don't
13122 call x_set_offset a second time
13123 if we get to x_make_frame_visible a second time
13124 before the window gets really visible. */
13125 if (! FRAME_ICONIFIED_P (f)
13126 && ! f->output_data.x->asked_for_visible)
13127 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13129 f->output_data.x->asked_for_visible = 1;
13131 if (! EQ (Vx_no_window_manager, Qt))
13132 x_wm_set_window_state (f, NormalState);
13133 #ifdef USE_X_TOOLKIT
13134 /* This was XtPopup, but that did nothing for an iconified frame. */
13135 XtMapWidget (f->output_data.x->widget);
13136 #else /* not USE_X_TOOLKIT */
13137 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13138 #endif /* not USE_X_TOOLKIT */
13139 #if 0 /* This seems to bring back scroll bars in the wrong places
13140 if the window configuration has changed. They seem
13141 to come back ok without this. */
13142 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
13143 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13144 #endif
13147 XFlush (FRAME_X_DISPLAY (f));
13149 /* Synchronize to ensure Emacs knows the frame is visible
13150 before we do anything else. We do this loop with input not blocked
13151 so that incoming events are handled. */
13153 Lisp_Object frame;
13154 int count;
13155 /* This must be before UNBLOCK_INPUT
13156 since events that arrive in response to the actions above
13157 will set it when they are handled. */
13158 int previously_visible = f->output_data.x->has_been_visible;
13160 original_left = f->output_data.x->left_pos;
13161 original_top = f->output_data.x->top_pos;
13163 /* This must come after we set COUNT. */
13164 UNBLOCK_INPUT;
13166 /* We unblock here so that arriving X events are processed. */
13168 /* Now move the window back to where it was "supposed to be".
13169 But don't do it if the gravity is negative.
13170 When the gravity is negative, this uses a position
13171 that is 3 pixels too low. Perhaps that's really the border width.
13173 Don't do this if the window has never been visible before,
13174 because the window manager may choose the position
13175 and we don't want to override it. */
13177 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
13178 && f->output_data.x->win_gravity == NorthWestGravity
13179 && previously_visible)
13181 Drawable rootw;
13182 int x, y;
13183 unsigned int width, height, border, depth;
13185 BLOCK_INPUT;
13187 /* On some window managers (such as FVWM) moving an existing
13188 window, even to the same place, causes the window manager
13189 to introduce an offset. This can cause the window to move
13190 to an unexpected location. Check the geometry (a little
13191 slow here) and then verify that the window is in the right
13192 place. If the window is not in the right place, move it
13193 there, and take the potential window manager hit. */
13194 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13195 &rootw, &x, &y, &width, &height, &border, &depth);
13197 if (original_left != x || original_top != y)
13198 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13199 original_left, original_top);
13201 UNBLOCK_INPUT;
13204 XSETFRAME (frame, f);
13206 /* Wait until the frame is visible. Process X events until a
13207 MapNotify event has been seen, or until we think we won't get a
13208 MapNotify at all.. */
13209 for (count = input_signal_count + 10;
13210 input_signal_count < count && !FRAME_VISIBLE_P (f);)
13212 /* Force processing of queued events. */
13213 x_sync (f);
13215 /* Machines that do polling rather than SIGIO have been
13216 observed to go into a busy-wait here. So we'll fake an
13217 alarm signal to let the handler know that there's something
13218 to be read. We used to raise a real alarm, but it seems
13219 that the handler isn't always enabled here. This is
13220 probably a bug. */
13221 if (input_polling_used ())
13223 /* It could be confusing if a real alarm arrives while
13224 processing the fake one. Turn it off and let the
13225 handler reset it. */
13226 extern void poll_for_input_1 P_ ((void));
13227 int old_poll_suppress_count = poll_suppress_count;
13228 poll_suppress_count = 1;
13229 poll_for_input_1 ();
13230 poll_suppress_count = old_poll_suppress_count;
13233 /* See if a MapNotify event has been processed. */
13234 FRAME_SAMPLE_VISIBILITY (f);
13237 /* 2000-09-28: In
13239 (let ((f (selected-frame)))
13240 (iconify-frame f)
13241 (raise-frame f))
13243 the frame is not raised with various window managers on
13244 FreeBSD, Linux and Solaris. It turns out that, for some
13245 unknown reason, the call to XtMapWidget is completely ignored.
13246 Mapping the widget a second time works. */
13248 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13249 goto retry;
13253 /* Change from mapped state to withdrawn state. */
13255 /* Make the frame visible (mapped and not iconified). */
13257 void
13258 x_make_frame_invisible (f)
13259 struct frame *f;
13261 Window window;
13263 #ifdef USE_X_TOOLKIT
13264 /* Use the frame's outermost window, not the one we normally draw on. */
13265 window = XtWindow (f->output_data.x->widget);
13266 #else /* not USE_X_TOOLKIT */
13267 window = FRAME_X_WINDOW (f);
13268 #endif /* not USE_X_TOOLKIT */
13270 /* Don't keep the highlight on an invisible frame. */
13271 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13272 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13274 #if 0/* This might add unreliability; I don't trust it -- rms. */
13275 if (! f->async_visible && ! f->async_iconified)
13276 return;
13277 #endif
13279 BLOCK_INPUT;
13281 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13282 that the current position of the window is user-specified, rather than
13283 program-specified, so that when the window is mapped again, it will be
13284 placed at the same location, without forcing the user to position it
13285 by hand again (they have already done that once for this window.) */
13286 x_wm_set_size_hint (f, (long) 0, 1);
13288 #ifdef HAVE_X11R4
13290 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13291 DefaultScreen (FRAME_X_DISPLAY (f))))
13293 UNBLOCK_INPUT_RESIGNAL;
13294 error ("Can't notify window manager of window withdrawal");
13296 #else /* ! defined (HAVE_X11R4) */
13298 /* Tell the window manager what we're going to do. */
13299 if (! EQ (Vx_no_window_manager, Qt))
13301 XEvent unmap;
13303 unmap.xunmap.type = UnmapNotify;
13304 unmap.xunmap.window = window;
13305 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13306 unmap.xunmap.from_configure = False;
13307 if (! XSendEvent (FRAME_X_DISPLAY (f),
13308 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13309 False,
13310 SubstructureRedirectMaskSubstructureNotifyMask,
13311 &unmap))
13313 UNBLOCK_INPUT_RESIGNAL;
13314 error ("Can't notify window manager of withdrawal");
13318 /* Unmap the window ourselves. Cheeky! */
13319 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13320 #endif /* ! defined (HAVE_X11R4) */
13322 /* We can't distinguish this from iconification
13323 just by the event that we get from the server.
13324 So we can't win using the usual strategy of letting
13325 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13326 and synchronize with the server to make sure we agree. */
13327 f->visible = 0;
13328 FRAME_ICONIFIED_P (f) = 0;
13329 f->async_visible = 0;
13330 f->async_iconified = 0;
13332 x_sync (f);
13334 UNBLOCK_INPUT;
13337 /* Change window state from mapped to iconified. */
13339 void
13340 x_iconify_frame (f)
13341 struct frame *f;
13343 int result;
13344 Lisp_Object type;
13346 /* Don't keep the highlight on an invisible frame. */
13347 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13348 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13350 if (f->async_iconified)
13351 return;
13353 BLOCK_INPUT;
13355 FRAME_SAMPLE_VISIBILITY (f);
13357 type = x_icon_type (f);
13358 if (!NILP (type))
13359 x_bitmap_icon (f, type);
13361 #ifdef USE_X_TOOLKIT
13363 if (! FRAME_VISIBLE_P (f))
13365 if (! EQ (Vx_no_window_manager, Qt))
13366 x_wm_set_window_state (f, IconicState);
13367 /* This was XtPopup, but that did nothing for an iconified frame. */
13368 XtMapWidget (f->output_data.x->widget);
13369 /* The server won't give us any event to indicate
13370 that an invisible frame was changed to an icon,
13371 so we have to record it here. */
13372 f->iconified = 1;
13373 f->visible = 1;
13374 f->async_iconified = 1;
13375 f->async_visible = 0;
13376 UNBLOCK_INPUT;
13377 return;
13380 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13381 XtWindow (f->output_data.x->widget),
13382 DefaultScreen (FRAME_X_DISPLAY (f)));
13383 UNBLOCK_INPUT;
13385 if (!result)
13386 error ("Can't notify window manager of iconification");
13388 f->async_iconified = 1;
13389 f->async_visible = 0;
13392 BLOCK_INPUT;
13393 XFlush (FRAME_X_DISPLAY (f));
13394 UNBLOCK_INPUT;
13395 #else /* not USE_X_TOOLKIT */
13397 /* Make sure the X server knows where the window should be positioned,
13398 in case the user deiconifies with the window manager. */
13399 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13400 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13402 /* Since we don't know which revision of X we're running, we'll use both
13403 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13405 /* X11R4: send a ClientMessage to the window manager using the
13406 WM_CHANGE_STATE type. */
13408 XEvent message;
13410 message.xclient.window = FRAME_X_WINDOW (f);
13411 message.xclient.type = ClientMessage;
13412 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13413 message.xclient.format = 32;
13414 message.xclient.data.l[0] = IconicState;
13416 if (! XSendEvent (FRAME_X_DISPLAY (f),
13417 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13418 False,
13419 SubstructureRedirectMask | SubstructureNotifyMask,
13420 &message))
13422 UNBLOCK_INPUT_RESIGNAL;
13423 error ("Can't notify window manager of iconification");
13427 /* X11R3: set the initial_state field of the window manager hints to
13428 IconicState. */
13429 x_wm_set_window_state (f, IconicState);
13431 if (!FRAME_VISIBLE_P (f))
13433 /* If the frame was withdrawn, before, we must map it. */
13434 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13437 f->async_iconified = 1;
13438 f->async_visible = 0;
13440 XFlush (FRAME_X_DISPLAY (f));
13441 UNBLOCK_INPUT;
13442 #endif /* not USE_X_TOOLKIT */
13446 /* Free X resources of frame F. */
13448 void
13449 x_free_frame_resources (f)
13450 struct frame *f;
13452 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13453 Lisp_Object bar;
13454 struct scroll_bar *b;
13456 BLOCK_INPUT;
13458 /* If a display connection is dead, don't try sending more
13459 commands to the X server. */
13460 if (dpyinfo->display)
13462 if (f->output_data.x->icon_desc)
13463 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13465 #ifdef USE_X_TOOLKIT
13466 /* Explicitly destroy the scroll bars of the frame. Without
13467 this, we get "BadDrawable" errors from the toolkit later on,
13468 presumably from expose events generated for the disappearing
13469 toolkit scroll bars. */
13470 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13472 b = XSCROLL_BAR (bar);
13473 x_scroll_bar_remove (b);
13475 #endif
13477 #ifdef HAVE_X_I18N
13478 if (FRAME_XIC (f))
13479 free_frame_xic (f);
13480 #endif
13482 #ifdef USE_X_TOOLKIT
13483 if (f->output_data.x->widget)
13485 XtDestroyWidget (f->output_data.x->widget);
13486 f->output_data.x->widget = NULL;
13488 /* Tooltips don't have widgets, only a simple X window, even if
13489 we are using a toolkit. */
13490 else if (FRAME_X_WINDOW (f))
13491 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13493 free_frame_menubar (f);
13494 #else /* !USE_X_TOOLKIT */
13495 if (FRAME_X_WINDOW (f))
13496 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13497 #endif /* !USE_X_TOOLKIT */
13499 unload_color (f, f->output_data.x->foreground_pixel);
13500 unload_color (f, f->output_data.x->background_pixel);
13501 unload_color (f, f->output_data.x->cursor_pixel);
13502 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13503 unload_color (f, f->output_data.x->border_pixel);
13504 unload_color (f, f->output_data.x->mouse_pixel);
13506 if (f->output_data.x->scroll_bar_background_pixel != -1)
13507 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13508 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13509 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13510 #ifdef USE_TOOLKIT_SCROLL_BARS
13511 /* Scrollbar shadow colors. */
13512 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13513 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13514 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13515 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13516 #endif /* USE_TOOLKIT_SCROLL_BARS */
13517 if (f->output_data.x->white_relief.allocated_p)
13518 unload_color (f, f->output_data.x->white_relief.pixel);
13519 if (f->output_data.x->black_relief.allocated_p)
13520 unload_color (f, f->output_data.x->black_relief.pixel);
13522 if (FRAME_FACE_CACHE (f))
13523 free_frame_faces (f);
13525 x_free_gcs (f);
13526 XFlush (FRAME_X_DISPLAY (f));
13529 if (f->output_data.x->saved_menu_event)
13530 xfree (f->output_data.x->saved_menu_event);
13532 xfree (f->output_data.x);
13533 f->output_data.x = NULL;
13535 if (f == dpyinfo->x_focus_frame)
13536 dpyinfo->x_focus_frame = 0;
13537 if (f == dpyinfo->x_focus_event_frame)
13538 dpyinfo->x_focus_event_frame = 0;
13539 if (f == dpyinfo->x_highlight_frame)
13540 dpyinfo->x_highlight_frame = 0;
13542 if (f == dpyinfo->mouse_face_mouse_frame)
13544 dpyinfo->mouse_face_beg_row
13545 = dpyinfo->mouse_face_beg_col = -1;
13546 dpyinfo->mouse_face_end_row
13547 = dpyinfo->mouse_face_end_col = -1;
13548 dpyinfo->mouse_face_window = Qnil;
13549 dpyinfo->mouse_face_deferred_gc = 0;
13550 dpyinfo->mouse_face_mouse_frame = 0;
13553 UNBLOCK_INPUT;
13557 /* Destroy the X window of frame F. */
13559 void
13560 x_destroy_window (f)
13561 struct frame *f;
13563 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13565 /* If a display connection is dead, don't try sending more
13566 commands to the X server. */
13567 if (dpyinfo->display != 0)
13568 x_free_frame_resources (f);
13570 dpyinfo->reference_count--;
13574 /* Setting window manager hints. */
13576 /* Set the normal size hints for the window manager, for frame F.
13577 FLAGS is the flags word to use--or 0 meaning preserve the flags
13578 that the window now has.
13579 If USER_POSITION is nonzero, we set the USPosition
13580 flag (this is useful when FLAGS is 0). */
13582 void
13583 x_wm_set_size_hint (f, flags, user_position)
13584 struct frame *f;
13585 long flags;
13586 int user_position;
13588 XSizeHints size_hints;
13590 #ifdef USE_X_TOOLKIT
13591 Arg al[2];
13592 int ac = 0;
13593 Dimension widget_width, widget_height;
13594 Window window = XtWindow (f->output_data.x->widget);
13595 #else /* not USE_X_TOOLKIT */
13596 Window window = FRAME_X_WINDOW (f);
13597 #endif /* not USE_X_TOOLKIT */
13599 /* Setting PMaxSize caused various problems. */
13600 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13602 size_hints.x = f->output_data.x->left_pos;
13603 size_hints.y = f->output_data.x->top_pos;
13605 #ifdef USE_X_TOOLKIT
13606 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13607 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13608 XtGetValues (f->output_data.x->widget, al, ac);
13609 size_hints.height = widget_height;
13610 size_hints.width = widget_width;
13611 #else /* not USE_X_TOOLKIT */
13612 size_hints.height = PIXEL_HEIGHT (f);
13613 size_hints.width = PIXEL_WIDTH (f);
13614 #endif /* not USE_X_TOOLKIT */
13616 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13617 size_hints.height_inc = f->output_data.x->line_height;
13618 size_hints.max_width
13619 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13620 size_hints.max_height
13621 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13623 /* Calculate the base and minimum sizes.
13625 (When we use the X toolkit, we don't do it here.
13626 Instead we copy the values that the widgets are using, below.) */
13627 #ifndef USE_X_TOOLKIT
13629 int base_width, base_height;
13630 int min_rows = 0, min_cols = 0;
13632 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13633 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13635 check_frame_size (f, &min_rows, &min_cols);
13637 /* The window manager uses the base width hints to calculate the
13638 current number of rows and columns in the frame while
13639 resizing; min_width and min_height aren't useful for this
13640 purpose, since they might not give the dimensions for a
13641 zero-row, zero-column frame.
13643 We use the base_width and base_height members if we have
13644 them; otherwise, we set the min_width and min_height members
13645 to the size for a zero x zero frame. */
13647 #ifdef HAVE_X11R4
13648 size_hints.flags |= PBaseSize;
13649 size_hints.base_width = base_width;
13650 size_hints.base_height = base_height;
13651 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13652 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13653 #else
13654 size_hints.min_width = base_width;
13655 size_hints.min_height = base_height;
13656 #endif
13659 /* If we don't need the old flags, we don't need the old hint at all. */
13660 if (flags)
13662 size_hints.flags |= flags;
13663 goto no_read;
13665 #endif /* not USE_X_TOOLKIT */
13668 XSizeHints hints; /* Sometimes I hate X Windows... */
13669 long supplied_return;
13670 int value;
13672 #ifdef HAVE_X11R4
13673 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13674 &supplied_return);
13675 #else
13676 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13677 #endif
13679 #ifdef USE_X_TOOLKIT
13680 size_hints.base_height = hints.base_height;
13681 size_hints.base_width = hints.base_width;
13682 size_hints.min_height = hints.min_height;
13683 size_hints.min_width = hints.min_width;
13684 #endif
13686 if (flags)
13687 size_hints.flags |= flags;
13688 else
13690 if (value == 0)
13691 hints.flags = 0;
13692 if (hints.flags & PSize)
13693 size_hints.flags |= PSize;
13694 if (hints.flags & PPosition)
13695 size_hints.flags |= PPosition;
13696 if (hints.flags & USPosition)
13697 size_hints.flags |= USPosition;
13698 if (hints.flags & USSize)
13699 size_hints.flags |= USSize;
13703 #ifndef USE_X_TOOLKIT
13704 no_read:
13705 #endif
13707 #ifdef PWinGravity
13708 size_hints.win_gravity = f->output_data.x->win_gravity;
13709 size_hints.flags |= PWinGravity;
13711 if (user_position)
13713 size_hints.flags &= ~ PPosition;
13714 size_hints.flags |= USPosition;
13716 #endif /* PWinGravity */
13718 #ifdef HAVE_X11R4
13719 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13720 #else
13721 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13722 #endif
13725 /* Used for IconicState or NormalState */
13727 void
13728 x_wm_set_window_state (f, state)
13729 struct frame *f;
13730 int state;
13732 #ifdef USE_X_TOOLKIT
13733 Arg al[1];
13735 XtSetArg (al[0], XtNinitialState, state);
13736 XtSetValues (f->output_data.x->widget, al, 1);
13737 #else /* not USE_X_TOOLKIT */
13738 Window window = FRAME_X_WINDOW (f);
13740 f->output_data.x->wm_hints.flags |= StateHint;
13741 f->output_data.x->wm_hints.initial_state = state;
13743 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13744 #endif /* not USE_X_TOOLKIT */
13747 void
13748 x_wm_set_icon_pixmap (f, pixmap_id)
13749 struct frame *f;
13750 int pixmap_id;
13752 Pixmap icon_pixmap;
13754 #ifndef USE_X_TOOLKIT
13755 Window window = FRAME_X_WINDOW (f);
13756 #endif
13758 if (pixmap_id > 0)
13760 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13761 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13763 else
13765 /* It seems there is no way to turn off use of an icon pixmap.
13766 The following line does it, only if no icon has yet been created,
13767 for some window managers. But with mwm it crashes.
13768 Some people say it should clear the IconPixmapHint bit in this case,
13769 but that doesn't work, and the X consortium said it isn't the
13770 right thing at all. Since there is no way to win,
13771 best to explicitly give up. */
13772 #if 0
13773 f->output_data.x->wm_hints.icon_pixmap = None;
13774 #else
13775 return;
13776 #endif
13779 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13782 Arg al[1];
13783 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13784 XtSetValues (f->output_data.x->widget, al, 1);
13787 #else /* not USE_X_TOOLKIT */
13789 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13790 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13792 #endif /* not USE_X_TOOLKIT */
13795 void
13796 x_wm_set_icon_position (f, icon_x, icon_y)
13797 struct frame *f;
13798 int icon_x, icon_y;
13800 #ifdef USE_X_TOOLKIT
13801 Window window = XtWindow (f->output_data.x->widget);
13802 #else
13803 Window window = FRAME_X_WINDOW (f);
13804 #endif
13806 f->output_data.x->wm_hints.flags |= IconPositionHint;
13807 f->output_data.x->wm_hints.icon_x = icon_x;
13808 f->output_data.x->wm_hints.icon_y = icon_y;
13810 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13814 /***********************************************************************
13815 Fonts
13816 ***********************************************************************/
13818 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13820 struct font_info *
13821 x_get_font_info (f, font_idx)
13822 FRAME_PTR f;
13823 int font_idx;
13825 return (FRAME_X_FONT_TABLE (f) + font_idx);
13829 /* Return a list of names of available fonts matching PATTERN on frame F.
13831 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13832 to be listed.
13834 SIZE < 0 means include scalable fonts.
13836 Frame F null means we have not yet created any frame on X, and
13837 consult the first display in x_display_list. MAXNAMES sets a limit
13838 on how many fonts to match. */
13840 Lisp_Object
13841 x_list_fonts (f, pattern, size, maxnames)
13842 struct frame *f;
13843 Lisp_Object pattern;
13844 int size;
13845 int maxnames;
13847 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13848 Lisp_Object tem, second_best;
13849 struct x_display_info *dpyinfo
13850 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13851 Display *dpy = dpyinfo->display;
13852 int try_XLoadQueryFont = 0;
13853 int count;
13854 int allow_scalable_fonts_p = 0;
13856 if (size < 0)
13858 allow_scalable_fonts_p = 1;
13859 size = 0;
13862 patterns = Fassoc (pattern, Valternate_fontname_alist);
13863 if (NILP (patterns))
13864 patterns = Fcons (pattern, Qnil);
13866 if (maxnames == 1 && !size)
13867 /* We can return any single font matching PATTERN. */
13868 try_XLoadQueryFont = 1;
13870 for (; CONSP (patterns); patterns = XCDR (patterns))
13872 int num_fonts;
13873 char **names = NULL;
13875 pattern = XCAR (patterns);
13876 /* See if we cached the result for this particular query.
13877 The cache is an alist of the form:
13878 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13879 tem = XCDR (dpyinfo->name_list_element);
13880 key = Fcons (Fcons (pattern, make_number (maxnames)),
13881 allow_scalable_fonts_p ? Qt : Qnil);
13882 list = Fassoc (key, tem);
13883 if (!NILP (list))
13885 list = Fcdr_safe (list);
13886 /* We have a cashed list. Don't have to get the list again. */
13887 goto label_cached;
13890 /* At first, put PATTERN in the cache. */
13892 BLOCK_INPUT;
13893 count = x_catch_errors (dpy);
13895 if (try_XLoadQueryFont)
13897 XFontStruct *font;
13898 unsigned long value;
13900 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13901 if (x_had_errors_p (dpy))
13903 /* This error is perhaps due to insufficient memory on X
13904 server. Let's just ignore it. */
13905 font = NULL;
13906 x_clear_errors (dpy);
13909 if (font
13910 && XGetFontProperty (font, XA_FONT, &value))
13912 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13913 int len = strlen (name);
13914 char *tmp;
13916 /* If DXPC (a Differential X Protocol Compressor)
13917 Ver.3.7 is running, XGetAtomName will return null
13918 string. We must avoid such a name. */
13919 if (len == 0)
13920 try_XLoadQueryFont = 0;
13921 else
13923 num_fonts = 1;
13924 names = (char **) alloca (sizeof (char *));
13925 /* Some systems only allow alloca assigned to a
13926 simple var. */
13927 tmp = (char *) alloca (len + 1); names[0] = tmp;
13928 bcopy (name, names[0], len + 1);
13929 XFree (name);
13932 else
13933 try_XLoadQueryFont = 0;
13935 if (font)
13936 XFreeFont (dpy, font);
13939 if (!try_XLoadQueryFont)
13941 /* We try at least 10 fonts because XListFonts will return
13942 auto-scaled fonts at the head. */
13943 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13944 &num_fonts);
13945 if (x_had_errors_p (dpy))
13947 /* This error is perhaps due to insufficient memory on X
13948 server. Let's just ignore it. */
13949 names = NULL;
13950 x_clear_errors (dpy);
13954 x_uncatch_errors (dpy, count);
13955 UNBLOCK_INPUT;
13957 if (names)
13959 int i;
13961 /* Make a list of all the fonts we got back.
13962 Store that in the font cache for the display. */
13963 for (i = 0; i < num_fonts; i++)
13965 int width = 0;
13966 char *p = names[i];
13967 int average_width = -1, dashes = 0;
13969 /* Count the number of dashes in NAMES[I]. If there are
13970 14 dashes, and the field value following 12th dash
13971 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13972 is usually too ugly to be used for editing. Let's
13973 ignore it. */
13974 while (*p)
13975 if (*p++ == '-')
13977 dashes++;
13978 if (dashes == 7) /* PIXEL_SIZE field */
13979 width = atoi (p);
13980 else if (dashes == 12) /* AVERAGE_WIDTH field */
13981 average_width = atoi (p);
13984 if (allow_scalable_fonts_p
13985 || dashes < 14 || average_width != 0)
13987 tem = build_string (names[i]);
13988 if (NILP (Fassoc (tem, list)))
13990 if (STRINGP (Vx_pixel_size_width_font_regexp)
13991 && ((fast_c_string_match_ignore_case
13992 (Vx_pixel_size_width_font_regexp, names[i]))
13993 >= 0))
13994 /* We can set the value of PIXEL_SIZE to the
13995 width of this font. */
13996 list = Fcons (Fcons (tem, make_number (width)), list);
13997 else
13998 /* For the moment, width is not known. */
13999 list = Fcons (Fcons (tem, Qnil), list);
14004 if (!try_XLoadQueryFont)
14006 BLOCK_INPUT;
14007 XFreeFontNames (names);
14008 UNBLOCK_INPUT;
14012 /* Now store the result in the cache. */
14013 XSETCDR (dpyinfo->name_list_element,
14014 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
14016 label_cached:
14017 if (NILP (list)) continue; /* Try the remaining alternatives. */
14019 newlist = second_best = Qnil;
14020 /* Make a list of the fonts that have the right width. */
14021 for (; CONSP (list); list = XCDR (list))
14023 int found_size;
14025 tem = XCAR (list);
14027 if (!CONSP (tem) || NILP (XCAR (tem)))
14028 continue;
14029 if (!size)
14031 newlist = Fcons (XCAR (tem), newlist);
14032 continue;
14035 if (!INTEGERP (XCDR (tem)))
14037 /* Since we have not yet known the size of this font, we
14038 must try slow function call XLoadQueryFont. */
14039 XFontStruct *thisinfo;
14041 BLOCK_INPUT;
14042 count = x_catch_errors (dpy);
14043 thisinfo = XLoadQueryFont (dpy,
14044 XSTRING (XCAR (tem))->data);
14045 if (x_had_errors_p (dpy))
14047 /* This error is perhaps due to insufficient memory on X
14048 server. Let's just ignore it. */
14049 thisinfo = NULL;
14050 x_clear_errors (dpy);
14052 x_uncatch_errors (dpy, count);
14053 UNBLOCK_INPUT;
14055 if (thisinfo)
14057 XSETCDR (tem,
14058 (thisinfo->min_bounds.width == 0
14059 ? make_number (0)
14060 : make_number (thisinfo->max_bounds.width)));
14061 BLOCK_INPUT;
14062 XFreeFont (dpy, thisinfo);
14063 UNBLOCK_INPUT;
14065 else
14066 /* For unknown reason, the previous call of XListFont had
14067 returned a font which can't be opened. Record the size
14068 as 0 not to try to open it again. */
14069 XSETCDR (tem, make_number (0));
14072 found_size = XINT (XCDR (tem));
14073 if (found_size == size)
14074 newlist = Fcons (XCAR (tem), newlist);
14075 else if (found_size > 0)
14077 if (NILP (second_best))
14078 second_best = tem;
14079 else if (found_size < size)
14081 if (XINT (XCDR (second_best)) > size
14082 || XINT (XCDR (second_best)) < found_size)
14083 second_best = tem;
14085 else
14087 if (XINT (XCDR (second_best)) > size
14088 && XINT (XCDR (second_best)) > found_size)
14089 second_best = tem;
14093 if (!NILP (newlist))
14094 break;
14095 else if (!NILP (second_best))
14097 newlist = Fcons (XCAR (second_best), Qnil);
14098 break;
14102 return newlist;
14106 #if GLYPH_DEBUG
14108 /* Check that FONT is valid on frame F. It is if it can be found in F's
14109 font table. */
14111 static void
14112 x_check_font (f, font)
14113 struct frame *f;
14114 XFontStruct *font;
14116 int i;
14117 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14119 xassert (font != NULL);
14121 for (i = 0; i < dpyinfo->n_fonts; i++)
14122 if (dpyinfo->font_table[i].name
14123 && font == dpyinfo->font_table[i].font)
14124 break;
14126 xassert (i < dpyinfo->n_fonts);
14129 #endif /* GLYPH_DEBUG != 0 */
14131 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14132 Note: There are (broken) X fonts out there with invalid XFontStruct
14133 min_bounds contents. For example, handa@etl.go.jp reports that
14134 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14135 have font->min_bounds.width == 0. */
14137 static INLINE void
14138 x_font_min_bounds (font, w, h)
14139 XFontStruct *font;
14140 int *w, *h;
14142 *h = FONT_HEIGHT (font);
14143 *w = font->min_bounds.width;
14145 /* Try to handle the case where FONT->min_bounds has invalid
14146 contents. Since the only font known to have invalid min_bounds
14147 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14148 if (*w <= 0)
14149 *w = font->max_bounds.width;
14153 /* Compute the smallest character width and smallest font height over
14154 all fonts available on frame F. Set the members smallest_char_width
14155 and smallest_font_height in F's x_display_info structure to
14156 the values computed. Value is non-zero if smallest_font_height or
14157 smallest_char_width become smaller than they were before. */
14159 static int
14160 x_compute_min_glyph_bounds (f)
14161 struct frame *f;
14163 int i;
14164 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14165 XFontStruct *font;
14166 int old_width = dpyinfo->smallest_char_width;
14167 int old_height = dpyinfo->smallest_font_height;
14169 dpyinfo->smallest_font_height = 100000;
14170 dpyinfo->smallest_char_width = 100000;
14172 for (i = 0; i < dpyinfo->n_fonts; ++i)
14173 if (dpyinfo->font_table[i].name)
14175 struct font_info *fontp = dpyinfo->font_table + i;
14176 int w, h;
14178 font = (XFontStruct *) fontp->font;
14179 xassert (font != (XFontStruct *) ~0);
14180 x_font_min_bounds (font, &w, &h);
14182 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
14183 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
14186 xassert (dpyinfo->smallest_char_width > 0
14187 && dpyinfo->smallest_font_height > 0);
14189 return (dpyinfo->n_fonts == 1
14190 || dpyinfo->smallest_char_width < old_width
14191 || dpyinfo->smallest_font_height < old_height);
14195 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14196 pointer to the structure font_info while allocating it dynamically.
14197 If SIZE is 0, load any size of font.
14198 If loading is failed, return NULL. */
14200 struct font_info *
14201 x_load_font (f, fontname, size)
14202 struct frame *f;
14203 register char *fontname;
14204 int size;
14206 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14207 Lisp_Object font_names;
14208 int count;
14210 /* Get a list of all the fonts that match this name. Once we
14211 have a list of matching fonts, we compare them against the fonts
14212 we already have by comparing names. */
14213 font_names = x_list_fonts (f, build_string (fontname), size, 1);
14215 if (!NILP (font_names))
14217 Lisp_Object tail;
14218 int i;
14220 for (i = 0; i < dpyinfo->n_fonts; i++)
14221 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
14222 if (dpyinfo->font_table[i].name
14223 && (!strcmp (dpyinfo->font_table[i].name,
14224 XSTRING (XCAR (tail))->data)
14225 || !strcmp (dpyinfo->font_table[i].full_name,
14226 XSTRING (XCAR (tail))->data)))
14227 return (dpyinfo->font_table + i);
14230 /* Load the font and add it to the table. */
14232 char *full_name;
14233 XFontStruct *font;
14234 struct font_info *fontp;
14235 unsigned long value;
14236 int i;
14238 /* If we have found fonts by x_list_font, load one of them. If
14239 not, we still try to load a font by the name given as FONTNAME
14240 because XListFonts (called in x_list_font) of some X server has
14241 a bug of not finding a font even if the font surely exists and
14242 is loadable by XLoadQueryFont. */
14243 if (size > 0 && !NILP (font_names))
14244 fontname = (char *) XSTRING (XCAR (font_names))->data;
14246 BLOCK_INPUT;
14247 count = x_catch_errors (FRAME_X_DISPLAY (f));
14248 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14249 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14251 /* This error is perhaps due to insufficient memory on X
14252 server. Let's just ignore it. */
14253 font = NULL;
14254 x_clear_errors (FRAME_X_DISPLAY (f));
14256 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14257 UNBLOCK_INPUT;
14258 if (!font)
14259 return NULL;
14261 /* Find a free slot in the font table. */
14262 for (i = 0; i < dpyinfo->n_fonts; ++i)
14263 if (dpyinfo->font_table[i].name == NULL)
14264 break;
14266 /* If no free slot found, maybe enlarge the font table. */
14267 if (i == dpyinfo->n_fonts
14268 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14270 int sz;
14271 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14272 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14273 dpyinfo->font_table
14274 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14277 fontp = dpyinfo->font_table + i;
14278 if (i == dpyinfo->n_fonts)
14279 ++dpyinfo->n_fonts;
14281 /* Now fill in the slots of *FONTP. */
14282 BLOCK_INPUT;
14283 fontp->font = font;
14284 fontp->font_idx = i;
14285 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14286 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14288 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14289 full_name = 0;
14290 if (XGetFontProperty (font, XA_FONT, &value))
14292 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14293 char *p = name;
14294 int dashes = 0;
14296 /* Count the number of dashes in the "full name".
14297 If it is too few, this isn't really the font's full name,
14298 so don't use it.
14299 In X11R4, the fonts did not come with their canonical names
14300 stored in them. */
14301 while (*p)
14303 if (*p == '-')
14304 dashes++;
14305 p++;
14308 if (dashes >= 13)
14310 full_name = (char *) xmalloc (p - name + 1);
14311 bcopy (name, full_name, p - name + 1);
14314 XFree (name);
14317 if (full_name != 0)
14318 fontp->full_name = full_name;
14319 else
14320 fontp->full_name = fontp->name;
14322 fontp->size = font->max_bounds.width;
14323 fontp->height = FONT_HEIGHT (font);
14325 if (NILP (font_names))
14327 /* We come here because of a bug of XListFonts mentioned at
14328 the head of this block. Let's store this information in
14329 the cache for x_list_fonts. */
14330 Lisp_Object lispy_name = build_string (fontname);
14331 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14332 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14333 Qnil);
14335 XSETCDR (dpyinfo->name_list_element,
14336 Fcons (Fcons (key,
14337 Fcons (Fcons (lispy_full_name,
14338 make_number (fontp->size)),
14339 Qnil)),
14340 XCDR (dpyinfo->name_list_element)));
14341 if (full_name)
14343 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14344 Qnil);
14345 XSETCDR (dpyinfo->name_list_element,
14346 Fcons (Fcons (key,
14347 Fcons (Fcons (lispy_full_name,
14348 make_number (fontp->size)),
14349 Qnil)),
14350 XCDR (dpyinfo->name_list_element)));
14354 /* The slot `encoding' specifies how to map a character
14355 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14356 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14357 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14358 2:0xA020..0xFF7F). For the moment, we don't know which charset
14359 uses this font. So, we set information in fontp->encoding[1]
14360 which is never used by any charset. If mapping can't be
14361 decided, set FONT_ENCODING_NOT_DECIDED. */
14362 fontp->encoding_type
14363 = (font->max_byte1 == 0
14364 /* 1-byte font */
14365 ? (font->min_char_or_byte2 < 0x80
14366 ? (font->max_char_or_byte2 < 0x80
14367 ? 0 /* 0x20..0x7F */
14368 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14369 : 1) /* 0xA0..0xFF */
14370 /* 2-byte font */
14371 : (font->min_byte1 < 0x80
14372 ? (font->max_byte1 < 0x80
14373 ? (font->min_char_or_byte2 < 0x80
14374 ? (font->max_char_or_byte2 < 0x80
14375 ? 0 /* 0x2020..0x7F7F */
14376 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14377 : 3) /* 0x20A0..0x7FFF */
14378 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14379 : (font->min_char_or_byte2 < 0x80
14380 ? (font->max_char_or_byte2 < 0x80
14381 ? 2 /* 0xA020..0xFF7F */
14382 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14383 : 1))); /* 0xA0A0..0xFFFF */
14385 fontp->baseline_offset
14386 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14387 ? (long) value : 0);
14388 fontp->relative_compose
14389 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14390 ? (long) value : 0);
14391 fontp->default_ascent
14392 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14393 ? (long) value : 0);
14395 /* Set global flag fonts_changed_p to non-zero if the font loaded
14396 has a character with a smaller width than any other character
14397 before, or if the font loaded has a smaller height than any
14398 other font loaded before. If this happens, it will make a
14399 glyph matrix reallocation necessary. */
14400 fonts_changed_p |= x_compute_min_glyph_bounds (f);
14401 UNBLOCK_INPUT;
14402 return fontp;
14407 /* Return a pointer to struct font_info of a font named FONTNAME for
14408 frame F. If no such font is loaded, return NULL. */
14410 struct font_info *
14411 x_query_font (f, fontname)
14412 struct frame *f;
14413 register char *fontname;
14415 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14416 int i;
14418 for (i = 0; i < dpyinfo->n_fonts; i++)
14419 if (dpyinfo->font_table[i].name
14420 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14421 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14422 return (dpyinfo->font_table + i);
14423 return NULL;
14427 /* Find a CCL program for a font specified by FONTP, and set the member
14428 `encoder' of the structure. */
14430 void
14431 x_find_ccl_program (fontp)
14432 struct font_info *fontp;
14434 Lisp_Object list, elt;
14436 elt = Qnil;
14437 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14439 elt = XCAR (list);
14440 if (CONSP (elt)
14441 && STRINGP (XCAR (elt))
14442 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14443 >= 0)
14444 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14445 >= 0)))
14446 break;
14449 if (! NILP (list))
14451 struct ccl_program *ccl
14452 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14454 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14455 xfree (ccl);
14456 else
14457 fontp->font_encoder = ccl;
14463 /***********************************************************************
14464 Initialization
14465 ***********************************************************************/
14467 #ifdef USE_X_TOOLKIT
14468 static XrmOptionDescRec emacs_options[] = {
14469 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14470 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14472 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14473 XrmoptionSepArg, NULL},
14474 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14476 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14477 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14478 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14479 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14480 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14481 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14482 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14484 #endif /* USE_X_TOOLKIT */
14486 static int x_initialized;
14488 #ifdef MULTI_KBOARD
14489 /* Test whether two display-name strings agree up to the dot that separates
14490 the screen number from the server number. */
14491 static int
14492 same_x_server (name1, name2)
14493 char *name1, *name2;
14495 int seen_colon = 0;
14496 unsigned char *system_name = XSTRING (Vsystem_name)->data;
14497 int system_name_length = strlen (system_name);
14498 int length_until_period = 0;
14500 while (system_name[length_until_period] != 0
14501 && system_name[length_until_period] != '.')
14502 length_until_period++;
14504 /* Treat `unix' like an empty host name. */
14505 if (! strncmp (name1, "unix:", 5))
14506 name1 += 4;
14507 if (! strncmp (name2, "unix:", 5))
14508 name2 += 4;
14509 /* Treat this host's name like an empty host name. */
14510 if (! strncmp (name1, system_name, system_name_length)
14511 && name1[system_name_length] == ':')
14512 name1 += system_name_length;
14513 if (! strncmp (name2, system_name, system_name_length)
14514 && name2[system_name_length] == ':')
14515 name2 += system_name_length;
14516 /* Treat this host's domainless name like an empty host name. */
14517 if (! strncmp (name1, system_name, length_until_period)
14518 && name1[length_until_period] == ':')
14519 name1 += length_until_period;
14520 if (! strncmp (name2, system_name, length_until_period)
14521 && name2[length_until_period] == ':')
14522 name2 += length_until_period;
14524 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14526 if (*name1 == ':')
14527 seen_colon++;
14528 if (seen_colon && *name1 == '.')
14529 return 1;
14531 return (seen_colon
14532 && (*name1 == '.' || *name1 == '\0')
14533 && (*name2 == '.' || *name2 == '\0'));
14535 #endif
14537 struct x_display_info *
14538 x_term_init (display_name, xrm_option, resource_name)
14539 Lisp_Object display_name;
14540 char *xrm_option;
14541 char *resource_name;
14543 int connection;
14544 Display *dpy;
14545 struct x_display_info *dpyinfo;
14546 XrmDatabase xrdb;
14548 BLOCK_INPUT;
14550 if (!x_initialized)
14552 x_initialize ();
14553 x_initialized = 1;
14556 #ifdef USE_X_TOOLKIT
14557 /* weiner@footloose.sps.mot.com reports that this causes
14558 errors with X11R5:
14559 X protocol error: BadAtom (invalid Atom parameter)
14560 on protocol request 18skiloaf.
14561 So let's not use it until R6. */
14562 #ifdef HAVE_X11XTR6
14563 XtSetLanguageProc (NULL, NULL, NULL);
14564 #endif
14567 int argc = 0;
14568 char *argv[3];
14570 argv[0] = "";
14571 argc = 1;
14572 if (xrm_option)
14574 argv[argc++] = "-xrm";
14575 argv[argc++] = xrm_option;
14577 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
14578 resource_name, EMACS_CLASS,
14579 emacs_options, XtNumber (emacs_options),
14580 &argc, argv);
14582 #ifdef HAVE_X11XTR6
14583 /* I think this is to compensate for XtSetLanguageProc. */
14584 fixup_locale ();
14585 #endif
14588 #else /* not USE_X_TOOLKIT */
14589 #ifdef HAVE_X11R5
14590 XSetLocaleModifiers ("");
14591 #endif
14592 dpy = XOpenDisplay (XSTRING (display_name)->data);
14593 #endif /* not USE_X_TOOLKIT */
14595 /* Detect failure. */
14596 if (dpy == 0)
14598 UNBLOCK_INPUT;
14599 return 0;
14602 /* We have definitely succeeded. Record the new connection. */
14604 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14605 bzero (dpyinfo, sizeof *dpyinfo);
14607 #ifdef MULTI_KBOARD
14609 struct x_display_info *share;
14610 Lisp_Object tail;
14612 for (share = x_display_list, tail = x_display_name_list; share;
14613 share = share->next, tail = XCDR (tail))
14614 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
14615 XSTRING (display_name)->data))
14616 break;
14617 if (share)
14618 dpyinfo->kboard = share->kboard;
14619 else
14621 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14622 init_kboard (dpyinfo->kboard);
14623 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14625 char *vendor = ServerVendor (dpy);
14626 UNBLOCK_INPUT;
14627 dpyinfo->kboard->Vsystem_key_alist
14628 = call1 (Qvendor_specific_keysyms,
14629 build_string (vendor ? vendor : ""));
14630 BLOCK_INPUT;
14633 dpyinfo->kboard->next_kboard = all_kboards;
14634 all_kboards = dpyinfo->kboard;
14635 /* Don't let the initial kboard remain current longer than necessary.
14636 That would cause problems if a file loaded on startup tries to
14637 prompt in the mini-buffer. */
14638 if (current_kboard == initial_kboard)
14639 current_kboard = dpyinfo->kboard;
14641 dpyinfo->kboard->reference_count++;
14643 #endif
14645 /* Put this display on the chain. */
14646 dpyinfo->next = x_display_list;
14647 x_display_list = dpyinfo;
14649 /* Put it on x_display_name_list as well, to keep them parallel. */
14650 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14651 x_display_name_list);
14652 dpyinfo->name_list_element = XCAR (x_display_name_list);
14654 dpyinfo->display = dpy;
14656 #if 0
14657 XSetAfterFunction (x_current_display, x_trace_wire);
14658 #endif /* ! 0 */
14660 dpyinfo->x_id_name
14661 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14662 + STRING_BYTES (XSTRING (Vsystem_name))
14663 + 2);
14664 sprintf (dpyinfo->x_id_name, "%s@%s",
14665 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
14667 /* Figure out which modifier bits mean what. */
14668 x_find_modifier_meanings (dpyinfo);
14670 /* Get the scroll bar cursor. */
14671 dpyinfo->vertical_scroll_bar_cursor
14672 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14674 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14675 resource_name, EMACS_CLASS);
14676 #ifdef HAVE_XRMSETDATABASE
14677 XrmSetDatabase (dpyinfo->display, xrdb);
14678 #else
14679 dpyinfo->display->db = xrdb;
14680 #endif
14681 /* Put the rdb where we can find it in a way that works on
14682 all versions. */
14683 dpyinfo->xrdb = xrdb;
14685 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14686 DefaultScreen (dpyinfo->display));
14687 select_visual (dpyinfo);
14688 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14689 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14690 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14691 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14692 dpyinfo->grabbed = 0;
14693 dpyinfo->reference_count = 0;
14694 dpyinfo->icon_bitmap_id = -1;
14695 dpyinfo->font_table = NULL;
14696 dpyinfo->n_fonts = 0;
14697 dpyinfo->font_table_size = 0;
14698 dpyinfo->bitmaps = 0;
14699 dpyinfo->bitmaps_size = 0;
14700 dpyinfo->bitmaps_last = 0;
14701 dpyinfo->scratch_cursor_gc = 0;
14702 dpyinfo->mouse_face_mouse_frame = 0;
14703 dpyinfo->mouse_face_deferred_gc = 0;
14704 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14705 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14706 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14707 dpyinfo->mouse_face_window = Qnil;
14708 dpyinfo->mouse_face_overlay = Qnil;
14709 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14710 dpyinfo->mouse_face_defer = 0;
14711 dpyinfo->mouse_face_hidden = 0;
14712 dpyinfo->x_focus_frame = 0;
14713 dpyinfo->x_focus_event_frame = 0;
14714 dpyinfo->x_highlight_frame = 0;
14715 dpyinfo->image_cache = make_image_cache ();
14717 /* See if a private colormap is requested. */
14718 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14720 if (dpyinfo->visual->class == PseudoColor)
14722 Lisp_Object value;
14723 value = display_x_get_resource (dpyinfo,
14724 build_string ("privateColormap"),
14725 build_string ("PrivateColormap"),
14726 Qnil, Qnil);
14727 if (STRINGP (value)
14728 && (!strcmp (XSTRING (value)->data, "true")
14729 || !strcmp (XSTRING (value)->data, "on")))
14730 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14733 else
14734 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14735 dpyinfo->visual, AllocNone);
14738 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14739 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14740 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14741 dpyinfo->resy = pixels * 25.4 / mm;
14742 pixels = DisplayWidth (dpyinfo->display, screen_number);
14743 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14744 dpyinfo->resx = pixels * 25.4 / mm;
14747 dpyinfo->Xatom_wm_protocols
14748 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14749 dpyinfo->Xatom_wm_take_focus
14750 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14751 dpyinfo->Xatom_wm_save_yourself
14752 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14753 dpyinfo->Xatom_wm_delete_window
14754 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14755 dpyinfo->Xatom_wm_change_state
14756 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14757 dpyinfo->Xatom_wm_configure_denied
14758 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14759 dpyinfo->Xatom_wm_window_moved
14760 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14761 dpyinfo->Xatom_editres
14762 = XInternAtom (dpyinfo->display, "Editres", False);
14763 dpyinfo->Xatom_CLIPBOARD
14764 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14765 dpyinfo->Xatom_TIMESTAMP
14766 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14767 dpyinfo->Xatom_TEXT
14768 = XInternAtom (dpyinfo->display, "TEXT", False);
14769 dpyinfo->Xatom_COMPOUND_TEXT
14770 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14771 dpyinfo->Xatom_DELETE
14772 = XInternAtom (dpyinfo->display, "DELETE", False);
14773 dpyinfo->Xatom_MULTIPLE
14774 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14775 dpyinfo->Xatom_INCR
14776 = XInternAtom (dpyinfo->display, "INCR", False);
14777 dpyinfo->Xatom_EMACS_TMP
14778 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14779 dpyinfo->Xatom_TARGETS
14780 = XInternAtom (dpyinfo->display, "TARGETS", False);
14781 dpyinfo->Xatom_NULL
14782 = XInternAtom (dpyinfo->display, "NULL", False);
14783 dpyinfo->Xatom_ATOM_PAIR
14784 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14785 /* For properties of font. */
14786 dpyinfo->Xatom_PIXEL_SIZE
14787 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14788 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14789 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14790 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14791 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14792 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14793 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14795 /* Ghostscript support. */
14796 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14797 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14799 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14800 False);
14802 dpyinfo->cut_buffers_initialized = 0;
14804 connection = ConnectionNumber (dpyinfo->display);
14805 dpyinfo->connection = connection;
14808 char null_bits[1];
14810 null_bits[0] = 0x00;
14812 dpyinfo->null_pixel
14813 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14814 null_bits, 1, 1, (long) 0, (long) 0,
14819 extern int gray_bitmap_width, gray_bitmap_height;
14820 extern char *gray_bitmap_bits;
14821 dpyinfo->gray
14822 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14823 gray_bitmap_bits,
14824 gray_bitmap_width, gray_bitmap_height,
14825 (unsigned long) 1, (unsigned long) 0, 1);
14828 #ifdef HAVE_X_I18N
14829 xim_initialize (dpyinfo, resource_name);
14830 #endif
14832 #ifdef subprocesses
14833 /* This is only needed for distinguishing keyboard and process input. */
14834 if (connection != 0)
14835 add_keyboard_wait_descriptor (connection);
14836 #endif
14838 #ifndef F_SETOWN_BUG
14839 #ifdef F_SETOWN
14840 #ifdef F_SETOWN_SOCK_NEG
14841 /* stdin is a socket here */
14842 fcntl (connection, F_SETOWN, -getpid ());
14843 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14844 fcntl (connection, F_SETOWN, getpid ());
14845 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14846 #endif /* ! defined (F_SETOWN) */
14847 #endif /* F_SETOWN_BUG */
14849 #ifdef SIGIO
14850 if (interrupt_input)
14851 init_sigio (connection);
14852 #endif /* ! defined (SIGIO) */
14854 #ifdef USE_LUCID
14855 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14856 /* Make sure that we have a valid font for dialog boxes
14857 so that Xt does not crash. */
14859 Display *dpy = dpyinfo->display;
14860 XrmValue d, fr, to;
14861 Font font;
14862 int count;
14864 d.addr = (XPointer)&dpy;
14865 d.size = sizeof (Display *);
14866 fr.addr = XtDefaultFont;
14867 fr.size = sizeof (XtDefaultFont);
14868 to.size = sizeof (Font *);
14869 to.addr = (XPointer)&font;
14870 count = x_catch_errors (dpy);
14871 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14872 abort ();
14873 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14874 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14875 x_uncatch_errors (dpy, count);
14877 #endif
14878 #endif
14880 /* See if we should run in synchronous mode. This is useful
14881 for debugging X code. */
14883 Lisp_Object value;
14884 value = display_x_get_resource (dpyinfo,
14885 build_string ("synchronous"),
14886 build_string ("Synchronous"),
14887 Qnil, Qnil);
14888 if (STRINGP (value)
14889 && (!strcmp (XSTRING (value)->data, "true")
14890 || !strcmp (XSTRING (value)->data, "on")))
14891 XSynchronize (dpyinfo->display, True);
14894 UNBLOCK_INPUT;
14896 return dpyinfo;
14899 /* Get rid of display DPYINFO, assuming all frames are already gone,
14900 and without sending any more commands to the X server. */
14902 void
14903 x_delete_display (dpyinfo)
14904 struct x_display_info *dpyinfo;
14906 delete_keyboard_wait_descriptor (dpyinfo->connection);
14908 /* Discard this display from x_display_name_list and x_display_list.
14909 We can't use Fdelq because that can quit. */
14910 if (! NILP (x_display_name_list)
14911 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14912 x_display_name_list = XCDR (x_display_name_list);
14913 else
14915 Lisp_Object tail;
14917 tail = x_display_name_list;
14918 while (CONSP (tail) && CONSP (XCDR (tail)))
14920 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14922 XSETCDR (tail, XCDR (XCDR (tail)));
14923 break;
14925 tail = XCDR (tail);
14929 if (next_noop_dpyinfo == dpyinfo)
14930 next_noop_dpyinfo = dpyinfo->next;
14932 if (x_display_list == dpyinfo)
14933 x_display_list = dpyinfo->next;
14934 else
14936 struct x_display_info *tail;
14938 for (tail = x_display_list; tail; tail = tail->next)
14939 if (tail->next == dpyinfo)
14940 tail->next = tail->next->next;
14943 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14944 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14945 XrmDestroyDatabase (dpyinfo->xrdb);
14946 #endif
14947 #endif
14948 #ifdef MULTI_KBOARD
14949 if (--dpyinfo->kboard->reference_count == 0)
14950 delete_kboard (dpyinfo->kboard);
14951 #endif
14952 #ifdef HAVE_X_I18N
14953 if (dpyinfo->xim)
14954 xim_close_dpy (dpyinfo);
14955 #endif
14957 xfree (dpyinfo->font_table);
14958 xfree (dpyinfo->x_id_name);
14959 xfree (dpyinfo->color_cells);
14960 xfree (dpyinfo);
14964 /* Set up use of X before we make the first connection. */
14966 static struct redisplay_interface x_redisplay_interface =
14968 x_produce_glyphs,
14969 x_write_glyphs,
14970 x_insert_glyphs,
14971 x_clear_end_of_line,
14972 x_scroll_run,
14973 x_after_update_window_line,
14974 x_update_window_begin,
14975 x_update_window_end,
14976 XTcursor_to,
14977 x_flush,
14978 x_clear_mouse_face,
14979 x_get_glyph_overhangs,
14980 x_fix_overlapping_area
14983 void
14984 x_initialize ()
14986 rif = &x_redisplay_interface;
14988 clear_frame_hook = x_clear_frame;
14989 ins_del_lines_hook = x_ins_del_lines;
14990 delete_glyphs_hook = x_delete_glyphs;
14991 ring_bell_hook = XTring_bell;
14992 reset_terminal_modes_hook = XTreset_terminal_modes;
14993 set_terminal_modes_hook = XTset_terminal_modes;
14994 update_begin_hook = x_update_begin;
14995 update_end_hook = x_update_end;
14996 set_terminal_window_hook = XTset_terminal_window;
14997 read_socket_hook = XTread_socket;
14998 frame_up_to_date_hook = XTframe_up_to_date;
14999 mouse_position_hook = XTmouse_position;
15000 frame_rehighlight_hook = XTframe_rehighlight;
15001 frame_raise_lower_hook = XTframe_raise_lower;
15002 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
15003 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
15004 redeem_scroll_bar_hook = XTredeem_scroll_bar;
15005 judge_scroll_bars_hook = XTjudge_scroll_bars;
15006 estimate_mode_line_height_hook = x_estimate_mode_line_height;
15008 scroll_region_ok = 1; /* we'll scroll partial frames */
15009 char_ins_del_ok = 1;
15010 line_ins_del_ok = 1; /* we'll just blt 'em */
15011 fast_clear_end_of_line = 1; /* X does this well */
15012 memory_below_frame = 0; /* we don't remember what scrolls
15013 off the bottom */
15014 baud_rate = 19200;
15016 x_noop_count = 0;
15017 last_tool_bar_item = -1;
15018 any_help_event_p = 0;
15020 /* Try to use interrupt input; if we can't, then start polling. */
15021 Fset_input_mode (Qt, Qnil, Qt, Qnil);
15023 #ifdef USE_X_TOOLKIT
15024 XtToolkitInitialize ();
15026 Xt_app_con = XtCreateApplicationContext ();
15028 /* Register a converter from strings to pixels, which uses
15029 Emacs' color allocation infrastructure. */
15030 XtAppSetTypeConverter (Xt_app_con,
15031 XtRString, XtRPixel, cvt_string_to_pixel,
15032 cvt_string_to_pixel_args,
15033 XtNumber (cvt_string_to_pixel_args),
15034 XtCacheByDisplay, cvt_pixel_dtor);
15036 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
15038 /* Install an asynchronous timer that processes Xt timeout events
15039 every 0.1s. This is necessary because some widget sets use
15040 timeouts internally, for example the LessTif menu bar, or the
15041 Xaw3d scroll bar. When Xt timouts aren't processed, these
15042 widgets don't behave normally. */
15044 EMACS_TIME interval;
15045 EMACS_SET_SECS_USECS (interval, 0, 100000);
15046 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
15048 #endif
15050 #ifdef USE_TOOLKIT_SCROLL_BARS
15051 xaw3d_arrow_scroll = False;
15052 xaw3d_pick_top = True;
15053 #endif
15055 /* Note that there is no real way portable across R3/R4 to get the
15056 original error handler. */
15057 XSetErrorHandler (x_error_handler);
15058 XSetIOErrorHandler (x_io_error_quitter);
15060 /* Disable Window Change signals; they are handled by X events. */
15061 #ifdef SIGWINCH
15062 signal (SIGWINCH, SIG_DFL);
15063 #endif /* ! defined (SIGWINCH) */
15065 signal (SIGPIPE, x_connection_signal);
15069 void
15070 syms_of_xterm ()
15072 staticpro (&x_error_message_string);
15073 x_error_message_string = Qnil;
15075 staticpro (&x_display_name_list);
15076 x_display_name_list = Qnil;
15078 staticpro (&last_mouse_scroll_bar);
15079 last_mouse_scroll_bar = Qnil;
15081 staticpro (&Qvendor_specific_keysyms);
15082 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
15084 staticpro (&last_mouse_press_frame);
15085 last_mouse_press_frame = Qnil;
15087 help_echo = Qnil;
15088 staticpro (&help_echo);
15089 help_echo_object = Qnil;
15090 staticpro (&help_echo_object);
15091 help_echo_window = Qnil;
15092 staticpro (&help_echo_window);
15093 previous_help_echo = Qnil;
15094 staticpro (&previous_help_echo);
15095 help_echo_pos = -1;
15097 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
15098 doc: /* *Non-nil means autoselect window with mouse pointer. */);
15099 x_autoselect_window_p = 0;
15101 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
15102 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
15103 For example, if a block cursor is over a tab, it will be drawn as
15104 wide as that tab on the display. */);
15105 x_stretch_cursor_p = 0;
15107 DEFVAR_BOOL ("x-use-underline-position-properties",
15108 &x_use_underline_position_properties,
15109 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15110 nil means ignore them. If you encounter fonts with bogus
15111 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15112 to 4.1, set this to nil. */);
15113 x_use_underline_position_properties = 1;
15115 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
15116 doc: /* What X toolkit scroll bars Emacs uses.
15117 A value of nil means Emacs doesn't use X toolkit scroll bars.
15118 Otherwise, value is a symbol describing the X toolkit. */);
15119 #ifdef USE_TOOLKIT_SCROLL_BARS
15120 #ifdef USE_MOTIF
15121 Vx_toolkit_scroll_bars = intern ("motif");
15122 #elif defined HAVE_XAW3D
15123 Vx_toolkit_scroll_bars = intern ("xaw3d");
15124 #else
15125 Vx_toolkit_scroll_bars = intern ("xaw");
15126 #endif
15127 #else
15128 Vx_toolkit_scroll_bars = Qnil;
15129 #endif
15131 staticpro (&last_mouse_motion_frame);
15132 last_mouse_motion_frame = Qnil;
15134 Qmodifier_value = intern ("modifier-value");
15135 Qalt = intern ("alt");
15136 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
15137 Qhyper = intern ("hyper");
15138 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
15139 Qmeta = intern ("meta");
15140 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
15141 Qsuper = intern ("super");
15142 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
15144 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
15145 doc: /* Which keys Emacs uses for the alt modifier.
15146 This should be one of the symbols `alt', `hyper', `meta', `super'.
15147 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15148 is nil, which is the same as `alt'. */);
15149 Vx_alt_keysym = Qnil;
15151 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
15152 doc: /* Which keys Emacs uses for the hyper modifier.
15153 This should be one of the symbols `alt', `hyper', `meta', `super'.
15154 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15155 default is nil, which is the same as `hyper'. */);
15156 Vx_hyper_keysym = Qnil;
15158 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
15159 doc: /* Which keys Emacs uses for the meta modifier.
15160 This should be one of the symbols `alt', `hyper', `meta', `super'.
15161 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15162 default is nil, which is the same as `meta'. */);
15163 Vx_meta_keysym = Qnil;
15165 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
15166 doc: /* Which keys Emacs uses for the super modifier.
15167 This should be one of the symbols `alt', `hyper', `meta', `super'.
15168 For example, `super' means use the Super_L and Super_R keysyms. The
15169 default is nil, which is the same as `super'. */);
15170 Vx_super_keysym = Qnil;
15174 #endif /* HAVE_X_WINDOWS */