(AC_PREREQ): Bump from 2.50 to 2.51; needed for vfork.
[emacs.git] / src / xterm.c
blob51b94c9fb37f3e31f5b594b0e0f605d7ab3cb21e
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 "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "process.h"
86 #include "atimer.h"
87 #include "keymap.h"
89 #ifdef USE_X_TOOLKIT
90 #include <X11/Shell.h>
91 #endif
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
100 #ifdef USE_LUCID
101 extern int xlwmenu_window_p (Widget w, Window window);
102 extern void xlwmenu_redisplay P_ ((Widget));
103 #endif
105 #ifdef USE_X_TOOLKIT
107 extern void free_frame_menubar P_ ((struct frame *));
108 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 #define HACK_EDITRES
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
116 /* Include toolkit specific headers for the scroll bar widget. */
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
124 #ifdef HAVE_XAW3D
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
133 #ifndef XtNpickTop
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
139 #endif /* USE_X_TOOLKIT */
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
144 #endif
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
153 #define abs(x) ((x) < 0 ? -(x) : (x))
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
158 /* Fringe bitmaps. */
160 enum fringe_bitmap_type
162 NO_FRINGE_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
174 #define zv_width 8
175 #define zv_height 72
176 #define zv_period 3
177 static unsigned char zv_bits[] = {
178 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
179 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
180 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
181 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
182 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
183 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
187 /* An arrow like this: `<-'. */
189 #define left_width 8
190 #define left_height 8
191 static unsigned char left_bits[] = {
192 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
194 /* Right truncation arrow bitmap `->'. */
196 #define right_width 8
197 #define right_height 8
198 static unsigned char right_bits[] = {
199 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
201 /* Marker for continued lines. */
203 #define continued_width 8
204 #define continued_height 8
205 static unsigned char continued_bits[] = {
206 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
208 /* Marker for continuation lines. */
210 #define continuation_width 8
211 #define continuation_height 8
212 static unsigned char continuation_bits[] = {
213 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
215 /* Overlay arrow bitmap. */
217 #if 0
218 /* A bomb. */
219 #define ov_width 8
220 #define ov_height 8
221 static unsigned char ov_bits[] = {
222 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
223 #else
224 /* A triangular arrow. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230 #endif
232 extern Lisp_Object Qhelp_echo;
235 /* Non-nil means Emacs uses toolkit scroll bars. */
237 Lisp_Object Vx_toolkit_scroll_bars;
239 /* If a string, XTread_socket generates an event to display that string.
240 (The display is done in read_char.) */
242 static Lisp_Object help_echo;
243 static Lisp_Object help_echo_window;
244 static Lisp_Object help_echo_object;
245 static int help_echo_pos;
247 /* Temporary variable for XTread_socket. */
249 static Lisp_Object previous_help_echo;
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
254 static int any_help_event_p;
256 /* Non-zero means draw block and hollow cursor as wide as the glyph
257 under it. For example, if a block cursor is over a tab, it will be
258 drawn as wide as that tab on the display. */
260 int x_stretch_cursor_p;
262 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
264 int x_use_underline_position_properties;
266 /* This is a chain of structures for all the X displays currently in
267 use. */
269 struct x_display_info *x_display_list;
271 /* This is a list of cons cells, each of the form (NAME
272 . FONT-LIST-CACHE), one for each element of x_display_list and in
273 the same order. NAME is the name of the frame. FONT-LIST-CACHE
274 records previous values returned by x-list-fonts. */
276 Lisp_Object x_display_name_list;
278 /* Frame being updated by update_frame. This is declared in term.c.
279 This is set by update_begin and looked at by all the XT functions.
280 It is zero while not inside an update. In that case, the XT
281 functions assume that `selected_frame' is the frame to apply to. */
283 extern struct frame *updating_frame;
285 /* This is a frame waiting to be auto-raised, within XTread_socket. */
287 struct frame *pending_autoraise_frame;
289 #ifdef USE_X_TOOLKIT
290 /* The application context for Xt use. */
291 XtAppContext Xt_app_con;
292 static String Xt_default_resources[] = {0};
293 #endif /* USE_X_TOOLKIT */
295 /* Nominal cursor position -- where to draw output.
296 HPOS and VPOS are window relative glyph matrix coordinates.
297 X and Y are window relative pixel coordinates. */
299 struct cursor_pos output_cursor;
301 /* Non-zero means user is interacting with a toolkit scroll bar. */
303 static int toolkit_scroll_bar_interaction;
305 /* Mouse movement.
307 Formerly, we used PointerMotionHintMask (in standard_event_mask)
308 so that we would have to call XQueryPointer after each MotionNotify
309 event to ask for another such event. However, this made mouse tracking
310 slow, and there was a bug that made it eventually stop.
312 Simply asking for MotionNotify all the time seems to work better.
314 In order to avoid asking for motion events and then throwing most
315 of them away or busy-polling the server for mouse positions, we ask
316 the server for pointer motion hints. This means that we get only
317 one event per group of mouse movements. "Groups" are delimited by
318 other kinds of events (focus changes and button clicks, for
319 example), or by XQueryPointer calls; when one of these happens, we
320 get another MotionNotify event the next time the mouse moves. This
321 is at least as efficient as getting motion events when mouse
322 tracking is on, and I suspect only negligibly worse when tracking
323 is off. */
325 /* Where the mouse was last time we reported a mouse event. */
327 FRAME_PTR last_mouse_frame;
328 static XRectangle last_mouse_glyph;
329 static Lisp_Object last_mouse_press_frame;
331 /* The scroll bar in which the last X motion event occurred.
333 If the last X motion event occurred in a scroll bar, we set this so
334 XTmouse_position can know whether to report a scroll bar motion or
335 an ordinary motion.
337 If the last X motion event didn't occur in a scroll bar, we set
338 this to Qnil, to tell XTmouse_position to return an ordinary motion
339 event. */
341 static Lisp_Object last_mouse_scroll_bar;
343 /* This is a hack. We would really prefer that XTmouse_position would
344 return the time associated with the position it returns, but there
345 doesn't seem to be any way to wrest the time-stamp from the server
346 along with the position query. So, we just keep track of the time
347 of the last movement we received, and return that in hopes that
348 it's somewhat accurate. */
350 static Time last_mouse_movement_time;
352 /* Incremented by XTread_socket whenever it really tries to read
353 events. */
355 #ifdef __STDC__
356 static int volatile input_signal_count;
357 #else
358 static int input_signal_count;
359 #endif
361 /* Used locally within XTread_socket. */
363 static int x_noop_count;
365 /* Initial values of argv and argc. */
367 extern char **initial_argv;
368 extern int initial_argc;
370 extern Lisp_Object Vcommand_line_args, Vsystem_name;
372 /* Tells if a window manager is present or not. */
374 extern Lisp_Object Vx_no_window_manager;
376 extern Lisp_Object Qface, Qmouse_face;
378 extern int errno;
380 /* A mask of extra modifier bits to put into every keyboard char. */
382 extern int extra_keyboard_modifiers;
384 static Lisp_Object Qvendor_specific_keysyms;
386 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
387 extern Lisp_Object x_icon_type P_ ((struct frame *));
390 /* Enumeration for overriding/changing the face to use for drawing
391 glyphs in x_draw_glyphs. */
393 enum draw_glyphs_face
395 DRAW_NORMAL_TEXT,
396 DRAW_INVERSE_VIDEO,
397 DRAW_CURSOR,
398 DRAW_MOUSE_FACE,
399 DRAW_IMAGE_RAISED,
400 DRAW_IMAGE_SUNKEN
403 static int cursor_in_mouse_face_p P_ ((struct window *));
404 static int clear_mouse_face P_ ((struct x_display_info *));
405 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
406 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
407 static const XColor *x_color_cells P_ ((Display *, int *));
408 static void x_update_window_end P_ ((struct window *, int, int));
409 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
410 void x_delete_display P_ ((struct x_display_info *));
411 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
412 unsigned));
413 static int fast_find_position P_ ((struct window *, int, int *, int *,
414 int *, int *, Lisp_Object));
415 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
416 int *, int *, int *, int *, int));
417 static void set_output_cursor P_ ((struct cursor_pos *));
418 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
419 int *, int *, int *, int));
420 static void note_mode_line_highlight P_ ((struct window *, int, int));
421 static void note_mouse_highlight P_ ((struct frame *, int, int));
422 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
423 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
424 static void show_mouse_face P_ ((struct x_display_info *,
425 enum draw_glyphs_face));
426 static int x_io_error_quitter P_ ((Display *));
427 int x_catch_errors P_ ((Display *));
428 void x_uncatch_errors P_ ((Display *, int));
429 void x_lower_frame P_ ((struct frame *));
430 void x_scroll_bar_clear P_ ((struct frame *));
431 int x_had_errors_p P_ ((Display *));
432 void x_wm_set_size_hint P_ ((struct frame *, long, int));
433 void x_raise_frame P_ ((struct frame *));
434 void x_set_window_size P_ ((struct frame *, int, int, int));
435 void x_wm_set_window_state P_ ((struct frame *, int));
436 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
437 void x_initialize P_ ((void));
438 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
439 static int x_compute_min_glyph_bounds P_ ((struct frame *));
440 static void x_draw_phys_cursor_glyph P_ ((struct window *,
441 struct glyph_row *,
442 enum draw_glyphs_face));
443 static void x_update_end P_ ((struct frame *));
444 static void XTframe_up_to_date P_ ((struct frame *));
445 static void XTset_terminal_modes P_ ((void));
446 static void XTreset_terminal_modes P_ ((void));
447 static void XTcursor_to P_ ((int, int, int, int));
448 static void x_write_glyphs P_ ((struct glyph *, int));
449 static void x_clear_end_of_line P_ ((int));
450 static void x_clear_frame P_ ((void));
451 static void x_clear_cursor P_ ((struct window *));
452 static void frame_highlight P_ ((struct frame *));
453 static void frame_unhighlight P_ ((struct frame *));
454 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
455 static void XTframe_rehighlight P_ ((struct frame *));
456 static void x_frame_rehighlight P_ ((struct x_display_info *));
457 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
458 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
459 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
460 XRectangle *));
461 static void expose_frame P_ ((struct frame *, int, int, int, int));
462 static int expose_window_tree P_ ((struct window *, XRectangle *));
463 static int expose_window P_ ((struct window *, XRectangle *));
464 static void expose_area P_ ((struct window *, struct glyph_row *,
465 XRectangle *, enum glyph_row_area));
466 static int expose_line P_ ((struct window *, struct glyph_row *,
467 XRectangle *));
468 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
469 static void x_update_window_cursor P_ ((struct window *, int));
470 static void x_erase_phys_cursor P_ ((struct window *));
471 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
472 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
473 enum fringe_bitmap_type, int left_p));
475 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
476 GC, int));
477 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
478 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
479 static void notice_overwritten_cursor P_ ((struct window *, int, int));
480 static void x_flush P_ ((struct frame *f));
481 static void x_update_begin P_ ((struct frame *));
482 static void x_update_window_begin P_ ((struct window *));
483 static void x_draw_vertical_border P_ ((struct window *));
484 static void x_after_update_window_line P_ ((struct glyph_row *));
485 static INLINE void take_vertical_position_into_account P_ ((struct it *));
486 static void x_produce_stretch_glyph P_ ((struct it *));
487 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
488 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
489 enum scroll_bar_part *,
490 Lisp_Object *, Lisp_Object *,
491 unsigned long *));
493 /* Flush display of frame F, or of all frames if F is null. */
495 static void
496 x_flush (f)
497 struct frame *f;
499 BLOCK_INPUT;
500 if (f == NULL)
502 Lisp_Object rest, frame;
503 FOR_EACH_FRAME (rest, frame)
504 x_flush (XFRAME (frame));
506 else if (FRAME_X_P (f))
507 XFlush (FRAME_X_DISPLAY (f));
508 UNBLOCK_INPUT;
512 /* Remove calls to XFlush by defining XFlush to an empty replacement.
513 Calls to XFlush should be unnecessary because the X output buffer
514 is flushed automatically as needed by calls to XPending,
515 XNextEvent, or XWindowEvent according to the XFlush man page.
516 XTread_socket calls XPending. Removing XFlush improves
517 performance. */
519 #define XFlush(DISPLAY) (void) 0
522 /***********************************************************************
523 Debugging
524 ***********************************************************************/
526 #if 0
528 /* This is a function useful for recording debugging information about
529 the sequence of occurrences in this file. */
531 struct record
533 char *locus;
534 int type;
537 struct record event_record[100];
539 int event_record_index;
541 record_event (locus, type)
542 char *locus;
543 int type;
545 if (event_record_index == sizeof (event_record) / sizeof (struct record))
546 event_record_index = 0;
548 event_record[event_record_index].locus = locus;
549 event_record[event_record_index].type = type;
550 event_record_index++;
553 #endif /* 0 */
557 /* Return the struct x_display_info corresponding to DPY. */
559 struct x_display_info *
560 x_display_info_for_display (dpy)
561 Display *dpy;
563 struct x_display_info *dpyinfo;
565 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
566 if (dpyinfo->display == dpy)
567 return dpyinfo;
569 return 0;
574 /***********************************************************************
575 Starting and ending an update
576 ***********************************************************************/
578 /* Start an update of frame F. This function is installed as a hook
579 for update_begin, i.e. it is called when update_begin is called.
580 This function is called prior to calls to x_update_window_begin for
581 each window being updated. Currently, there is nothing to do here
582 because all interesting stuff is done on a window basis. */
584 static void
585 x_update_begin (f)
586 struct frame *f;
588 /* Nothing to do. */
592 /* Start update of window W. Set the global variable updated_window
593 to the window being updated and set output_cursor to the cursor
594 position of W. */
596 static void
597 x_update_window_begin (w)
598 struct window *w;
600 struct frame *f = XFRAME (WINDOW_FRAME (w));
601 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
603 updated_window = w;
604 set_output_cursor (&w->cursor);
606 BLOCK_INPUT;
608 if (f == display_info->mouse_face_mouse_frame)
610 /* Don't do highlighting for mouse motion during the update. */
611 display_info->mouse_face_defer = 1;
613 /* If F needs to be redrawn, simply forget about any prior mouse
614 highlighting. */
615 if (FRAME_GARBAGED_P (f))
616 display_info->mouse_face_window = Qnil;
618 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
619 their mouse_face_p flag set, which means that they are always
620 unequal to rows in a desired matrix which never have that
621 flag set. So, rows containing mouse-face glyphs are never
622 scrolled, and we don't have to switch the mouse highlight off
623 here to prevent it from being scrolled. */
625 /* Can we tell that this update does not affect the window
626 where the mouse highlight is? If so, no need to turn off.
627 Likewise, don't do anything if the frame is garbaged;
628 in that case, the frame's current matrix that we would use
629 is all wrong, and we will redisplay that line anyway. */
630 if (!NILP (display_info->mouse_face_window)
631 && w == XWINDOW (display_info->mouse_face_window))
633 int i;
635 for (i = 0; i < w->desired_matrix->nrows; ++i)
636 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
637 break;
639 if (i < w->desired_matrix->nrows)
640 clear_mouse_face (display_info);
642 #endif /* 0 */
645 UNBLOCK_INPUT;
649 /* Draw a vertical window border to the right of window W if W doesn't
650 have vertical scroll bars. */
652 static void
653 x_draw_vertical_border (w)
654 struct window *w;
656 struct frame *f = XFRAME (WINDOW_FRAME (w));
658 /* Redraw borders between horizontally adjacent windows. Don't
659 do it for frames with vertical scroll bars because either the
660 right scroll bar of a window, or the left scroll bar of its
661 neighbor will suffice as a border. */
662 if (!WINDOW_RIGHTMOST_P (w)
663 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
665 int x0, x1, y0, y1;
667 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
668 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
669 y1 -= 1;
671 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
672 f->output_data.x->normal_gc, x1, y0, x1, y1);
677 /* End update of window W (which is equal to updated_window).
679 Draw vertical borders between horizontally adjacent windows, and
680 display W's cursor if CURSOR_ON_P is non-zero.
682 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
683 glyphs in mouse-face were overwritten. In that case we have to
684 make sure that the mouse-highlight is properly redrawn.
686 W may be a menu bar pseudo-window in case we don't have X toolkit
687 support. Such windows don't have a cursor, so don't display it
688 here. */
690 static void
691 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
692 struct window *w;
693 int cursor_on_p, mouse_face_overwritten_p;
695 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
697 if (!w->pseudo_window_p)
699 BLOCK_INPUT;
701 if (cursor_on_p)
702 x_display_and_set_cursor (w, 1, output_cursor.hpos,
703 output_cursor.vpos,
704 output_cursor.x, output_cursor.y);
706 x_draw_vertical_border (w);
707 UNBLOCK_INPUT;
710 /* If a row with mouse-face was overwritten, arrange for
711 XTframe_up_to_date to redisplay the mouse highlight. */
712 if (mouse_face_overwritten_p)
714 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
715 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
716 dpyinfo->mouse_face_window = Qnil;
719 updated_window = NULL;
723 /* End update of frame F. This function is installed as a hook in
724 update_end. */
726 static void
727 x_update_end (f)
728 struct frame *f;
730 /* Mouse highlight may be displayed again. */
731 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
733 BLOCK_INPUT;
734 XFlush (FRAME_X_DISPLAY (f));
735 UNBLOCK_INPUT;
739 /* This function is called from various places in xdisp.c whenever a
740 complete update has been performed. The global variable
741 updated_window is not available here. */
743 static void
744 XTframe_up_to_date (f)
745 struct frame *f;
747 if (FRAME_X_P (f))
749 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
751 if (dpyinfo->mouse_face_deferred_gc
752 || f == dpyinfo->mouse_face_mouse_frame)
754 BLOCK_INPUT;
755 if (dpyinfo->mouse_face_mouse_frame)
756 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
757 dpyinfo->mouse_face_mouse_x,
758 dpyinfo->mouse_face_mouse_y);
759 dpyinfo->mouse_face_deferred_gc = 0;
760 UNBLOCK_INPUT;
766 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
767 arrow bitmaps, or clear the fringes if no bitmaps are required
768 before DESIRED_ROW is made current. The window being updated is
769 found in updated_window. This function It is called from
770 update_window_line only if it is known that there are differences
771 between bitmaps to be drawn between current row and DESIRED_ROW. */
773 static void
774 x_after_update_window_line (desired_row)
775 struct glyph_row *desired_row;
777 struct window *w = updated_window;
778 struct frame *f;
779 int width, height;
781 xassert (w);
783 if (!desired_row->mode_line_p && !w->pseudo_window_p)
785 BLOCK_INPUT;
786 x_draw_row_fringe_bitmaps (w, desired_row);
787 UNBLOCK_INPUT;
790 /* When a window has disappeared, make sure that no rest of
791 full-width rows stays visible in the internal border. Could
792 check here if updated_window is the leftmost/rightmost window,
793 but I guess it's not worth doing since vertically split windows
794 are almost never used, internal border is rarely set, and the
795 overhead is very small. */
796 if (windows_or_buffers_changed
797 && desired_row->full_width_p
798 && (f = XFRAME (w->frame),
799 width = FRAME_INTERNAL_BORDER_WIDTH (f),
800 width != 0)
801 && (height = desired_row->visible_height,
802 height > 0))
804 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
806 /* Internal border is drawn below the tool bar. */
807 if (WINDOWP (f->tool_bar_window)
808 && w == XWINDOW (f->tool_bar_window))
809 y -= width;
811 BLOCK_INPUT;
812 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
813 0, y, width, height, False);
814 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
815 f->output_data.x->pixel_width - width,
816 y, width, height, False);
817 UNBLOCK_INPUT;
822 /* Draw the bitmap WHICH in one of the left or right fringes of
823 window W. ROW is the glyph row for which to display the bitmap; it
824 determines the vertical position at which the bitmap has to be
825 drawn. */
827 static void
828 x_draw_fringe_bitmap (w, row, which, left_p)
829 struct window *w;
830 struct glyph_row *row;
831 enum fringe_bitmap_type which;
832 int left_p;
834 struct frame *f = XFRAME (WINDOW_FRAME (w));
835 Display *display = FRAME_X_DISPLAY (f);
836 Window window = FRAME_X_WINDOW (f);
837 int x, y, wd, h, dy;
838 int b1, b2;
839 unsigned char *bits;
840 Pixmap pixmap;
841 GC gc = f->output_data.x->normal_gc;
842 struct face *face;
843 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
845 /* Must clip because of partially visible lines. */
846 x_clip_to_row (w, row, gc, 1);
848 /* Convert row to frame coordinates. */
849 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
851 switch (which)
853 case NO_FRINGE_BITMAP:
854 wd = 0;
855 h = 0;
856 break;
858 case LEFT_TRUNCATION_BITMAP:
859 wd = left_width;
860 h = left_height;
861 bits = left_bits;
862 break;
864 case OVERLAY_ARROW_BITMAP:
865 wd = ov_width;
866 h = ov_height;
867 bits = ov_bits;
868 break;
870 case RIGHT_TRUNCATION_BITMAP:
871 wd = right_width;
872 h = right_height;
873 bits = right_bits;
874 break;
876 case CONTINUED_LINE_BITMAP:
877 wd = continued_width;
878 h = continued_height;
879 bits = continued_bits;
880 break;
882 case CONTINUATION_LINE_BITMAP:
883 wd = continuation_width;
884 h = continuation_height;
885 bits = continuation_bits;
886 break;
888 case ZV_LINE_BITMAP:
889 wd = zv_width;
890 h = zv_height - (y % zv_period);
891 bits = zv_bits + (y % zv_period);
892 break;
894 default:
895 abort ();
898 /* Clip bitmap if too high. */
899 if (h > row->height)
900 h = row->height;
902 /* Set dy to the offset in the row to start drawing the bitmap. */
903 dy = (row->height - h) / 2;
905 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
906 PREPARE_FACE_FOR_DISPLAY (f, face);
908 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
909 the fringe. */
910 b1 = b2 = -1;
911 if (left_p)
913 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
914 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
915 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
916 - wd
917 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
918 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
920 /* If W has a vertical border to its left, don't draw over it. */
921 int border = ((XFASTINT (w->left) > 0
922 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
923 ? 1 : 0);
924 b1 = (window_box_left (w, -1)
925 - FRAME_X_LEFT_FRINGE_WIDTH (f)
926 + border);
927 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
930 else
932 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
933 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
934 x = (window_box_right (w, -1)
935 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
936 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
937 the fringe. */
938 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
940 b1 = window_box_right (w, -1);
941 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
945 if (b1 >= 0)
947 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
949 /* In case the same realized face is used for fringes and
950 for something displayed in the text (e.g. face `region' on
951 mono-displays, the fill style may have been changed to
952 FillSolid in x_draw_glyph_string_background. */
953 if (face->stipple)
954 XSetFillStyle (display, face->gc, FillOpaqueStippled);
955 else
956 XSetForeground (display, face->gc, face->background);
958 XFillRectangle (display, window, face->gc,
960 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
961 row->y)),
963 row->visible_height);
964 if (!face->stipple)
965 XSetForeground (display, face->gc, face->foreground);
968 if (which != NO_FRINGE_BITMAP)
970 /* Draw the bitmap. I believe these small pixmaps can be cached
971 by the server. */
972 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
973 face->foreground,
974 face->background, depth);
975 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
976 XFreePixmap (display, pixmap);
979 XSetClipMask (display, gc, None);
983 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
984 function with input blocked. */
986 static void
987 x_draw_row_fringe_bitmaps (w, row)
988 struct window *w;
989 struct glyph_row *row;
991 struct frame *f = XFRAME (w->frame);
992 enum fringe_bitmap_type bitmap;
994 xassert (interrupt_input_blocked);
996 /* If row is completely invisible, because of vscrolling, we
997 don't have to draw anything. */
998 if (row->visible_height <= 0)
999 return;
1001 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1003 /* Decide which bitmap to draw in the left fringe. */
1004 if (row->overlay_arrow_p)
1005 bitmap = OVERLAY_ARROW_BITMAP;
1006 else if (row->truncated_on_left_p)
1007 bitmap = LEFT_TRUNCATION_BITMAP;
1008 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1009 bitmap = CONTINUATION_LINE_BITMAP;
1010 else if (row->indicate_empty_line_p)
1011 bitmap = ZV_LINE_BITMAP;
1012 else
1013 bitmap = NO_FRINGE_BITMAP;
1015 x_draw_fringe_bitmap (w, row, bitmap, 1);
1018 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1020 /* Decide which bitmap to draw in the right fringe. */
1021 if (row->truncated_on_right_p)
1022 bitmap = RIGHT_TRUNCATION_BITMAP;
1023 else if (row->continued_p)
1024 bitmap = CONTINUED_LINE_BITMAP;
1025 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1026 bitmap = ZV_LINE_BITMAP;
1027 else
1028 bitmap = NO_FRINGE_BITMAP;
1030 x_draw_fringe_bitmap (w, row, bitmap, 0);
1036 /* This is called when starting Emacs and when restarting after
1037 suspend. When starting Emacs, no X window is mapped. And nothing
1038 must be done to Emacs's own window if it is suspended (though that
1039 rarely happens). */
1041 static void
1042 XTset_terminal_modes ()
1046 /* This is called when exiting or suspending Emacs. Exiting will make
1047 the X-windows go away, and suspending requires no action. */
1049 static void
1050 XTreset_terminal_modes ()
1056 /***********************************************************************
1057 Output Cursor
1058 ***********************************************************************/
1060 /* Set the global variable output_cursor to CURSOR. All cursor
1061 positions are relative to updated_window. */
1063 static void
1064 set_output_cursor (cursor)
1065 struct cursor_pos *cursor;
1067 output_cursor.hpos = cursor->hpos;
1068 output_cursor.vpos = cursor->vpos;
1069 output_cursor.x = cursor->x;
1070 output_cursor.y = cursor->y;
1074 /* Set a nominal cursor position.
1076 HPOS and VPOS are column/row positions in a window glyph matrix. X
1077 and Y are window text area relative pixel positions.
1079 If this is done during an update, updated_window will contain the
1080 window that is being updated and the position is the future output
1081 cursor position for that window. If updated_window is null, use
1082 selected_window and display the cursor at the given position. */
1084 static void
1085 XTcursor_to (vpos, hpos, y, x)
1086 int vpos, hpos, y, x;
1088 struct window *w;
1090 /* If updated_window is not set, work on selected_window. */
1091 if (updated_window)
1092 w = updated_window;
1093 else
1094 w = XWINDOW (selected_window);
1096 /* Set the output cursor. */
1097 output_cursor.hpos = hpos;
1098 output_cursor.vpos = vpos;
1099 output_cursor.x = x;
1100 output_cursor.y = y;
1102 /* If not called as part of an update, really display the cursor.
1103 This will also set the cursor position of W. */
1104 if (updated_window == NULL)
1106 BLOCK_INPUT;
1107 x_display_cursor (w, 1, hpos, vpos, x, y);
1108 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1109 UNBLOCK_INPUT;
1115 /***********************************************************************
1116 Display Iterator
1117 ***********************************************************************/
1119 /* Function prototypes of this page. */
1121 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1122 struct glyph *,
1123 XChar2b *,
1124 int *));
1125 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1126 int, XChar2b *, int));
1127 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1128 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1129 static void x_append_glyph P_ ((struct it *));
1130 static void x_append_composite_glyph P_ ((struct it *));
1131 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1132 int, int, double));
1133 static void x_produce_glyphs P_ ((struct it *));
1134 static void x_produce_image_glyph P_ ((struct it *it));
1137 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1138 is not contained in the font. */
1140 static INLINE XCharStruct *
1141 x_per_char_metric (font, char2b)
1142 XFontStruct *font;
1143 XChar2b *char2b;
1145 /* The result metric information. */
1146 XCharStruct *pcm = NULL;
1148 xassert (font && char2b);
1150 if (font->per_char != NULL)
1152 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1154 /* min_char_or_byte2 specifies the linear character index
1155 corresponding to the first element of the per_char array,
1156 max_char_or_byte2 is the index of the last character. A
1157 character with non-zero CHAR2B->byte1 is not in the font.
1158 A character with byte2 less than min_char_or_byte2 or
1159 greater max_char_or_byte2 is not in the font. */
1160 if (char2b->byte1 == 0
1161 && char2b->byte2 >= font->min_char_or_byte2
1162 && char2b->byte2 <= font->max_char_or_byte2)
1163 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1165 else
1167 /* If either min_byte1 or max_byte1 are nonzero, both
1168 min_char_or_byte2 and max_char_or_byte2 are less than
1169 256, and the 2-byte character index values corresponding
1170 to the per_char array element N (counting from 0) are:
1172 byte1 = N/D + min_byte1
1173 byte2 = N\D + min_char_or_byte2
1175 where:
1177 D = max_char_or_byte2 - min_char_or_byte2 + 1
1178 / = integer division
1179 \ = integer modulus */
1180 if (char2b->byte1 >= font->min_byte1
1181 && char2b->byte1 <= font->max_byte1
1182 && char2b->byte2 >= font->min_char_or_byte2
1183 && char2b->byte2 <= font->max_char_or_byte2)
1185 pcm = (font->per_char
1186 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1187 * (char2b->byte1 - font->min_byte1))
1188 + (char2b->byte2 - font->min_char_or_byte2));
1192 else
1194 /* If the per_char pointer is null, all glyphs between the first
1195 and last character indexes inclusive have the same
1196 information, as given by both min_bounds and max_bounds. */
1197 if (char2b->byte2 >= font->min_char_or_byte2
1198 && char2b->byte2 <= font->max_char_or_byte2)
1199 pcm = &font->max_bounds;
1202 return ((pcm == NULL
1203 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1204 ? NULL : pcm);
1208 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1209 the two-byte form of C. Encoding is returned in *CHAR2B. */
1211 static INLINE void
1212 x_encode_char (c, char2b, font_info)
1213 int c;
1214 XChar2b *char2b;
1215 struct font_info *font_info;
1217 int charset = CHAR_CHARSET (c);
1218 XFontStruct *font = font_info->font;
1220 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1221 This may be either a program in a special encoder language or a
1222 fixed encoding. */
1223 if (font_info->font_encoder)
1225 /* It's a program. */
1226 struct ccl_program *ccl = font_info->font_encoder;
1228 if (CHARSET_DIMENSION (charset) == 1)
1230 ccl->reg[0] = charset;
1231 ccl->reg[1] = char2b->byte2;
1233 else
1235 ccl->reg[0] = charset;
1236 ccl->reg[1] = char2b->byte1;
1237 ccl->reg[2] = char2b->byte2;
1240 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1242 /* We assume that MSBs are appropriately set/reset by CCL
1243 program. */
1244 if (font->max_byte1 == 0) /* 1-byte font */
1245 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1246 else
1247 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1249 else if (font_info->encoding[charset])
1251 /* Fixed encoding scheme. See fontset.h for the meaning of the
1252 encoding numbers. */
1253 int enc = font_info->encoding[charset];
1255 if ((enc == 1 || enc == 2)
1256 && CHARSET_DIMENSION (charset) == 2)
1257 char2b->byte1 |= 0x80;
1259 if (enc == 1 || enc == 3)
1260 char2b->byte2 |= 0x80;
1265 /* Get face and two-byte form of character C in face FACE_ID on frame
1266 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1267 means we want to display multibyte text. Value is a pointer to a
1268 realized face that is ready for display. */
1270 static INLINE struct face *
1271 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1272 struct frame *f;
1273 int c, face_id;
1274 XChar2b *char2b;
1275 int multibyte_p;
1277 struct face *face = FACE_FROM_ID (f, face_id);
1279 if (!multibyte_p)
1281 /* Unibyte case. We don't have to encode, but we have to make
1282 sure to use a face suitable for unibyte. */
1283 char2b->byte1 = 0;
1284 char2b->byte2 = c;
1285 face_id = FACE_FOR_CHAR (f, face, c);
1286 face = FACE_FROM_ID (f, face_id);
1288 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1290 /* Case of ASCII in a face known to fit ASCII. */
1291 char2b->byte1 = 0;
1292 char2b->byte2 = c;
1294 else
1296 int c1, c2, charset;
1298 /* Split characters into bytes. If c2 is -1 afterwards, C is
1299 really a one-byte character so that byte1 is zero. */
1300 SPLIT_CHAR (c, charset, c1, c2);
1301 if (c2 > 0)
1302 char2b->byte1 = c1, char2b->byte2 = c2;
1303 else
1304 char2b->byte1 = 0, char2b->byte2 = c1;
1306 /* Maybe encode the character in *CHAR2B. */
1307 if (face->font != NULL)
1309 struct font_info *font_info
1310 = FONT_INFO_FROM_ID (f, face->font_info_id);
1311 if (font_info)
1312 x_encode_char (c, char2b, font_info);
1316 /* Make sure X resources of the face are allocated. */
1317 xassert (face != NULL);
1318 PREPARE_FACE_FOR_DISPLAY (f, face);
1320 return face;
1324 /* Get face and two-byte form of character glyph GLYPH on frame F.
1325 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1326 a pointer to a realized face that is ready for display. */
1328 static INLINE struct face *
1329 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1330 struct frame *f;
1331 struct glyph *glyph;
1332 XChar2b *char2b;
1333 int *two_byte_p;
1335 struct face *face;
1337 xassert (glyph->type == CHAR_GLYPH);
1338 face = FACE_FROM_ID (f, glyph->face_id);
1340 if (two_byte_p)
1341 *two_byte_p = 0;
1343 if (!glyph->multibyte_p)
1345 /* Unibyte case. We don't have to encode, but we have to make
1346 sure to use a face suitable for unibyte. */
1347 char2b->byte1 = 0;
1348 char2b->byte2 = glyph->u.ch;
1350 else if (glyph->u.ch < 128
1351 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1353 /* Case of ASCII in a face known to fit ASCII. */
1354 char2b->byte1 = 0;
1355 char2b->byte2 = glyph->u.ch;
1357 else
1359 int c1, c2, charset;
1361 /* Split characters into bytes. If c2 is -1 afterwards, C is
1362 really a one-byte character so that byte1 is zero. */
1363 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1364 if (c2 > 0)
1365 char2b->byte1 = c1, char2b->byte2 = c2;
1366 else
1367 char2b->byte1 = 0, char2b->byte2 = c1;
1369 /* Maybe encode the character in *CHAR2B. */
1370 if (charset != CHARSET_ASCII)
1372 struct font_info *font_info
1373 = FONT_INFO_FROM_ID (f, face->font_info_id);
1374 if (font_info)
1376 x_encode_char (glyph->u.ch, char2b, font_info);
1377 if (two_byte_p)
1378 *two_byte_p
1379 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1384 /* Make sure X resources of the face are allocated. */
1385 xassert (face != NULL);
1386 PREPARE_FACE_FOR_DISPLAY (f, face);
1387 return face;
1391 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1392 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1394 static INLINE void
1395 x_append_glyph (it)
1396 struct it *it;
1398 struct glyph *glyph;
1399 enum glyph_row_area area = it->area;
1401 xassert (it->glyph_row);
1402 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1404 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1405 if (glyph < it->glyph_row->glyphs[area + 1])
1407 glyph->charpos = CHARPOS (it->position);
1408 glyph->object = it->object;
1409 glyph->pixel_width = it->pixel_width;
1410 glyph->voffset = it->voffset;
1411 glyph->type = CHAR_GLYPH;
1412 glyph->multibyte_p = it->multibyte_p;
1413 glyph->left_box_line_p = it->start_of_box_run_p;
1414 glyph->right_box_line_p = it->end_of_box_run_p;
1415 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1416 || it->phys_descent > it->descent);
1417 glyph->padding_p = 0;
1418 glyph->glyph_not_available_p = it->glyph_not_available_p;
1419 glyph->face_id = it->face_id;
1420 glyph->u.ch = it->char_to_display;
1421 ++it->glyph_row->used[area];
1425 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1426 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1428 static INLINE void
1429 x_append_composite_glyph (it)
1430 struct it *it;
1432 struct glyph *glyph;
1433 enum glyph_row_area area = it->area;
1435 xassert (it->glyph_row);
1437 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1438 if (glyph < it->glyph_row->glyphs[area + 1])
1440 glyph->charpos = CHARPOS (it->position);
1441 glyph->object = it->object;
1442 glyph->pixel_width = it->pixel_width;
1443 glyph->voffset = it->voffset;
1444 glyph->type = COMPOSITE_GLYPH;
1445 glyph->multibyte_p = it->multibyte_p;
1446 glyph->left_box_line_p = it->start_of_box_run_p;
1447 glyph->right_box_line_p = it->end_of_box_run_p;
1448 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1449 || it->phys_descent > it->descent);
1450 glyph->padding_p = 0;
1451 glyph->glyph_not_available_p = 0;
1452 glyph->face_id = it->face_id;
1453 glyph->u.cmp_id = it->cmp_id;
1454 ++it->glyph_row->used[area];
1459 /* Change IT->ascent and IT->height according to the setting of
1460 IT->voffset. */
1462 static INLINE void
1463 take_vertical_position_into_account (it)
1464 struct it *it;
1466 if (it->voffset)
1468 if (it->voffset < 0)
1469 /* Increase the ascent so that we can display the text higher
1470 in the line. */
1471 it->ascent += abs (it->voffset);
1472 else
1473 /* Increase the descent so that we can display the text lower
1474 in the line. */
1475 it->descent += it->voffset;
1480 /* Produce glyphs/get display metrics for the image IT is loaded with.
1481 See the description of struct display_iterator in dispextern.h for
1482 an overview of struct display_iterator. */
1484 static void
1485 x_produce_image_glyph (it)
1486 struct it *it;
1488 struct image *img;
1489 struct face *face;
1491 xassert (it->what == IT_IMAGE);
1493 face = FACE_FROM_ID (it->f, it->face_id);
1494 img = IMAGE_FROM_ID (it->f, it->image_id);
1495 xassert (img);
1497 /* Make sure X resources of the face and image are loaded. */
1498 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1499 prepare_image_for_display (it->f, img);
1501 it->ascent = it->phys_ascent = image_ascent (img, face);
1502 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1503 it->pixel_width = img->width + 2 * img->hmargin;
1505 it->nglyphs = 1;
1507 if (face->box != FACE_NO_BOX)
1509 if (face->box_line_width > 0)
1511 it->ascent += face->box_line_width;
1512 it->descent += face->box_line_width;
1515 if (it->start_of_box_run_p)
1516 it->pixel_width += abs (face->box_line_width);
1517 if (it->end_of_box_run_p)
1518 it->pixel_width += abs (face->box_line_width);
1521 take_vertical_position_into_account (it);
1523 if (it->glyph_row)
1525 struct glyph *glyph;
1526 enum glyph_row_area area = it->area;
1528 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1529 if (glyph < it->glyph_row->glyphs[area + 1])
1531 glyph->charpos = CHARPOS (it->position);
1532 glyph->object = it->object;
1533 glyph->pixel_width = it->pixel_width;
1534 glyph->voffset = it->voffset;
1535 glyph->type = IMAGE_GLYPH;
1536 glyph->multibyte_p = it->multibyte_p;
1537 glyph->left_box_line_p = it->start_of_box_run_p;
1538 glyph->right_box_line_p = it->end_of_box_run_p;
1539 glyph->overlaps_vertically_p = 0;
1540 glyph->padding_p = 0;
1541 glyph->glyph_not_available_p = 0;
1542 glyph->face_id = it->face_id;
1543 glyph->u.img_id = img->id;
1544 ++it->glyph_row->used[area];
1550 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1551 of the glyph, WIDTH and HEIGHT are the width and height of the
1552 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1553 ascent of the glyph (0 <= ASCENT <= 1). */
1555 static void
1556 x_append_stretch_glyph (it, object, width, height, ascent)
1557 struct it *it;
1558 Lisp_Object object;
1559 int width, height;
1560 double ascent;
1562 struct glyph *glyph;
1563 enum glyph_row_area area = it->area;
1565 xassert (ascent >= 0 && ascent <= 1);
1567 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1568 if (glyph < it->glyph_row->glyphs[area + 1])
1570 glyph->charpos = CHARPOS (it->position);
1571 glyph->object = object;
1572 glyph->pixel_width = width;
1573 glyph->voffset = it->voffset;
1574 glyph->type = STRETCH_GLYPH;
1575 glyph->multibyte_p = it->multibyte_p;
1576 glyph->left_box_line_p = it->start_of_box_run_p;
1577 glyph->right_box_line_p = it->end_of_box_run_p;
1578 glyph->overlaps_vertically_p = 0;
1579 glyph->padding_p = 0;
1580 glyph->glyph_not_available_p = 0;
1581 glyph->face_id = it->face_id;
1582 glyph->u.stretch.ascent = height * ascent;
1583 glyph->u.stretch.height = height;
1584 ++it->glyph_row->used[area];
1589 /* Produce a stretch glyph for iterator IT. IT->object is the value
1590 of the glyph property displayed. The value must be a list
1591 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1592 being recognized:
1594 1. `:width WIDTH' specifies that the space should be WIDTH *
1595 canonical char width wide. WIDTH may be an integer or floating
1596 point number.
1598 2. `:relative-width FACTOR' specifies that the width of the stretch
1599 should be computed from the width of the first character having the
1600 `glyph' property, and should be FACTOR times that width.
1602 3. `:align-to HPOS' specifies that the space should be wide enough
1603 to reach HPOS, a value in canonical character units.
1605 Exactly one of the above pairs must be present.
1607 4. `:height HEIGHT' specifies that the height of the stretch produced
1608 should be HEIGHT, measured in canonical character units.
1610 5. `:relative-height FACTOR' specifies that the height of the the
1611 stretch should be FACTOR times the height of the characters having
1612 the glyph property.
1614 Either none or exactly one of 4 or 5 must be present.
1616 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1617 of the stretch should be used for the ascent of the stretch.
1618 ASCENT must be in the range 0 <= ASCENT <= 100. */
1620 #define NUMVAL(X) \
1621 ((INTEGERP (X) || FLOATP (X)) \
1622 ? XFLOATINT (X) \
1623 : - 1)
1626 static void
1627 x_produce_stretch_glyph (it)
1628 struct it *it;
1630 /* (space :width WIDTH :height HEIGHT. */
1631 #if GLYPH_DEBUG
1632 extern Lisp_Object Qspace;
1633 #endif
1634 extern Lisp_Object QCwidth, QCheight, QCascent;
1635 extern Lisp_Object QCrelative_width, QCrelative_height;
1636 extern Lisp_Object QCalign_to;
1637 Lisp_Object prop, plist;
1638 double width = 0, height = 0, ascent = 0;
1639 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1640 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1642 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1644 /* List should start with `space'. */
1645 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1646 plist = XCDR (it->object);
1648 /* Compute the width of the stretch. */
1649 if (prop = Fplist_get (plist, QCwidth),
1650 NUMVAL (prop) > 0)
1651 /* Absolute width `:width WIDTH' specified and valid. */
1652 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1653 else if (prop = Fplist_get (plist, QCrelative_width),
1654 NUMVAL (prop) > 0)
1656 /* Relative width `:relative-width FACTOR' specified and valid.
1657 Compute the width of the characters having the `glyph'
1658 property. */
1659 struct it it2;
1660 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1662 it2 = *it;
1663 if (it->multibyte_p)
1665 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1666 - IT_BYTEPOS (*it));
1667 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1669 else
1670 it2.c = *p, it2.len = 1;
1672 it2.glyph_row = NULL;
1673 it2.what = IT_CHARACTER;
1674 x_produce_glyphs (&it2);
1675 width = NUMVAL (prop) * it2.pixel_width;
1677 else if (prop = Fplist_get (plist, QCalign_to),
1678 NUMVAL (prop) > 0)
1679 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1680 else
1681 /* Nothing specified -> width defaults to canonical char width. */
1682 width = CANON_X_UNIT (it->f);
1684 /* Compute height. */
1685 if (prop = Fplist_get (plist, QCheight),
1686 NUMVAL (prop) > 0)
1687 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1688 else if (prop = Fplist_get (plist, QCrelative_height),
1689 NUMVAL (prop) > 0)
1690 height = FONT_HEIGHT (font) * NUMVAL (prop);
1691 else
1692 height = FONT_HEIGHT (font);
1694 /* Compute percentage of height used for ascent. If
1695 `:ascent ASCENT' is present and valid, use that. Otherwise,
1696 derive the ascent from the font in use. */
1697 if (prop = Fplist_get (plist, QCascent),
1698 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1699 ascent = NUMVAL (prop) / 100.0;
1700 else
1701 ascent = (double) font->ascent / FONT_HEIGHT (font);
1703 if (width <= 0)
1704 width = 1;
1705 if (height <= 0)
1706 height = 1;
1708 if (it->glyph_row)
1710 Lisp_Object object = it->stack[it->sp - 1].string;
1711 if (!STRINGP (object))
1712 object = it->w->buffer;
1713 x_append_stretch_glyph (it, object, width, height, ascent);
1716 it->pixel_width = width;
1717 it->ascent = it->phys_ascent = height * ascent;
1718 it->descent = it->phys_descent = height - it->ascent;
1719 it->nglyphs = 1;
1721 if (face->box != FACE_NO_BOX)
1723 if (face->box_line_width > 0)
1725 it->ascent += face->box_line_width;
1726 it->descent += face->box_line_width;
1729 if (it->start_of_box_run_p)
1730 it->pixel_width += abs (face->box_line_width);
1731 if (it->end_of_box_run_p)
1732 it->pixel_width += abs (face->box_line_width);
1735 take_vertical_position_into_account (it);
1738 /* Return proper value to be used as baseline offset of font that has
1739 ASCENT and DESCENT to draw characters by the font at the vertical
1740 center of the line of frame F.
1742 Here, out task is to find the value of BOFF in the following figure;
1744 -------------------------+-----------+-
1745 -+-+---------+-+ | |
1746 | | | | | |
1747 | | | | F_ASCENT F_HEIGHT
1748 | | | ASCENT | |
1749 HEIGHT | | | | |
1750 | | |-|-+------+-----------|------- baseline
1751 | | | | BOFF | |
1752 | |---------|-+-+ | |
1753 | | | DESCENT | |
1754 -+-+---------+-+ F_DESCENT |
1755 -------------------------+-----------+-
1757 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1758 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1759 DESCENT = FONT->descent
1760 HEIGHT = FONT_HEIGHT (FONT)
1761 F_DESCENT = (F->output_data.x->font->descent
1762 - F->output_data.x->baseline_offset)
1763 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1766 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1767 ((FONT)->descent \
1768 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1769 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1770 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1772 /* Produce glyphs/get display metrics for the display element IT is
1773 loaded with. See the description of struct display_iterator in
1774 dispextern.h for an overview of struct display_iterator. */
1776 static void
1777 x_produce_glyphs (it)
1778 struct it *it;
1780 it->glyph_not_available_p = 0;
1782 if (it->what == IT_CHARACTER)
1784 XChar2b char2b;
1785 XFontStruct *font;
1786 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1787 XCharStruct *pcm;
1788 int font_not_found_p;
1789 struct font_info *font_info;
1790 int boff; /* baseline offset */
1791 /* We may change it->multibyte_p upon unibyte<->multibyte
1792 conversion. So, save the current value now and restore it
1793 later.
1795 Note: It seems that we don't have to record multibyte_p in
1796 struct glyph because the character code itself tells if or
1797 not the character is multibyte. Thus, in the future, we must
1798 consider eliminating the field `multibyte_p' in the struct
1799 glyph. */
1800 int saved_multibyte_p = it->multibyte_p;
1802 /* Maybe translate single-byte characters to multibyte, or the
1803 other way. */
1804 it->char_to_display = it->c;
1805 if (!ASCII_BYTE_P (it->c))
1807 if (unibyte_display_via_language_environment
1808 && SINGLE_BYTE_CHAR_P (it->c)
1809 && (it->c >= 0240
1810 || !NILP (Vnonascii_translation_table)))
1812 it->char_to_display = unibyte_char_to_multibyte (it->c);
1813 it->multibyte_p = 1;
1814 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1815 face = FACE_FROM_ID (it->f, it->face_id);
1817 else if (!SINGLE_BYTE_CHAR_P (it->c)
1818 && !it->multibyte_p)
1820 it->multibyte_p = 1;
1821 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1822 face = FACE_FROM_ID (it->f, it->face_id);
1826 /* Get font to use. Encode IT->char_to_display. */
1827 x_get_char_face_and_encoding (it->f, it->char_to_display,
1828 it->face_id, &char2b,
1829 it->multibyte_p);
1830 font = face->font;
1832 /* When no suitable font found, use the default font. */
1833 font_not_found_p = font == NULL;
1834 if (font_not_found_p)
1836 font = FRAME_FONT (it->f);
1837 boff = it->f->output_data.x->baseline_offset;
1838 font_info = NULL;
1840 else
1842 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1843 boff = font_info->baseline_offset;
1844 if (font_info->vertical_centering)
1845 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1848 if (it->char_to_display >= ' '
1849 && (!it->multibyte_p || it->char_to_display < 128))
1851 /* Either unibyte or ASCII. */
1852 int stretched_p;
1854 it->nglyphs = 1;
1856 pcm = x_per_char_metric (font, &char2b);
1857 it->ascent = font->ascent + boff;
1858 it->descent = font->descent - boff;
1860 if (pcm)
1862 it->phys_ascent = pcm->ascent + boff;
1863 it->phys_descent = pcm->descent - boff;
1864 it->pixel_width = pcm->width;
1866 else
1868 it->glyph_not_available_p = 1;
1869 it->phys_ascent = font->ascent + boff;
1870 it->phys_descent = font->descent - boff;
1871 it->pixel_width = FONT_WIDTH (font);
1874 /* If this is a space inside a region of text with
1875 `space-width' property, change its width. */
1876 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1877 if (stretched_p)
1878 it->pixel_width *= XFLOATINT (it->space_width);
1880 /* If face has a box, add the box thickness to the character
1881 height. If character has a box line to the left and/or
1882 right, add the box line width to the character's width. */
1883 if (face->box != FACE_NO_BOX)
1885 int thick = face->box_line_width;
1887 if (thick > 0)
1889 it->ascent += thick;
1890 it->descent += thick;
1892 else
1893 thick = -thick;
1895 if (it->start_of_box_run_p)
1896 it->pixel_width += thick;
1897 if (it->end_of_box_run_p)
1898 it->pixel_width += thick;
1901 /* If face has an overline, add the height of the overline
1902 (1 pixel) and a 1 pixel margin to the character height. */
1903 if (face->overline_p)
1904 it->ascent += 2;
1906 take_vertical_position_into_account (it);
1908 /* If we have to actually produce glyphs, do it. */
1909 if (it->glyph_row)
1911 if (stretched_p)
1913 /* Translate a space with a `space-width' property
1914 into a stretch glyph. */
1915 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1916 x_append_stretch_glyph (it, it->object, it->pixel_width,
1917 it->ascent + it->descent, ascent);
1919 else
1920 x_append_glyph (it);
1922 /* If characters with lbearing or rbearing are displayed
1923 in this line, record that fact in a flag of the
1924 glyph row. This is used to optimize X output code. */
1925 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1926 it->glyph_row->contains_overlapping_glyphs_p = 1;
1929 else if (it->char_to_display == '\n')
1931 /* A newline has no width but we need the height of the line. */
1932 it->pixel_width = 0;
1933 it->nglyphs = 0;
1934 it->ascent = it->phys_ascent = font->ascent + boff;
1935 it->descent = it->phys_descent = font->descent - boff;
1937 if (face->box != FACE_NO_BOX
1938 && face->box_line_width > 0)
1940 it->ascent += face->box_line_width;
1941 it->descent += face->box_line_width;
1944 else if (it->char_to_display == '\t')
1946 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1947 int x = it->current_x + it->continuation_lines_width;
1948 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1950 /* If the distance from the current position to the next tab
1951 stop is less than a canonical character width, use the
1952 tab stop after that. */
1953 if (next_tab_x - x < CANON_X_UNIT (it->f))
1954 next_tab_x += tab_width;
1956 it->pixel_width = next_tab_x - x;
1957 it->nglyphs = 1;
1958 it->ascent = it->phys_ascent = font->ascent + boff;
1959 it->descent = it->phys_descent = font->descent - boff;
1961 if (it->glyph_row)
1963 double ascent = (double) it->ascent / (it->ascent + it->descent);
1964 x_append_stretch_glyph (it, it->object, it->pixel_width,
1965 it->ascent + it->descent, ascent);
1968 else
1970 /* A multi-byte character. Assume that the display width of the
1971 character is the width of the character multiplied by the
1972 width of the font. */
1974 /* If we found a font, this font should give us the right
1975 metrics. If we didn't find a font, use the frame's
1976 default font and calculate the width of the character
1977 from the charset width; this is what old redisplay code
1978 did. */
1979 pcm = x_per_char_metric (font, &char2b);
1980 if (font_not_found_p || !pcm)
1982 int charset = CHAR_CHARSET (it->char_to_display);
1984 it->glyph_not_available_p = 1;
1985 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1986 * CHARSET_WIDTH (charset));
1987 it->phys_ascent = font->ascent + boff;
1988 it->phys_descent = font->descent - boff;
1990 else
1992 it->pixel_width = pcm->width;
1993 it->phys_ascent = pcm->ascent + boff;
1994 it->phys_descent = pcm->descent - boff;
1995 if (it->glyph_row
1996 && (pcm->lbearing < 0
1997 || pcm->rbearing > pcm->width))
1998 it->glyph_row->contains_overlapping_glyphs_p = 1;
2000 it->nglyphs = 1;
2001 it->ascent = font->ascent + boff;
2002 it->descent = font->descent - boff;
2003 if (face->box != FACE_NO_BOX)
2005 int thick = face->box_line_width;
2007 if (thick > 0)
2009 it->ascent += thick;
2010 it->descent += thick;
2012 else
2013 thick = - thick;
2015 if (it->start_of_box_run_p)
2016 it->pixel_width += thick;
2017 if (it->end_of_box_run_p)
2018 it->pixel_width += thick;
2021 /* If face has an overline, add the height of the overline
2022 (1 pixel) and a 1 pixel margin to the character height. */
2023 if (face->overline_p)
2024 it->ascent += 2;
2026 take_vertical_position_into_account (it);
2028 if (it->glyph_row)
2029 x_append_glyph (it);
2031 it->multibyte_p = saved_multibyte_p;
2033 else if (it->what == IT_COMPOSITION)
2035 /* Note: A composition is represented as one glyph in the
2036 glyph matrix. There are no padding glyphs. */
2037 XChar2b char2b;
2038 XFontStruct *font;
2039 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2040 XCharStruct *pcm;
2041 int font_not_found_p;
2042 struct font_info *font_info;
2043 int boff; /* baseline offset */
2044 struct composition *cmp = composition_table[it->cmp_id];
2046 /* Maybe translate single-byte characters to multibyte. */
2047 it->char_to_display = it->c;
2048 if (unibyte_display_via_language_environment
2049 && SINGLE_BYTE_CHAR_P (it->c)
2050 && (it->c >= 0240
2051 || (it->c >= 0200
2052 && !NILP (Vnonascii_translation_table))))
2054 it->char_to_display = unibyte_char_to_multibyte (it->c);
2057 /* Get face and font to use. Encode IT->char_to_display. */
2058 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2059 face = FACE_FROM_ID (it->f, it->face_id);
2060 x_get_char_face_and_encoding (it->f, it->char_to_display,
2061 it->face_id, &char2b, it->multibyte_p);
2062 font = face->font;
2064 /* When no suitable font found, use the default font. */
2065 font_not_found_p = font == NULL;
2066 if (font_not_found_p)
2068 font = FRAME_FONT (it->f);
2069 boff = it->f->output_data.x->baseline_offset;
2070 font_info = NULL;
2072 else
2074 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2075 boff = font_info->baseline_offset;
2076 if (font_info->vertical_centering)
2077 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2080 /* There are no padding glyphs, so there is only one glyph to
2081 produce for the composition. Important is that pixel_width,
2082 ascent and descent are the values of what is drawn by
2083 draw_glyphs (i.e. the values of the overall glyphs composed). */
2084 it->nglyphs = 1;
2086 /* If we have not yet calculated pixel size data of glyphs of
2087 the composition for the current face font, calculate them
2088 now. Theoretically, we have to check all fonts for the
2089 glyphs, but that requires much time and memory space. So,
2090 here we check only the font of the first glyph. This leads
2091 to incorrect display very rarely, and C-l (recenter) can
2092 correct the display anyway. */
2093 if (cmp->font != (void *) font)
2095 /* Ascent and descent of the font of the first character of
2096 this composition (adjusted by baseline offset). Ascent
2097 and descent of overall glyphs should not be less than
2098 them respectively. */
2099 int font_ascent = font->ascent + boff;
2100 int font_descent = font->descent - boff;
2101 /* Bounding box of the overall glyphs. */
2102 int leftmost, rightmost, lowest, highest;
2103 int i, width, ascent, descent;
2105 cmp->font = (void *) font;
2107 /* Initialize the bounding box. */
2108 if (font_info
2109 && (pcm = x_per_char_metric (font, &char2b)))
2111 width = pcm->width;
2112 ascent = pcm->ascent;
2113 descent = pcm->descent;
2115 else
2117 width = FONT_WIDTH (font);
2118 ascent = font->ascent;
2119 descent = font->descent;
2122 rightmost = width;
2123 lowest = - descent + boff;
2124 highest = ascent + boff;
2125 leftmost = 0;
2127 if (font_info
2128 && font_info->default_ascent
2129 && CHAR_TABLE_P (Vuse_default_ascent)
2130 && !NILP (Faref (Vuse_default_ascent,
2131 make_number (it->char_to_display))))
2132 highest = font_info->default_ascent + boff;
2134 /* Draw the first glyph at the normal position. It may be
2135 shifted to right later if some other glyphs are drawn at
2136 the left. */
2137 cmp->offsets[0] = 0;
2138 cmp->offsets[1] = boff;
2140 /* Set cmp->offsets for the remaining glyphs. */
2141 for (i = 1; i < cmp->glyph_len; i++)
2143 int left, right, btm, top;
2144 int ch = COMPOSITION_GLYPH (cmp, i);
2145 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2147 face = FACE_FROM_ID (it->f, face_id);
2148 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2149 it->multibyte_p);
2150 font = face->font;
2151 if (font == NULL)
2153 font = FRAME_FONT (it->f);
2154 boff = it->f->output_data.x->baseline_offset;
2155 font_info = NULL;
2157 else
2159 font_info
2160 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2161 boff = font_info->baseline_offset;
2162 if (font_info->vertical_centering)
2163 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2166 if (font_info
2167 && (pcm = x_per_char_metric (font, &char2b)))
2169 width = pcm->width;
2170 ascent = pcm->ascent;
2171 descent = pcm->descent;
2173 else
2175 width = FONT_WIDTH (font);
2176 ascent = 1;
2177 descent = 0;
2180 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2182 /* Relative composition with or without
2183 alternate chars. */
2184 left = (leftmost + rightmost - width) / 2;
2185 btm = - descent + boff;
2186 if (font_info && font_info->relative_compose
2187 && (! CHAR_TABLE_P (Vignore_relative_composition)
2188 || NILP (Faref (Vignore_relative_composition,
2189 make_number (ch)))))
2192 if (- descent >= font_info->relative_compose)
2193 /* One extra pixel between two glyphs. */
2194 btm = highest + 1;
2195 else if (ascent <= 0)
2196 /* One extra pixel between two glyphs. */
2197 btm = lowest - 1 - ascent - descent;
2200 else
2202 /* A composition rule is specified by an integer
2203 value that encodes global and new reference
2204 points (GREF and NREF). GREF and NREF are
2205 specified by numbers as below:
2207 0---1---2 -- ascent
2211 9--10--11 -- center
2213 ---3---4---5--- baseline
2215 6---7---8 -- descent
2217 int rule = COMPOSITION_RULE (cmp, i);
2218 int gref, nref, grefx, grefy, nrefx, nrefy;
2220 COMPOSITION_DECODE_RULE (rule, gref, nref);
2221 grefx = gref % 3, nrefx = nref % 3;
2222 grefy = gref / 3, nrefy = nref / 3;
2224 left = (leftmost
2225 + grefx * (rightmost - leftmost) / 2
2226 - nrefx * width / 2);
2227 btm = ((grefy == 0 ? highest
2228 : grefy == 1 ? 0
2229 : grefy == 2 ? lowest
2230 : (highest + lowest) / 2)
2231 - (nrefy == 0 ? ascent + descent
2232 : nrefy == 1 ? descent - boff
2233 : nrefy == 2 ? 0
2234 : (ascent + descent) / 2));
2237 cmp->offsets[i * 2] = left;
2238 cmp->offsets[i * 2 + 1] = btm + descent;
2240 /* Update the bounding box of the overall glyphs. */
2241 right = left + width;
2242 top = btm + descent + ascent;
2243 if (left < leftmost)
2244 leftmost = left;
2245 if (right > rightmost)
2246 rightmost = right;
2247 if (top > highest)
2248 highest = top;
2249 if (btm < lowest)
2250 lowest = btm;
2253 /* If there are glyphs whose x-offsets are negative,
2254 shift all glyphs to the right and make all x-offsets
2255 non-negative. */
2256 if (leftmost < 0)
2258 for (i = 0; i < cmp->glyph_len; i++)
2259 cmp->offsets[i * 2] -= leftmost;
2260 rightmost -= leftmost;
2263 cmp->pixel_width = rightmost;
2264 cmp->ascent = highest;
2265 cmp->descent = - lowest;
2266 if (cmp->ascent < font_ascent)
2267 cmp->ascent = font_ascent;
2268 if (cmp->descent < font_descent)
2269 cmp->descent = font_descent;
2272 it->pixel_width = cmp->pixel_width;
2273 it->ascent = it->phys_ascent = cmp->ascent;
2274 it->descent = it->phys_descent = cmp->descent;
2276 if (face->box != FACE_NO_BOX)
2278 int thick = face->box_line_width;
2280 if (thick > 0)
2282 it->ascent += thick;
2283 it->descent += thick;
2285 else
2286 thick = - thick;
2288 if (it->start_of_box_run_p)
2289 it->pixel_width += thick;
2290 if (it->end_of_box_run_p)
2291 it->pixel_width += thick;
2294 /* If face has an overline, add the height of the overline
2295 (1 pixel) and a 1 pixel margin to the character height. */
2296 if (face->overline_p)
2297 it->ascent += 2;
2299 take_vertical_position_into_account (it);
2301 if (it->glyph_row)
2302 x_append_composite_glyph (it);
2304 else if (it->what == IT_IMAGE)
2305 x_produce_image_glyph (it);
2306 else if (it->what == IT_STRETCH)
2307 x_produce_stretch_glyph (it);
2309 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2310 because this isn't true for images with `:ascent 100'. */
2311 xassert (it->ascent >= 0 && it->descent >= 0);
2312 if (it->area == TEXT_AREA)
2313 it->current_x += it->pixel_width;
2315 it->descent += it->extra_line_spacing;
2317 it->max_ascent = max (it->max_ascent, it->ascent);
2318 it->max_descent = max (it->max_descent, it->descent);
2319 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2320 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2324 /* Estimate the pixel height of the mode or top line on frame F.
2325 FACE_ID specifies what line's height to estimate. */
2328 x_estimate_mode_line_height (f, face_id)
2329 struct frame *f;
2330 enum face_id face_id;
2332 int height = FONT_HEIGHT (FRAME_FONT (f));
2334 /* This function is called so early when Emacs starts that the face
2335 cache and mode line face are not yet initialized. */
2336 if (FRAME_FACE_CACHE (f))
2338 struct face *face = FACE_FROM_ID (f, face_id);
2339 if (face)
2341 if (face->font)
2342 height = FONT_HEIGHT (face->font);
2343 if (face->box_line_width > 0)
2344 height += 2 * face->box_line_width;
2348 return height;
2352 /***********************************************************************
2353 Glyph display
2354 ***********************************************************************/
2356 /* A sequence of glyphs to be drawn in the same face.
2358 This data structure is not really completely X specific, so it
2359 could possibly, at least partially, be useful for other systems. It
2360 is currently not part of the external redisplay interface because
2361 it's not clear what other systems will need. */
2363 struct glyph_string
2365 /* X-origin of the string. */
2366 int x;
2368 /* Y-origin and y-position of the base line of this string. */
2369 int y, ybase;
2371 /* The width of the string, not including a face extension. */
2372 int width;
2374 /* The width of the string, including a face extension. */
2375 int background_width;
2377 /* The height of this string. This is the height of the line this
2378 string is drawn in, and can be different from the height of the
2379 font the string is drawn in. */
2380 int height;
2382 /* Number of pixels this string overwrites in front of its x-origin.
2383 This number is zero if the string has an lbearing >= 0; it is
2384 -lbearing, if the string has an lbearing < 0. */
2385 int left_overhang;
2387 /* Number of pixels this string overwrites past its right-most
2388 nominal x-position, i.e. x + width. Zero if the string's
2389 rbearing is <= its nominal width, rbearing - width otherwise. */
2390 int right_overhang;
2392 /* The frame on which the glyph string is drawn. */
2393 struct frame *f;
2395 /* The window on which the glyph string is drawn. */
2396 struct window *w;
2398 /* X display and window for convenience. */
2399 Display *display;
2400 Window window;
2402 /* The glyph row for which this string was built. It determines the
2403 y-origin and height of the string. */
2404 struct glyph_row *row;
2406 /* The area within row. */
2407 enum glyph_row_area area;
2409 /* Characters to be drawn, and number of characters. */
2410 XChar2b *char2b;
2411 int nchars;
2413 /* A face-override for drawing cursors, mouse face and similar. */
2414 enum draw_glyphs_face hl;
2416 /* Face in which this string is to be drawn. */
2417 struct face *face;
2419 /* Font in which this string is to be drawn. */
2420 XFontStruct *font;
2422 /* Font info for this string. */
2423 struct font_info *font_info;
2425 /* Non-null means this string describes (part of) a composition.
2426 All characters from char2b are drawn composed. */
2427 struct composition *cmp;
2429 /* Index of this glyph string's first character in the glyph
2430 definition of CMP. If this is zero, this glyph string describes
2431 the first character of a composition. */
2432 int gidx;
2434 /* 1 means this glyph strings face has to be drawn to the right end
2435 of the window's drawing area. */
2436 unsigned extends_to_end_of_line_p : 1;
2438 /* 1 means the background of this string has been drawn. */
2439 unsigned background_filled_p : 1;
2441 /* 1 means glyph string must be drawn with 16-bit functions. */
2442 unsigned two_byte_p : 1;
2444 /* 1 means that the original font determined for drawing this glyph
2445 string could not be loaded. The member `font' has been set to
2446 the frame's default font in this case. */
2447 unsigned font_not_found_p : 1;
2449 /* 1 means that the face in which this glyph string is drawn has a
2450 stipple pattern. */
2451 unsigned stippled_p : 1;
2453 /* 1 means only the foreground of this glyph string must be drawn,
2454 and we should use the physical height of the line this glyph
2455 string appears in as clip rect. */
2456 unsigned for_overlaps_p : 1;
2458 /* The GC to use for drawing this glyph string. */
2459 GC gc;
2461 /* A pointer to the first glyph in the string. This glyph
2462 corresponds to char2b[0]. Needed to draw rectangles if
2463 font_not_found_p is 1. */
2464 struct glyph *first_glyph;
2466 /* Image, if any. */
2467 struct image *img;
2469 struct glyph_string *next, *prev;
2473 #if GLYPH_DEBUG
2475 static void
2476 x_dump_glyph_string (s)
2477 struct glyph_string *s;
2479 fprintf (stderr, "glyph string\n");
2480 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2481 s->x, s->y, s->width, s->height);
2482 fprintf (stderr, " ybase = %d\n", s->ybase);
2483 fprintf (stderr, " hl = %d\n", s->hl);
2484 fprintf (stderr, " left overhang = %d, right = %d\n",
2485 s->left_overhang, s->right_overhang);
2486 fprintf (stderr, " nchars = %d\n", s->nchars);
2487 fprintf (stderr, " extends to end of line = %d\n",
2488 s->extends_to_end_of_line_p);
2489 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2490 fprintf (stderr, " bg width = %d\n", s->background_width);
2493 #endif /* GLYPH_DEBUG */
2497 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2498 struct glyph_string **,
2499 struct glyph_string *,
2500 struct glyph_string *));
2501 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2502 struct glyph_string **,
2503 struct glyph_string *,
2504 struct glyph_string *));
2505 static void x_append_glyph_string P_ ((struct glyph_string **,
2506 struct glyph_string **,
2507 struct glyph_string *));
2508 static int x_left_overwritten P_ ((struct glyph_string *));
2509 static int x_left_overwriting P_ ((struct glyph_string *));
2510 static int x_right_overwritten P_ ((struct glyph_string *));
2511 static int x_right_overwriting P_ ((struct glyph_string *));
2512 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2513 int));
2514 static void x_init_glyph_string P_ ((struct glyph_string *,
2515 XChar2b *, struct window *,
2516 struct glyph_row *,
2517 enum glyph_row_area, int,
2518 enum draw_glyphs_face));
2519 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2520 enum glyph_row_area, int, int,
2521 enum draw_glyphs_face, int));
2522 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2523 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2524 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2525 int));
2526 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2527 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2528 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2529 static void x_draw_glyph_string P_ ((struct glyph_string *));
2530 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2531 static void x_set_cursor_gc P_ ((struct glyph_string *));
2532 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2533 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2534 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2535 int *, int *));
2536 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2537 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2538 unsigned long *, double, int));
2539 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2540 double, int, unsigned long));
2541 static void x_setup_relief_colors P_ ((struct glyph_string *));
2542 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2543 static void x_draw_image_relief P_ ((struct glyph_string *));
2544 static void x_draw_image_foreground P_ ((struct glyph_string *));
2545 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2546 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2547 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2548 int, int, int));
2549 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2550 int, int, int, int, XRectangle *));
2551 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2552 int, int, int, XRectangle *));
2553 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2554 enum glyph_row_area));
2555 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2556 struct glyph_row *,
2557 enum glyph_row_area, int, int));
2559 #if GLYPH_DEBUG
2560 static void x_check_font P_ ((struct frame *, XFontStruct *));
2561 #endif
2564 /* Append the list of glyph strings with head H and tail T to the list
2565 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2567 static INLINE void
2568 x_append_glyph_string_lists (head, tail, h, t)
2569 struct glyph_string **head, **tail;
2570 struct glyph_string *h, *t;
2572 if (h)
2574 if (*head)
2575 (*tail)->next = h;
2576 else
2577 *head = h;
2578 h->prev = *tail;
2579 *tail = t;
2584 /* Prepend the list of glyph strings with head H and tail T to the
2585 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2586 result. */
2588 static INLINE void
2589 x_prepend_glyph_string_lists (head, tail, h, t)
2590 struct glyph_string **head, **tail;
2591 struct glyph_string *h, *t;
2593 if (h)
2595 if (*head)
2596 (*head)->prev = t;
2597 else
2598 *tail = t;
2599 t->next = *head;
2600 *head = h;
2605 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2606 Set *HEAD and *TAIL to the resulting list. */
2608 static INLINE void
2609 x_append_glyph_string (head, tail, s)
2610 struct glyph_string **head, **tail;
2611 struct glyph_string *s;
2613 s->next = s->prev = NULL;
2614 x_append_glyph_string_lists (head, tail, s, s);
2618 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2619 face. */
2621 static void
2622 x_set_cursor_gc (s)
2623 struct glyph_string *s;
2625 if (s->font == FRAME_FONT (s->f)
2626 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2627 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2628 && !s->cmp)
2629 s->gc = s->f->output_data.x->cursor_gc;
2630 else
2632 /* Cursor on non-default face: must merge. */
2633 XGCValues xgcv;
2634 unsigned long mask;
2636 xgcv.background = s->f->output_data.x->cursor_pixel;
2637 xgcv.foreground = s->face->background;
2639 /* If the glyph would be invisible, try a different foreground. */
2640 if (xgcv.foreground == xgcv.background)
2641 xgcv.foreground = s->face->foreground;
2642 if (xgcv.foreground == xgcv.background)
2643 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2644 if (xgcv.foreground == xgcv.background)
2645 xgcv.foreground = s->face->foreground;
2647 /* Make sure the cursor is distinct from text in this face. */
2648 if (xgcv.background == s->face->background
2649 && xgcv.foreground == s->face->foreground)
2651 xgcv.background = s->face->foreground;
2652 xgcv.foreground = s->face->background;
2655 IF_DEBUG (x_check_font (s->f, s->font));
2656 xgcv.font = s->font->fid;
2657 xgcv.graphics_exposures = False;
2658 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2660 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2661 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2662 mask, &xgcv);
2663 else
2664 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2665 = XCreateGC (s->display, s->window, mask, &xgcv);
2667 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2672 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2674 static void
2675 x_set_mouse_face_gc (s)
2676 struct glyph_string *s;
2678 int face_id;
2679 struct face *face;
2681 /* What face has to be used last for the mouse face? */
2682 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2683 face = FACE_FROM_ID (s->f, face_id);
2684 if (face == NULL)
2685 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2687 if (s->first_glyph->type == CHAR_GLYPH)
2688 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2689 else
2690 face_id = FACE_FOR_CHAR (s->f, face, 0);
2691 s->face = FACE_FROM_ID (s->f, face_id);
2692 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2694 /* If font in this face is same as S->font, use it. */
2695 if (s->font == s->face->font)
2696 s->gc = s->face->gc;
2697 else
2699 /* Otherwise construct scratch_cursor_gc with values from FACE
2700 but font FONT. */
2701 XGCValues xgcv;
2702 unsigned long mask;
2704 xgcv.background = s->face->background;
2705 xgcv.foreground = s->face->foreground;
2706 IF_DEBUG (x_check_font (s->f, s->font));
2707 xgcv.font = s->font->fid;
2708 xgcv.graphics_exposures = False;
2709 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2711 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2712 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2713 mask, &xgcv);
2714 else
2715 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2716 = XCreateGC (s->display, s->window, mask, &xgcv);
2718 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2721 xassert (s->gc != 0);
2725 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2726 Faces to use in the mode line have already been computed when the
2727 matrix was built, so there isn't much to do, here. */
2729 static INLINE void
2730 x_set_mode_line_face_gc (s)
2731 struct glyph_string *s;
2733 s->gc = s->face->gc;
2737 /* Set S->gc of glyph string S for drawing that glyph string. Set
2738 S->stippled_p to a non-zero value if the face of S has a stipple
2739 pattern. */
2741 static INLINE void
2742 x_set_glyph_string_gc (s)
2743 struct glyph_string *s;
2745 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2747 if (s->hl == DRAW_NORMAL_TEXT)
2749 s->gc = s->face->gc;
2750 s->stippled_p = s->face->stipple != 0;
2752 else if (s->hl == DRAW_INVERSE_VIDEO)
2754 x_set_mode_line_face_gc (s);
2755 s->stippled_p = s->face->stipple != 0;
2757 else if (s->hl == DRAW_CURSOR)
2759 x_set_cursor_gc (s);
2760 s->stippled_p = 0;
2762 else if (s->hl == DRAW_MOUSE_FACE)
2764 x_set_mouse_face_gc (s);
2765 s->stippled_p = s->face->stipple != 0;
2767 else if (s->hl == DRAW_IMAGE_RAISED
2768 || s->hl == DRAW_IMAGE_SUNKEN)
2770 s->gc = s->face->gc;
2771 s->stippled_p = s->face->stipple != 0;
2773 else
2775 s->gc = s->face->gc;
2776 s->stippled_p = s->face->stipple != 0;
2779 /* GC must have been set. */
2780 xassert (s->gc != 0);
2784 /* Return in *R the clipping rectangle for glyph string S. */
2786 static void
2787 x_get_glyph_string_clip_rect (s, r)
2788 struct glyph_string *s;
2789 XRectangle *r;
2791 if (s->row->full_width_p)
2793 /* Draw full-width. X coordinates are relative to S->w->left. */
2794 int canon_x = CANON_X_UNIT (s->f);
2796 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2797 r->width = XFASTINT (s->w->width) * canon_x;
2799 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2801 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2802 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2803 r->x -= width;
2806 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2808 /* Unless displaying a mode or menu bar line, which are always
2809 fully visible, clip to the visible part of the row. */
2810 if (s->w->pseudo_window_p)
2811 r->height = s->row->visible_height;
2812 else
2813 r->height = s->height;
2815 else
2817 /* This is a text line that may be partially visible. */
2818 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2819 r->width = window_box_width (s->w, s->area);
2820 r->height = s->row->visible_height;
2823 /* If S draws overlapping rows, it's sufficient to use the top and
2824 bottom of the window for clipping because this glyph string
2825 intentionally draws over other lines. */
2826 if (s->for_overlaps_p)
2828 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2829 r->height = window_text_bottom_y (s->w) - r->y;
2831 else
2833 /* Don't use S->y for clipping because it doesn't take partially
2834 visible lines into account. For example, it can be negative for
2835 partially visible lines at the top of a window. */
2836 if (!s->row->full_width_p
2837 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2838 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2839 else
2840 r->y = max (0, s->row->y);
2842 /* If drawing a tool-bar window, draw it over the internal border
2843 at the top of the window. */
2844 if (s->w == XWINDOW (s->f->tool_bar_window))
2845 r->y -= s->f->output_data.x->internal_border_width;
2848 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2852 /* Set clipping for output of glyph string S. S may be part of a mode
2853 line or menu if we don't have X toolkit support. */
2855 static INLINE void
2856 x_set_glyph_string_clipping (s)
2857 struct glyph_string *s;
2859 XRectangle r;
2860 x_get_glyph_string_clip_rect (s, &r);
2861 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2865 /* Compute left and right overhang of glyph string S. If S is a glyph
2866 string for a composition, assume overhangs don't exist. */
2868 static INLINE void
2869 x_compute_glyph_string_overhangs (s)
2870 struct glyph_string *s;
2872 if (s->cmp == NULL
2873 && s->first_glyph->type == CHAR_GLYPH)
2875 XCharStruct cs;
2876 int direction, font_ascent, font_descent;
2877 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2878 &font_ascent, &font_descent, &cs);
2879 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2880 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2885 /* Compute overhangs and x-positions for glyph string S and its
2886 predecessors, or successors. X is the starting x-position for S.
2887 BACKWARD_P non-zero means process predecessors. */
2889 static void
2890 x_compute_overhangs_and_x (s, x, backward_p)
2891 struct glyph_string *s;
2892 int x;
2893 int backward_p;
2895 if (backward_p)
2897 while (s)
2899 x_compute_glyph_string_overhangs (s);
2900 x -= s->width;
2901 s->x = x;
2902 s = s->prev;
2905 else
2907 while (s)
2909 x_compute_glyph_string_overhangs (s);
2910 s->x = x;
2911 x += s->width;
2912 s = s->next;
2918 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2919 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2920 assumed to be zero. */
2922 static void
2923 x_get_glyph_overhangs (glyph, f, left, right)
2924 struct glyph *glyph;
2925 struct frame *f;
2926 int *left, *right;
2928 *left = *right = 0;
2930 if (glyph->type == CHAR_GLYPH)
2932 XFontStruct *font;
2933 struct face *face;
2934 struct font_info *font_info;
2935 XChar2b char2b;
2936 XCharStruct *pcm;
2938 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2939 font = face->font;
2940 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2941 if (font
2942 && (pcm = x_per_char_metric (font, &char2b)))
2944 if (pcm->rbearing > pcm->width)
2945 *right = pcm->rbearing - pcm->width;
2946 if (pcm->lbearing < 0)
2947 *left = -pcm->lbearing;
2953 /* Return the index of the first glyph preceding glyph string S that
2954 is overwritten by S because of S's left overhang. Value is -1
2955 if no glyphs are overwritten. */
2957 static int
2958 x_left_overwritten (s)
2959 struct glyph_string *s;
2961 int k;
2963 if (s->left_overhang)
2965 int x = 0, i;
2966 struct glyph *glyphs = s->row->glyphs[s->area];
2967 int first = s->first_glyph - glyphs;
2969 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2970 x -= glyphs[i].pixel_width;
2972 k = i + 1;
2974 else
2975 k = -1;
2977 return k;
2981 /* Return the index of the first glyph preceding glyph string S that
2982 is overwriting S because of its right overhang. Value is -1 if no
2983 glyph in front of S overwrites S. */
2985 static int
2986 x_left_overwriting (s)
2987 struct glyph_string *s;
2989 int i, k, x;
2990 struct glyph *glyphs = s->row->glyphs[s->area];
2991 int first = s->first_glyph - glyphs;
2993 k = -1;
2994 x = 0;
2995 for (i = first - 1; i >= 0; --i)
2997 int left, right;
2998 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2999 if (x + right > 0)
3000 k = i;
3001 x -= glyphs[i].pixel_width;
3004 return k;
3008 /* Return the index of the last glyph following glyph string S that is
3009 not overwritten by S because of S's right overhang. Value is -1 if
3010 no such glyph is found. */
3012 static int
3013 x_right_overwritten (s)
3014 struct glyph_string *s;
3016 int k = -1;
3018 if (s->right_overhang)
3020 int x = 0, i;
3021 struct glyph *glyphs = s->row->glyphs[s->area];
3022 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3023 int end = s->row->used[s->area];
3025 for (i = first; i < end && s->right_overhang > x; ++i)
3026 x += glyphs[i].pixel_width;
3028 k = i;
3031 return k;
3035 /* Return the index of the last glyph following glyph string S that
3036 overwrites S because of its left overhang. Value is negative
3037 if no such glyph is found. */
3039 static int
3040 x_right_overwriting (s)
3041 struct glyph_string *s;
3043 int i, k, x;
3044 int end = s->row->used[s->area];
3045 struct glyph *glyphs = s->row->glyphs[s->area];
3046 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3048 k = -1;
3049 x = 0;
3050 for (i = first; i < end; ++i)
3052 int left, right;
3053 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3054 if (x - left < 0)
3055 k = i;
3056 x += glyphs[i].pixel_width;
3059 return k;
3063 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3065 static INLINE void
3066 x_clear_glyph_string_rect (s, x, y, w, h)
3067 struct glyph_string *s;
3068 int x, y, w, h;
3070 XGCValues xgcv;
3071 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3072 XSetForeground (s->display, s->gc, xgcv.background);
3073 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3074 XSetForeground (s->display, s->gc, xgcv.foreground);
3078 /* Draw the background of glyph_string S. If S->background_filled_p
3079 is non-zero don't draw it. FORCE_P non-zero means draw the
3080 background even if it wouldn't be drawn normally. This is used
3081 when a string preceding S draws into the background of S, or S
3082 contains the first component of a composition. */
3084 static void
3085 x_draw_glyph_string_background (s, force_p)
3086 struct glyph_string *s;
3087 int force_p;
3089 /* Nothing to do if background has already been drawn or if it
3090 shouldn't be drawn in the first place. */
3091 if (!s->background_filled_p)
3093 int box_line_width = max (s->face->box_line_width, 0);
3095 if (s->stippled_p)
3097 /* Fill background with a stipple pattern. */
3098 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3099 XFillRectangle (s->display, s->window, s->gc, s->x,
3100 s->y + box_line_width,
3101 s->background_width,
3102 s->height - 2 * box_line_width);
3103 XSetFillStyle (s->display, s->gc, FillSolid);
3104 s->background_filled_p = 1;
3106 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3107 || s->font_not_found_p
3108 || s->extends_to_end_of_line_p
3109 || force_p)
3111 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3112 s->background_width,
3113 s->height - 2 * box_line_width);
3114 s->background_filled_p = 1;
3120 /* Draw the foreground of glyph string S. */
3122 static void
3123 x_draw_glyph_string_foreground (s)
3124 struct glyph_string *s;
3126 int i, x;
3128 /* If first glyph of S has a left box line, start drawing the text
3129 of S to the right of that box line. */
3130 if (s->face->box != FACE_NO_BOX
3131 && s->first_glyph->left_box_line_p)
3132 x = s->x + abs (s->face->box_line_width);
3133 else
3134 x = s->x;
3136 /* Draw characters of S as rectangles if S's font could not be
3137 loaded. */
3138 if (s->font_not_found_p)
3140 for (i = 0; i < s->nchars; ++i)
3142 struct glyph *g = s->first_glyph + i;
3143 XDrawRectangle (s->display, s->window,
3144 s->gc, x, s->y, g->pixel_width - 1,
3145 s->height - 1);
3146 x += g->pixel_width;
3149 else
3151 char *char1b = (char *) s->char2b;
3152 int boff = s->font_info->baseline_offset;
3154 if (s->font_info->vertical_centering)
3155 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3157 /* If we can use 8-bit functions, condense S->char2b. */
3158 if (!s->two_byte_p)
3159 for (i = 0; i < s->nchars; ++i)
3160 char1b[i] = s->char2b[i].byte2;
3162 /* Draw text with XDrawString if background has already been
3163 filled. Otherwise, use XDrawImageString. (Note that
3164 XDrawImageString is usually faster than XDrawString.) Always
3165 use XDrawImageString when drawing the cursor so that there is
3166 no chance that characters under a box cursor are invisible. */
3167 if (s->for_overlaps_p
3168 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3170 /* Draw characters with 16-bit or 8-bit functions. */
3171 if (s->two_byte_p)
3172 XDrawString16 (s->display, s->window, s->gc, x,
3173 s->ybase - boff, s->char2b, s->nchars);
3174 else
3175 XDrawString (s->display, s->window, s->gc, x,
3176 s->ybase - boff, char1b, s->nchars);
3178 else
3180 if (s->two_byte_p)
3181 XDrawImageString16 (s->display, s->window, s->gc, x,
3182 s->ybase - boff, s->char2b, s->nchars);
3183 else
3184 XDrawImageString (s->display, s->window, s->gc, x,
3185 s->ybase - boff, char1b, s->nchars);
3190 /* Draw the foreground of composite glyph string S. */
3192 static void
3193 x_draw_composite_glyph_string_foreground (s)
3194 struct glyph_string *s;
3196 int i, x;
3198 /* If first glyph of S has a left box line, start drawing the text
3199 of S to the right of that box line. */
3200 if (s->face->box != FACE_NO_BOX
3201 && s->first_glyph->left_box_line_p)
3202 x = s->x + abs (s->face->box_line_width);
3203 else
3204 x = s->x;
3206 /* S is a glyph string for a composition. S->gidx is the index of
3207 the first character drawn for glyphs of this composition.
3208 S->gidx == 0 means we are drawing the very first character of
3209 this composition. */
3211 /* Draw a rectangle for the composition if the font for the very
3212 first character of the composition could not be loaded. */
3213 if (s->font_not_found_p)
3215 if (s->gidx == 0)
3216 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3217 s->width - 1, s->height - 1);
3219 else
3221 for (i = 0; i < s->nchars; i++, ++s->gidx)
3222 XDrawString16 (s->display, s->window, s->gc,
3223 x + s->cmp->offsets[s->gidx * 2],
3224 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3225 s->char2b + i, 1);
3230 #ifdef USE_X_TOOLKIT
3232 static struct frame *x_frame_of_widget P_ ((Widget));
3233 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3234 XrmValue *, XrmValue *, XtPointer *));
3235 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3236 XrmValue *, Cardinal *));
3239 /* Return the frame on which widget WIDGET is used.. Abort if frame
3240 cannot be determined. */
3242 static struct frame *
3243 x_frame_of_widget (widget)
3244 Widget widget;
3246 struct x_display_info *dpyinfo;
3247 Lisp_Object tail;
3248 struct frame *f;
3250 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3252 /* Find the top-level shell of the widget. Note that this function
3253 can be called when the widget is not yet realized, so XtWindow
3254 (widget) == 0. That's the reason we can't simply use
3255 x_any_window_to_frame. */
3256 while (!XtIsTopLevelShell (widget))
3257 widget = XtParent (widget);
3259 /* Look for a frame with that top-level widget. Allocate the color
3260 on that frame to get the right gamma correction value. */
3261 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3262 if (GC_FRAMEP (XCAR (tail))
3263 && (f = XFRAME (XCAR (tail)),
3264 (f->output_data.nothing != 1
3265 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3266 && f->output_data.x->widget == widget)
3267 return f;
3269 abort ();
3273 /* Allocate the color COLOR->pixel on the screen and display of
3274 widget WIDGET in colormap CMAP. If an exact match cannot be
3275 allocated, try the nearest color available. Value is non-zero
3276 if successful. This is called from lwlib. */
3279 x_alloc_nearest_color_for_widget (widget, cmap, color)
3280 Widget widget;
3281 Colormap cmap;
3282 XColor *color;
3284 struct frame *f = x_frame_of_widget (widget);
3285 return x_alloc_nearest_color (f, cmap, color);
3289 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3290 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3291 If this produces the same color as PIXEL, try a color where all RGB
3292 values have DELTA added. Return the allocated color in *PIXEL.
3293 DISPLAY is the X display, CMAP is the colormap to operate on.
3294 Value is non-zero if successful. */
3297 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3298 Widget widget;
3299 Display *display;
3300 Colormap cmap;
3301 unsigned long *pixel;
3302 double factor;
3303 int delta;
3305 struct frame *f = x_frame_of_widget (widget);
3306 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3310 /* Structure specifying which arguments should be passed by Xt to
3311 cvt_string_to_pixel. We want the widget's screen and colormap. */
3313 static XtConvertArgRec cvt_string_to_pixel_args[] =
3315 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3316 sizeof (Screen *)},
3317 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3318 sizeof (Colormap)}
3322 /* The address of this variable is returned by
3323 cvt_string_to_pixel. */
3325 static Pixel cvt_string_to_pixel_value;
3328 /* Convert a color name to a pixel color.
3330 DPY is the display we are working on.
3332 ARGS is an array of *NARGS XrmValue structures holding additional
3333 information about the widget for which the conversion takes place.
3334 The contents of this array are determined by the specification
3335 in cvt_string_to_pixel_args.
3337 FROM is a pointer to an XrmValue which points to the color name to
3338 convert. TO is an XrmValue in which to return the pixel color.
3340 CLOSURE_RET is a pointer to user-data, in which we record if
3341 we allocated the color or not.
3343 Value is True if successful, False otherwise. */
3345 static Boolean
3346 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3347 Display *dpy;
3348 XrmValue *args;
3349 Cardinal *nargs;
3350 XrmValue *from, *to;
3351 XtPointer *closure_ret;
3353 Screen *screen;
3354 Colormap cmap;
3355 Pixel pixel;
3356 String color_name;
3357 XColor color;
3359 if (*nargs != 2)
3361 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3362 "wrongParameters", "cvt_string_to_pixel",
3363 "XtToolkitError",
3364 "Screen and colormap args required", NULL, NULL);
3365 return False;
3368 screen = *(Screen **) args[0].addr;
3369 cmap = *(Colormap *) args[1].addr;
3370 color_name = (String) from->addr;
3372 if (strcmp (color_name, XtDefaultBackground) == 0)
3374 *closure_ret = (XtPointer) False;
3375 pixel = WhitePixelOfScreen (screen);
3377 else if (strcmp (color_name, XtDefaultForeground) == 0)
3379 *closure_ret = (XtPointer) False;
3380 pixel = BlackPixelOfScreen (screen);
3382 else if (XParseColor (dpy, cmap, color_name, &color)
3383 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3385 pixel = color.pixel;
3386 *closure_ret = (XtPointer) True;
3388 else
3390 String params[1];
3391 Cardinal nparams = 1;
3393 params[0] = color_name;
3394 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3395 "badValue", "cvt_string_to_pixel",
3396 "XtToolkitError", "Invalid color `%s'",
3397 params, &nparams);
3398 return False;
3401 if (to->addr != NULL)
3403 if (to->size < sizeof (Pixel))
3405 to->size = sizeof (Pixel);
3406 return False;
3409 *(Pixel *) to->addr = pixel;
3411 else
3413 cvt_string_to_pixel_value = pixel;
3414 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3417 to->size = sizeof (Pixel);
3418 return True;
3422 /* Free a pixel color which was previously allocated via
3423 cvt_string_to_pixel. This is registered as the destructor
3424 for this type of resource via XtSetTypeConverter.
3426 APP is the application context in which we work.
3428 TO is a pointer to an XrmValue holding the color to free.
3429 CLOSURE is the value we stored in CLOSURE_RET for this color
3430 in cvt_string_to_pixel.
3432 ARGS and NARGS are like for cvt_string_to_pixel. */
3434 static void
3435 cvt_pixel_dtor (app, to, closure, args, nargs)
3436 XtAppContext app;
3437 XrmValuePtr to;
3438 XtPointer closure;
3439 XrmValuePtr args;
3440 Cardinal *nargs;
3442 if (*nargs != 2)
3444 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3445 "XtToolkitError",
3446 "Screen and colormap arguments required",
3447 NULL, NULL);
3449 else if (closure != NULL)
3451 /* We did allocate the pixel, so free it. */
3452 Screen *screen = *(Screen **) args[0].addr;
3453 Colormap cmap = *(Colormap *) args[1].addr;
3454 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3455 (Pixel *) to->addr, 1);
3460 #endif /* USE_X_TOOLKIT */
3463 /* Value is an array of XColor structures for the contents of the
3464 color map of display DPY. Set *NCELLS to the size of the array.
3465 Note that this probably shouldn't be called for large color maps,
3466 say a 24-bit TrueColor map. */
3468 static const XColor *
3469 x_color_cells (dpy, ncells)
3470 Display *dpy;
3471 int *ncells;
3473 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3475 if (dpyinfo->color_cells == NULL)
3477 Screen *screen = dpyinfo->screen;
3478 int i;
3480 dpyinfo->ncolor_cells
3481 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3482 dpyinfo->color_cells
3483 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3484 * sizeof *dpyinfo->color_cells);
3486 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3487 dpyinfo->color_cells[i].pixel = i;
3489 XQueryColors (dpy, dpyinfo->cmap,
3490 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3493 *ncells = dpyinfo->ncolor_cells;
3494 return dpyinfo->color_cells;
3498 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3499 colors in COLORS. Use cached information, if available. */
3501 void
3502 x_query_colors (f, colors, ncolors)
3503 struct frame *f;
3504 XColor *colors;
3505 int ncolors;
3507 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3509 if (dpyinfo->color_cells)
3511 int i;
3512 for (i = 0; i < ncolors; ++i)
3514 unsigned long pixel = colors[i].pixel;
3515 xassert (pixel < dpyinfo->ncolor_cells);
3516 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3517 colors[i] = dpyinfo->color_cells[pixel];
3520 else
3521 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3525 /* On frame F, translate pixel color to RGB values for the color in
3526 COLOR. Use cached information, if available. */
3528 void
3529 x_query_color (f, color)
3530 struct frame *f;
3531 XColor *color;
3533 x_query_colors (f, color, 1);
3537 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3538 exact match can't be allocated, try the nearest color available.
3539 Value is non-zero if successful. Set *COLOR to the color
3540 allocated. */
3542 static int
3543 x_alloc_nearest_color_1 (dpy, cmap, color)
3544 Display *dpy;
3545 Colormap cmap;
3546 XColor *color;
3548 int rc;
3550 rc = XAllocColor (dpy, cmap, color);
3551 if (rc == 0)
3553 /* If we got to this point, the colormap is full, so we're going
3554 to try to get the next closest color. The algorithm used is
3555 a least-squares matching, which is what X uses for closest
3556 color matching with StaticColor visuals. */
3557 int nearest, i;
3558 unsigned long nearest_delta = ~0;
3559 int ncells;
3560 const XColor *cells = x_color_cells (dpy, &ncells);
3562 for (nearest = i = 0; i < ncells; ++i)
3564 long dred = (color->red >> 8) - (cells[i].red >> 8);
3565 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3566 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3567 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3569 if (delta < nearest_delta)
3571 nearest = i;
3572 nearest_delta = delta;
3576 color->red = cells[nearest].red;
3577 color->green = cells[nearest].green;
3578 color->blue = cells[nearest].blue;
3579 rc = XAllocColor (dpy, cmap, color);
3581 else
3583 /* If allocation succeeded, and the allocated pixel color is not
3584 equal to a cached pixel color recorded earlier, there was a
3585 change in the colormap, so clear the color cache. */
3586 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3587 XColor *cached_color;
3589 if (dpyinfo->color_cells
3590 && (cached_color = &dpyinfo->color_cells[color->pixel],
3591 (cached_color->red != color->red
3592 || cached_color->blue != color->blue
3593 || cached_color->green != color->green)))
3595 xfree (dpyinfo->color_cells);
3596 dpyinfo->color_cells = NULL;
3597 dpyinfo->ncolor_cells = 0;
3601 #ifdef DEBUG_X_COLORS
3602 if (rc)
3603 register_color (color->pixel);
3604 #endif /* DEBUG_X_COLORS */
3606 return rc;
3610 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3611 exact match can't be allocated, try the nearest color available.
3612 Value is non-zero if successful. Set *COLOR to the color
3613 allocated. */
3616 x_alloc_nearest_color (f, cmap, color)
3617 struct frame *f;
3618 Colormap cmap;
3619 XColor *color;
3621 gamma_correct (f, color);
3622 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3626 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3627 It's necessary to do this instead of just using PIXEL directly to
3628 get color reference counts right. */
3630 unsigned long
3631 x_copy_color (f, pixel)
3632 struct frame *f;
3633 unsigned long pixel;
3635 XColor color;
3637 color.pixel = pixel;
3638 BLOCK_INPUT;
3639 x_query_color (f, &color);
3640 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3641 UNBLOCK_INPUT;
3642 #ifdef DEBUG_X_COLORS
3643 register_color (pixel);
3644 #endif
3645 return color.pixel;
3649 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3650 It's necessary to do this instead of just using PIXEL directly to
3651 get color reference counts right. */
3653 unsigned long
3654 x_copy_dpy_color (dpy, cmap, pixel)
3655 Display *dpy;
3656 Colormap cmap;
3657 unsigned long pixel;
3659 XColor color;
3661 color.pixel = pixel;
3662 BLOCK_INPUT;
3663 XQueryColor (dpy, cmap, &color);
3664 XAllocColor (dpy, cmap, &color);
3665 UNBLOCK_INPUT;
3666 #ifdef DEBUG_X_COLORS
3667 register_color (pixel);
3668 #endif
3669 return color.pixel;
3673 /* Brightness beyond which a color won't have its highlight brightness
3674 boosted.
3676 Nominally, highlight colors for `3d' faces are calculated by
3677 brightening an object's color by a constant scale factor, but this
3678 doesn't yield good results for dark colors, so for colors who's
3679 brightness is less than this value (on a scale of 0-65535) have an
3680 use an additional additive factor.
3682 The value here is set so that the default menu-bar/mode-line color
3683 (grey75) will not have its highlights changed at all. */
3684 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3687 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3688 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3689 If this produces the same color as PIXEL, try a color where all RGB
3690 values have DELTA added. Return the allocated color in *PIXEL.
3691 DISPLAY is the X display, CMAP is the colormap to operate on.
3692 Value is non-zero if successful. */
3694 static int
3695 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3696 struct frame *f;
3697 Display *display;
3698 Colormap cmap;
3699 unsigned long *pixel;
3700 double factor;
3701 int delta;
3703 XColor color, new;
3704 long bright;
3705 int success_p;
3707 /* Get RGB color values. */
3708 color.pixel = *pixel;
3709 x_query_color (f, &color);
3711 /* Change RGB values by specified FACTOR. Avoid overflow! */
3712 xassert (factor >= 0);
3713 new.red = min (0xffff, factor * color.red);
3714 new.green = min (0xffff, factor * color.green);
3715 new.blue = min (0xffff, factor * color.blue);
3717 /* Calculate brightness of COLOR. */
3718 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3720 /* We only boost colors that are darker than
3721 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3722 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3723 /* Make an additive adjustment to NEW, because it's dark enough so
3724 that scaling by FACTOR alone isn't enough. */
3726 /* How far below the limit this color is (0 - 1, 1 being darker). */
3727 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3728 /* The additive adjustment. */
3729 int min_delta = delta * dimness * factor / 2;
3731 if (factor < 1)
3733 new.red = max (0, new.red - min_delta);
3734 new.green = max (0, new.green - min_delta);
3735 new.blue = max (0, new.blue - min_delta);
3737 else
3739 new.red = min (0xffff, min_delta + new.red);
3740 new.green = min (0xffff, min_delta + new.green);
3741 new.blue = min (0xffff, min_delta + new.blue);
3745 /* Try to allocate the color. */
3746 success_p = x_alloc_nearest_color (f, cmap, &new);
3747 if (success_p)
3749 if (new.pixel == *pixel)
3751 /* If we end up with the same color as before, try adding
3752 delta to the RGB values. */
3753 x_free_colors (f, &new.pixel, 1);
3755 new.red = min (0xffff, delta + color.red);
3756 new.green = min (0xffff, delta + color.green);
3757 new.blue = min (0xffff, delta + color.blue);
3758 success_p = x_alloc_nearest_color (f, cmap, &new);
3760 else
3761 success_p = 1;
3762 *pixel = new.pixel;
3765 return success_p;
3769 /* Set up the foreground color for drawing relief lines of glyph
3770 string S. RELIEF is a pointer to a struct relief containing the GC
3771 with which lines will be drawn. Use a color that is FACTOR or
3772 DELTA lighter or darker than the relief's background which is found
3773 in S->f->output_data.x->relief_background. If such a color cannot
3774 be allocated, use DEFAULT_PIXEL, instead. */
3776 static void
3777 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3778 struct frame *f;
3779 struct relief *relief;
3780 double factor;
3781 int delta;
3782 unsigned long default_pixel;
3784 XGCValues xgcv;
3785 struct x_output *di = f->output_data.x;
3786 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3787 unsigned long pixel;
3788 unsigned long background = di->relief_background;
3789 Colormap cmap = FRAME_X_COLORMAP (f);
3790 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3791 Display *dpy = FRAME_X_DISPLAY (f);
3793 xgcv.graphics_exposures = False;
3794 xgcv.line_width = 1;
3796 /* Free previously allocated color. The color cell will be reused
3797 when it has been freed as many times as it was allocated, so this
3798 doesn't affect faces using the same colors. */
3799 if (relief->gc
3800 && relief->allocated_p)
3802 x_free_colors (f, &relief->pixel, 1);
3803 relief->allocated_p = 0;
3806 /* Allocate new color. */
3807 xgcv.foreground = default_pixel;
3808 pixel = background;
3809 if (dpyinfo->n_planes != 1
3810 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3812 relief->allocated_p = 1;
3813 xgcv.foreground = relief->pixel = pixel;
3816 if (relief->gc == 0)
3818 xgcv.stipple = dpyinfo->gray;
3819 mask |= GCStipple;
3820 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3822 else
3823 XChangeGC (dpy, relief->gc, mask, &xgcv);
3827 /* Set up colors for the relief lines around glyph string S. */
3829 static void
3830 x_setup_relief_colors (s)
3831 struct glyph_string *s;
3833 struct x_output *di = s->f->output_data.x;
3834 unsigned long color;
3836 if (s->face->use_box_color_for_shadows_p)
3837 color = s->face->box_color;
3838 else if (s->first_glyph->type == IMAGE_GLYPH
3839 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3840 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3841 else
3843 XGCValues xgcv;
3845 /* Get the background color of the face. */
3846 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3847 color = xgcv.background;
3850 if (di->white_relief.gc == 0
3851 || color != di->relief_background)
3853 di->relief_background = color;
3854 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3855 WHITE_PIX_DEFAULT (s->f));
3856 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3857 BLACK_PIX_DEFAULT (s->f));
3862 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3863 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3864 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3865 relief. LEFT_P non-zero means draw a relief on the left side of
3866 the rectangle. RIGHT_P non-zero means draw a relief on the right
3867 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3868 when drawing. */
3870 static void
3871 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3872 raised_p, left_p, right_p, clip_rect)
3873 struct frame *f;
3874 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3875 XRectangle *clip_rect;
3877 Display *dpy = FRAME_X_DISPLAY (f);
3878 Window window = FRAME_X_WINDOW (f);
3879 int i;
3880 GC gc;
3882 if (raised_p)
3883 gc = f->output_data.x->white_relief.gc;
3884 else
3885 gc = f->output_data.x->black_relief.gc;
3886 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3888 /* Top. */
3889 for (i = 0; i < width; ++i)
3890 XDrawLine (dpy, window, gc,
3891 left_x + i * left_p, top_y + i,
3892 right_x + 1 - i * right_p, top_y + i);
3894 /* Left. */
3895 if (left_p)
3896 for (i = 0; i < width; ++i)
3897 XDrawLine (dpy, window, gc,
3898 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3900 XSetClipMask (dpy, gc, None);
3901 if (raised_p)
3902 gc = f->output_data.x->black_relief.gc;
3903 else
3904 gc = f->output_data.x->white_relief.gc;
3905 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3907 /* Bottom. */
3908 for (i = 0; i < width; ++i)
3909 XDrawLine (dpy, window, gc,
3910 left_x + i * left_p, bottom_y - i,
3911 right_x + 1 - i * right_p, bottom_y - i);
3913 /* Right. */
3914 if (right_p)
3915 for (i = 0; i < width; ++i)
3916 XDrawLine (dpy, window, gc,
3917 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3919 XSetClipMask (dpy, gc, None);
3923 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3924 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3925 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3926 left side of the rectangle. RIGHT_P non-zero means draw a line
3927 on the right side of the rectangle. CLIP_RECT is the clipping
3928 rectangle to use when drawing. */
3930 static void
3931 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3932 left_p, right_p, clip_rect)
3933 struct glyph_string *s;
3934 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3935 XRectangle *clip_rect;
3937 XGCValues xgcv;
3939 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3940 XSetForeground (s->display, s->gc, s->face->box_color);
3941 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3943 /* Top. */
3944 XFillRectangle (s->display, s->window, s->gc,
3945 left_x, top_y, right_x - left_x + 1, width);
3947 /* Left. */
3948 if (left_p)
3949 XFillRectangle (s->display, s->window, s->gc,
3950 left_x, top_y, width, bottom_y - top_y + 1);
3952 /* Bottom. */
3953 XFillRectangle (s->display, s->window, s->gc,
3954 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3956 /* Right. */
3957 if (right_p)
3958 XFillRectangle (s->display, s->window, s->gc,
3959 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3961 XSetForeground (s->display, s->gc, xgcv.foreground);
3962 XSetClipMask (s->display, s->gc, None);
3966 /* Draw a box around glyph string S. */
3968 static void
3969 x_draw_glyph_string_box (s)
3970 struct glyph_string *s;
3972 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3973 int left_p, right_p;
3974 struct glyph *last_glyph;
3975 XRectangle clip_rect;
3977 last_x = window_box_right (s->w, s->area);
3978 if (s->row->full_width_p
3979 && !s->w->pseudo_window_p)
3981 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
3982 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3983 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3986 /* The glyph that may have a right box line. */
3987 last_glyph = (s->cmp || s->img
3988 ? s->first_glyph
3989 : s->first_glyph + s->nchars - 1);
3991 width = abs (s->face->box_line_width);
3992 raised_p = s->face->box == FACE_RAISED_BOX;
3993 left_x = s->x;
3994 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3995 ? last_x - 1
3996 : min (last_x, s->x + s->background_width) - 1);
3997 top_y = s->y;
3998 bottom_y = top_y + s->height - 1;
4000 left_p = (s->first_glyph->left_box_line_p
4001 || (s->hl == DRAW_MOUSE_FACE
4002 && (s->prev == NULL
4003 || s->prev->hl != s->hl)));
4004 right_p = (last_glyph->right_box_line_p
4005 || (s->hl == DRAW_MOUSE_FACE
4006 && (s->next == NULL
4007 || s->next->hl != s->hl)));
4009 x_get_glyph_string_clip_rect (s, &clip_rect);
4011 if (s->face->box == FACE_SIMPLE_BOX)
4012 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4013 left_p, right_p, &clip_rect);
4014 else
4016 x_setup_relief_colors (s);
4017 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4018 width, raised_p, left_p, right_p, &clip_rect);
4023 /* Draw foreground of image glyph string S. */
4025 static void
4026 x_draw_image_foreground (s)
4027 struct glyph_string *s;
4029 int x;
4030 int y = s->ybase - image_ascent (s->img, s->face);
4032 /* If first glyph of S has a left box line, start drawing it to the
4033 right of that line. */
4034 if (s->face->box != FACE_NO_BOX
4035 && s->first_glyph->left_box_line_p)
4036 x = s->x + abs (s->face->box_line_width);
4037 else
4038 x = s->x;
4040 /* If there is a margin around the image, adjust x- and y-position
4041 by that margin. */
4042 x += s->img->hmargin;
4043 y += s->img->vmargin;
4045 if (s->img->pixmap)
4047 if (s->img->mask)
4049 /* We can't set both a clip mask and use XSetClipRectangles
4050 because the latter also sets a clip mask. We also can't
4051 trust on the shape extension to be available
4052 (XShapeCombineRegion). So, compute the rectangle to draw
4053 manually. */
4054 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4055 | GCFunction);
4056 XGCValues xgcv;
4057 XRectangle clip_rect, image_rect, r;
4059 xgcv.clip_mask = s->img->mask;
4060 xgcv.clip_x_origin = x;
4061 xgcv.clip_y_origin = y;
4062 xgcv.function = GXcopy;
4063 XChangeGC (s->display, s->gc, mask, &xgcv);
4065 x_get_glyph_string_clip_rect (s, &clip_rect);
4066 image_rect.x = x;
4067 image_rect.y = y;
4068 image_rect.width = s->img->width;
4069 image_rect.height = s->img->height;
4070 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4071 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4072 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4074 else
4076 XRectangle clip_rect, image_rect, r;
4078 x_get_glyph_string_clip_rect (s, &clip_rect);
4079 image_rect.x = x;
4080 image_rect.y = y;
4081 image_rect.width = s->img->width;
4082 image_rect.height = s->img->height;
4083 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4084 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4085 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4087 /* When the image has a mask, we can expect that at
4088 least part of a mouse highlight or a block cursor will
4089 be visible. If the image doesn't have a mask, make
4090 a block cursor visible by drawing a rectangle around
4091 the image. I believe it's looking better if we do
4092 nothing here for mouse-face. */
4093 if (s->hl == DRAW_CURSOR)
4094 XDrawRectangle (s->display, s->window, s->gc, x, y,
4095 s->img->width - 1, s->img->height - 1);
4098 else
4099 /* Draw a rectangle if image could not be loaded. */
4100 XDrawRectangle (s->display, s->window, s->gc, x, y,
4101 s->img->width - 1, s->img->height - 1);
4105 /* Draw a relief around the image glyph string S. */
4107 static void
4108 x_draw_image_relief (s)
4109 struct glyph_string *s;
4111 int x0, y0, x1, y1, thick, raised_p;
4112 XRectangle r;
4113 int x;
4114 int y = s->ybase - image_ascent (s->img, s->face);
4116 /* If first glyph of S has a left box line, start drawing it to the
4117 right of that line. */
4118 if (s->face->box != FACE_NO_BOX
4119 && s->first_glyph->left_box_line_p)
4120 x = s->x + abs (s->face->box_line_width);
4121 else
4122 x = s->x;
4124 /* If there is a margin around the image, adjust x- and y-position
4125 by that margin. */
4126 x += s->img->hmargin;
4127 y += s->img->vmargin;
4129 if (s->hl == DRAW_IMAGE_SUNKEN
4130 || s->hl == DRAW_IMAGE_RAISED)
4132 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4133 raised_p = s->hl == DRAW_IMAGE_RAISED;
4135 else
4137 thick = abs (s->img->relief);
4138 raised_p = s->img->relief > 0;
4141 x0 = x - thick;
4142 y0 = y - thick;
4143 x1 = x + s->img->width + thick - 1;
4144 y1 = y + s->img->height + thick - 1;
4146 x_setup_relief_colors (s);
4147 x_get_glyph_string_clip_rect (s, &r);
4148 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4152 /* Draw the foreground of image glyph string S to PIXMAP. */
4154 static void
4155 x_draw_image_foreground_1 (s, pixmap)
4156 struct glyph_string *s;
4157 Pixmap pixmap;
4159 int x;
4160 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4162 /* If first glyph of S has a left box line, start drawing it to the
4163 right of that line. */
4164 if (s->face->box != FACE_NO_BOX
4165 && s->first_glyph->left_box_line_p)
4166 x = abs (s->face->box_line_width);
4167 else
4168 x = 0;
4170 /* If there is a margin around the image, adjust x- and y-position
4171 by that margin. */
4172 x += s->img->hmargin;
4173 y += s->img->vmargin;
4175 if (s->img->pixmap)
4177 if (s->img->mask)
4179 /* We can't set both a clip mask and use XSetClipRectangles
4180 because the latter also sets a clip mask. We also can't
4181 trust on the shape extension to be available
4182 (XShapeCombineRegion). So, compute the rectangle to draw
4183 manually. */
4184 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4185 | GCFunction);
4186 XGCValues xgcv;
4188 xgcv.clip_mask = s->img->mask;
4189 xgcv.clip_x_origin = x;
4190 xgcv.clip_y_origin = y;
4191 xgcv.function = GXcopy;
4192 XChangeGC (s->display, s->gc, mask, &xgcv);
4194 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4195 0, 0, s->img->width, s->img->height, x, y);
4196 XSetClipMask (s->display, s->gc, None);
4198 else
4200 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4201 0, 0, s->img->width, s->img->height, x, y);
4203 /* When the image has a mask, we can expect that at
4204 least part of a mouse highlight or a block cursor will
4205 be visible. If the image doesn't have a mask, make
4206 a block cursor visible by drawing a rectangle around
4207 the image. I believe it's looking better if we do
4208 nothing here for mouse-face. */
4209 if (s->hl == DRAW_CURSOR)
4210 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4211 s->img->width - 1, s->img->height - 1);
4214 else
4215 /* Draw a rectangle if image could not be loaded. */
4216 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4217 s->img->width - 1, s->img->height - 1);
4221 /* Draw part of the background of glyph string S. X, Y, W, and H
4222 give the rectangle to draw. */
4224 static void
4225 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4226 struct glyph_string *s;
4227 int x, y, w, h;
4229 if (s->stippled_p)
4231 /* Fill background with a stipple pattern. */
4232 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4233 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4234 XSetFillStyle (s->display, s->gc, FillSolid);
4236 else
4237 x_clear_glyph_string_rect (s, x, y, w, h);
4241 /* Draw image glyph string S.
4243 s->y
4244 s->x +-------------------------
4245 | s->face->box
4247 | +-------------------------
4248 | | s->img->margin
4250 | | +-------------------
4251 | | | the image
4255 static void
4256 x_draw_image_glyph_string (s)
4257 struct glyph_string *s;
4259 int x, y;
4260 int box_line_hwidth = abs (s->face->box_line_width);
4261 int box_line_vwidth = max (s->face->box_line_width, 0);
4262 int height;
4263 Pixmap pixmap = None;
4265 height = s->height - 2 * box_line_vwidth;
4267 /* Fill background with face under the image. Do it only if row is
4268 taller than image or if image has a clip mask to reduce
4269 flickering. */
4270 s->stippled_p = s->face->stipple != 0;
4271 if (height > s->img->height
4272 || s->img->hmargin
4273 || s->img->vmargin
4274 || s->img->mask
4275 || s->img->pixmap == 0
4276 || s->width != s->background_width)
4278 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4279 x = s->x + box_line_hwidth;
4280 else
4281 x = s->x;
4283 y = s->y + box_line_vwidth;
4285 if (s->img->mask)
4287 /* Create a pixmap as large as the glyph string. Fill it
4288 with the background color. Copy the image to it, using
4289 its mask. Copy the temporary pixmap to the display. */
4290 Screen *screen = FRAME_X_SCREEN (s->f);
4291 int depth = DefaultDepthOfScreen (screen);
4293 /* Create a pixmap as large as the glyph string. */
4294 pixmap = XCreatePixmap (s->display, s->window,
4295 s->background_width,
4296 s->height, depth);
4298 /* Don't clip in the following because we're working on the
4299 pixmap. */
4300 XSetClipMask (s->display, s->gc, None);
4302 /* Fill the pixmap with the background color/stipple. */
4303 if (s->stippled_p)
4305 /* Fill background with a stipple pattern. */
4306 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4307 XFillRectangle (s->display, pixmap, s->gc,
4308 0, 0, s->background_width, s->height);
4309 XSetFillStyle (s->display, s->gc, FillSolid);
4311 else
4313 XGCValues xgcv;
4314 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4315 &xgcv);
4316 XSetForeground (s->display, s->gc, xgcv.background);
4317 XFillRectangle (s->display, pixmap, s->gc,
4318 0, 0, s->background_width, s->height);
4319 XSetForeground (s->display, s->gc, xgcv.foreground);
4322 else
4323 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4325 s->background_filled_p = 1;
4328 /* Draw the foreground. */
4329 if (pixmap != None)
4331 x_draw_image_foreground_1 (s, pixmap);
4332 x_set_glyph_string_clipping (s);
4333 XCopyArea (s->display, pixmap, s->window, s->gc,
4334 0, 0, s->background_width, s->height, s->x, s->y);
4335 XFreePixmap (s->display, pixmap);
4337 else
4338 x_draw_image_foreground (s);
4340 /* If we must draw a relief around the image, do it. */
4341 if (s->img->relief
4342 || s->hl == DRAW_IMAGE_RAISED
4343 || s->hl == DRAW_IMAGE_SUNKEN)
4344 x_draw_image_relief (s);
4348 /* Draw stretch glyph string S. */
4350 static void
4351 x_draw_stretch_glyph_string (s)
4352 struct glyph_string *s;
4354 xassert (s->first_glyph->type == STRETCH_GLYPH);
4355 s->stippled_p = s->face->stipple != 0;
4357 if (s->hl == DRAW_CURSOR
4358 && !x_stretch_cursor_p)
4360 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4361 as wide as the stretch glyph. */
4362 int width = min (CANON_X_UNIT (s->f), s->background_width);
4364 /* Draw cursor. */
4365 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4367 /* Clear rest using the GC of the original non-cursor face. */
4368 if (width < s->background_width)
4370 int x = s->x + width, y = s->y;
4371 int w = s->background_width - width, h = s->height;
4372 XRectangle r;
4373 GC gc;
4375 if (s->row->mouse_face_p
4376 && cursor_in_mouse_face_p (s->w))
4378 x_set_mouse_face_gc (s);
4379 gc = s->gc;
4381 else
4382 gc = s->face->gc;
4384 x_get_glyph_string_clip_rect (s, &r);
4385 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4387 if (s->face->stipple)
4389 /* Fill background with a stipple pattern. */
4390 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4391 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4392 XSetFillStyle (s->display, gc, FillSolid);
4394 else
4396 XGCValues xgcv;
4397 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4398 XSetForeground (s->display, gc, xgcv.background);
4399 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4400 XSetForeground (s->display, gc, xgcv.foreground);
4404 else if (!s->background_filled_p)
4405 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4406 s->height);
4408 s->background_filled_p = 1;
4412 /* Draw glyph string S. */
4414 static void
4415 x_draw_glyph_string (s)
4416 struct glyph_string *s;
4418 int relief_drawn_p = 0;
4420 /* If S draws into the background of its successor, draw the
4421 background of the successor first so that S can draw into it.
4422 This makes S->next use XDrawString instead of XDrawImageString. */
4423 if (s->next && s->right_overhang && !s->for_overlaps_p)
4425 xassert (s->next->img == NULL);
4426 x_set_glyph_string_gc (s->next);
4427 x_set_glyph_string_clipping (s->next);
4428 x_draw_glyph_string_background (s->next, 1);
4431 /* Set up S->gc, set clipping and draw S. */
4432 x_set_glyph_string_gc (s);
4434 /* Draw relief (if any) in advance for char/composition so that the
4435 glyph string can be drawn over it. */
4436 if (!s->for_overlaps_p
4437 && s->face->box != FACE_NO_BOX
4438 && (s->first_glyph->type == CHAR_GLYPH
4439 || s->first_glyph->type == COMPOSITE_GLYPH))
4442 x_set_glyph_string_clipping (s);
4443 x_draw_glyph_string_background (s, 1);
4444 x_draw_glyph_string_box (s);
4445 x_set_glyph_string_clipping (s);
4446 relief_drawn_p = 1;
4448 else
4449 x_set_glyph_string_clipping (s);
4451 switch (s->first_glyph->type)
4453 case IMAGE_GLYPH:
4454 x_draw_image_glyph_string (s);
4455 break;
4457 case STRETCH_GLYPH:
4458 x_draw_stretch_glyph_string (s);
4459 break;
4461 case CHAR_GLYPH:
4462 if (s->for_overlaps_p)
4463 s->background_filled_p = 1;
4464 else
4465 x_draw_glyph_string_background (s, 0);
4466 x_draw_glyph_string_foreground (s);
4467 break;
4469 case COMPOSITE_GLYPH:
4470 if (s->for_overlaps_p || s->gidx > 0)
4471 s->background_filled_p = 1;
4472 else
4473 x_draw_glyph_string_background (s, 1);
4474 x_draw_composite_glyph_string_foreground (s);
4475 break;
4477 default:
4478 abort ();
4481 if (!s->for_overlaps_p)
4483 /* Draw underline. */
4484 if (s->face->underline_p)
4486 unsigned long tem, h;
4487 int y;
4489 /* Get the underline thickness. Default is 1 pixel. */
4490 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4491 h = 1;
4493 /* Get the underline position. This is the recommended
4494 vertical offset in pixels from the baseline to the top of
4495 the underline. This is a signed value according to the
4496 specs, and its default is
4498 ROUND ((maximum descent) / 2), with
4499 ROUND(x) = floor (x + 0.5) */
4501 if (x_use_underline_position_properties
4502 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4503 y = s->ybase + (long) tem;
4504 else if (s->face->font)
4505 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4506 else
4507 y = s->y + s->height - h;
4509 if (s->face->underline_defaulted_p)
4510 XFillRectangle (s->display, s->window, s->gc,
4511 s->x, y, s->width, h);
4512 else
4514 XGCValues xgcv;
4515 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4516 XSetForeground (s->display, s->gc, s->face->underline_color);
4517 XFillRectangle (s->display, s->window, s->gc,
4518 s->x, y, s->width, h);
4519 XSetForeground (s->display, s->gc, xgcv.foreground);
4523 /* Draw overline. */
4524 if (s->face->overline_p)
4526 unsigned long dy = 0, h = 1;
4528 if (s->face->overline_color_defaulted_p)
4529 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4530 s->width, h);
4531 else
4533 XGCValues xgcv;
4534 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4535 XSetForeground (s->display, s->gc, s->face->overline_color);
4536 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4537 s->width, h);
4538 XSetForeground (s->display, s->gc, xgcv.foreground);
4542 /* Draw strike-through. */
4543 if (s->face->strike_through_p)
4545 unsigned long h = 1;
4546 unsigned long dy = (s->height - h) / 2;
4548 if (s->face->strike_through_color_defaulted_p)
4549 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4550 s->width, h);
4551 else
4553 XGCValues xgcv;
4554 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4555 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4556 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4557 s->width, h);
4558 XSetForeground (s->display, s->gc, xgcv.foreground);
4562 /* Draw relief if not yet drawn. */
4563 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4564 x_draw_glyph_string_box (s);
4567 /* Reset clipping. */
4568 XSetClipMask (s->display, s->gc, None);
4572 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4573 struct face **, int));
4576 /* Fill glyph string S with composition components specified by S->cmp.
4578 FACES is an array of faces for all components of this composition.
4579 S->gidx is the index of the first component for S.
4580 OVERLAPS_P non-zero means S should draw the foreground only, and
4581 use its physical height for clipping.
4583 Value is the index of a component not in S. */
4585 static int
4586 x_fill_composite_glyph_string (s, faces, overlaps_p)
4587 struct glyph_string *s;
4588 struct face **faces;
4589 int overlaps_p;
4591 int i;
4593 xassert (s);
4595 s->for_overlaps_p = overlaps_p;
4597 s->face = faces[s->gidx];
4598 s->font = s->face->font;
4599 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4601 /* For all glyphs of this composition, starting at the offset
4602 S->gidx, until we reach the end of the definition or encounter a
4603 glyph that requires the different face, add it to S. */
4604 ++s->nchars;
4605 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4606 ++s->nchars;
4608 /* All glyph strings for the same composition has the same width,
4609 i.e. the width set for the first component of the composition. */
4611 s->width = s->first_glyph->pixel_width;
4613 /* If the specified font could not be loaded, use the frame's
4614 default font, but record the fact that we couldn't load it in
4615 the glyph string so that we can draw rectangles for the
4616 characters of the glyph string. */
4617 if (s->font == NULL)
4619 s->font_not_found_p = 1;
4620 s->font = FRAME_FONT (s->f);
4623 /* Adjust base line for subscript/superscript text. */
4624 s->ybase += s->first_glyph->voffset;
4626 xassert (s->face && s->face->gc);
4628 /* This glyph string must always be drawn with 16-bit functions. */
4629 s->two_byte_p = 1;
4631 return s->gidx + s->nchars;
4635 /* Fill glyph string S from a sequence of character glyphs.
4637 FACE_ID is the face id of the string. START is the index of the
4638 first glyph to consider, END is the index of the last + 1.
4639 OVERLAPS_P non-zero means S should draw the foreground only, and
4640 use its physical height for clipping.
4642 Value is the index of the first glyph not in S. */
4644 static int
4645 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4646 struct glyph_string *s;
4647 int face_id;
4648 int start, end, overlaps_p;
4650 struct glyph *glyph, *last;
4651 int voffset;
4652 int glyph_not_available_p;
4654 xassert (s->f == XFRAME (s->w->frame));
4655 xassert (s->nchars == 0);
4656 xassert (start >= 0 && end > start);
4658 s->for_overlaps_p = overlaps_p,
4659 glyph = s->row->glyphs[s->area] + start;
4660 last = s->row->glyphs[s->area] + end;
4661 voffset = glyph->voffset;
4663 glyph_not_available_p = glyph->glyph_not_available_p;
4665 while (glyph < last
4666 && glyph->type == CHAR_GLYPH
4667 && glyph->voffset == voffset
4668 /* Same face id implies same font, nowadays. */
4669 && glyph->face_id == face_id
4670 && glyph->glyph_not_available_p == glyph_not_available_p)
4672 int two_byte_p;
4674 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4675 s->char2b + s->nchars,
4676 &two_byte_p);
4677 s->two_byte_p = two_byte_p;
4678 ++s->nchars;
4679 xassert (s->nchars <= end - start);
4680 s->width += glyph->pixel_width;
4681 ++glyph;
4684 s->font = s->face->font;
4685 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4687 /* If the specified font could not be loaded, use the frame's font,
4688 but record the fact that we couldn't load it in
4689 S->font_not_found_p so that we can draw rectangles for the
4690 characters of the glyph string. */
4691 if (s->font == NULL || glyph_not_available_p)
4693 s->font_not_found_p = 1;
4694 s->font = FRAME_FONT (s->f);
4697 /* Adjust base line for subscript/superscript text. */
4698 s->ybase += voffset;
4700 xassert (s->face && s->face->gc);
4701 return glyph - s->row->glyphs[s->area];
4705 /* Fill glyph string S from image glyph S->first_glyph. */
4707 static void
4708 x_fill_image_glyph_string (s)
4709 struct glyph_string *s;
4711 xassert (s->first_glyph->type == IMAGE_GLYPH);
4712 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4713 xassert (s->img);
4714 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4715 s->font = s->face->font;
4716 s->width = s->first_glyph->pixel_width;
4718 /* Adjust base line for subscript/superscript text. */
4719 s->ybase += s->first_glyph->voffset;
4723 /* Fill glyph string S from a sequence of stretch glyphs.
4725 ROW is the glyph row in which the glyphs are found, AREA is the
4726 area within the row. START is the index of the first glyph to
4727 consider, END is the index of the last + 1.
4729 Value is the index of the first glyph not in S. */
4731 static int
4732 x_fill_stretch_glyph_string (s, row, area, start, end)
4733 struct glyph_string *s;
4734 struct glyph_row *row;
4735 enum glyph_row_area area;
4736 int start, end;
4738 struct glyph *glyph, *last;
4739 int voffset, face_id;
4741 xassert (s->first_glyph->type == STRETCH_GLYPH);
4743 glyph = s->row->glyphs[s->area] + start;
4744 last = s->row->glyphs[s->area] + end;
4745 face_id = glyph->face_id;
4746 s->face = FACE_FROM_ID (s->f, face_id);
4747 s->font = s->face->font;
4748 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4749 s->width = glyph->pixel_width;
4750 voffset = glyph->voffset;
4752 for (++glyph;
4753 (glyph < last
4754 && glyph->type == STRETCH_GLYPH
4755 && glyph->voffset == voffset
4756 && glyph->face_id == face_id);
4757 ++glyph)
4758 s->width += glyph->pixel_width;
4760 /* Adjust base line for subscript/superscript text. */
4761 s->ybase += voffset;
4763 /* The case that face->gc == 0 is handled when drawing the glyph
4764 string by calling PREPARE_FACE_FOR_DISPLAY. */
4765 xassert (s->face);
4766 return glyph - s->row->glyphs[s->area];
4770 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4771 of XChar2b structures for S; it can't be allocated in
4772 x_init_glyph_string because it must be allocated via `alloca'. W
4773 is the window on which S is drawn. ROW and AREA are the glyph row
4774 and area within the row from which S is constructed. START is the
4775 index of the first glyph structure covered by S. HL is a
4776 face-override for drawing S. */
4778 static void
4779 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4780 struct glyph_string *s;
4781 XChar2b *char2b;
4782 struct window *w;
4783 struct glyph_row *row;
4784 enum glyph_row_area area;
4785 int start;
4786 enum draw_glyphs_face hl;
4788 bzero (s, sizeof *s);
4789 s->w = w;
4790 s->f = XFRAME (w->frame);
4791 s->display = FRAME_X_DISPLAY (s->f);
4792 s->window = FRAME_X_WINDOW (s->f);
4793 s->char2b = char2b;
4794 s->hl = hl;
4795 s->row = row;
4796 s->area = area;
4797 s->first_glyph = row->glyphs[area] + start;
4798 s->height = row->height;
4799 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4801 /* Display the internal border below the tool-bar window. */
4802 if (s->w == XWINDOW (s->f->tool_bar_window))
4803 s->y -= s->f->output_data.x->internal_border_width;
4805 s->ybase = s->y + row->ascent;
4809 /* Set background width of glyph string S. START is the index of the
4810 first glyph following S. LAST_X is the right-most x-position + 1
4811 in the drawing area. */
4813 static INLINE void
4814 x_set_glyph_string_background_width (s, start, last_x)
4815 struct glyph_string *s;
4816 int start;
4817 int last_x;
4819 /* If the face of this glyph string has to be drawn to the end of
4820 the drawing area, set S->extends_to_end_of_line_p. */
4821 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4823 if (start == s->row->used[s->area]
4824 && s->area == TEXT_AREA
4825 && ((s->hl == DRAW_NORMAL_TEXT
4826 && (s->row->fill_line_p
4827 || s->face->background != default_face->background
4828 || s->face->stipple != default_face->stipple
4829 || s->row->mouse_face_p))
4830 || s->hl == DRAW_MOUSE_FACE
4831 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4832 && s->row->fill_line_p)))
4833 s->extends_to_end_of_line_p = 1;
4835 /* If S extends its face to the end of the line, set its
4836 background_width to the distance to the right edge of the drawing
4837 area. */
4838 if (s->extends_to_end_of_line_p)
4839 s->background_width = last_x - s->x + 1;
4840 else
4841 s->background_width = s->width;
4845 /* Add a glyph string for a stretch glyph to the list of strings
4846 between HEAD and TAIL. START is the index of the stretch glyph in
4847 row area AREA of glyph row ROW. END is the index of the last glyph
4848 in that glyph row area. X is the current output position assigned
4849 to the new glyph string constructed. HL overrides that face of the
4850 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4851 is the right-most x-position of the drawing area. */
4853 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4854 and below -- keep them on one line. */
4855 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4856 do \
4858 s = (struct glyph_string *) alloca (sizeof *s); \
4859 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4860 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4861 x_append_glyph_string (&HEAD, &TAIL, s); \
4862 s->x = (X); \
4864 while (0)
4867 /* Add a glyph string for an image glyph to the list of strings
4868 between HEAD and TAIL. START is the index of the image glyph in
4869 row area AREA of glyph row ROW. END is the index of the last glyph
4870 in that glyph row area. X is the current output position assigned
4871 to the new glyph string constructed. HL overrides that face of the
4872 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4873 is the right-most x-position of the drawing area. */
4875 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4876 do \
4878 s = (struct glyph_string *) alloca (sizeof *s); \
4879 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4880 x_fill_image_glyph_string (s); \
4881 x_append_glyph_string (&HEAD, &TAIL, s); \
4882 ++START; \
4883 s->x = (X); \
4885 while (0)
4888 /* Add a glyph string for a sequence of character glyphs to the list
4889 of strings between HEAD and TAIL. START is the index of the first
4890 glyph in row area AREA of glyph row ROW that is part of the new
4891 glyph string. END is the index of the last glyph in that glyph row
4892 area. X is the current output position assigned to the new glyph
4893 string constructed. HL overrides that face of the glyph; e.g. it
4894 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4895 right-most x-position of the drawing area. */
4897 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4898 do \
4900 int c, face_id; \
4901 XChar2b *char2b; \
4903 c = (ROW)->glyphs[AREA][START].u.ch; \
4904 face_id = (ROW)->glyphs[AREA][START].face_id; \
4906 s = (struct glyph_string *) alloca (sizeof *s); \
4907 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4908 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4909 x_append_glyph_string (&HEAD, &TAIL, s); \
4910 s->x = (X); \
4911 START = x_fill_glyph_string (s, face_id, START, END, \
4912 OVERLAPS_P); \
4914 while (0)
4917 /* Add a glyph string for a composite sequence to the list of strings
4918 between HEAD and TAIL. START is the index of the first glyph in
4919 row area AREA of glyph row ROW that is part of the new glyph
4920 string. END is the index of the last glyph in that glyph row area.
4921 X is the current output position assigned to the new glyph string
4922 constructed. HL overrides that face of the glyph; e.g. it is
4923 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4924 x-position of the drawing area. */
4926 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4927 do { \
4928 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4929 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4930 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4931 struct composition *cmp = composition_table[cmp_id]; \
4932 int glyph_len = cmp->glyph_len; \
4933 XChar2b *char2b; \
4934 struct face **faces; \
4935 struct glyph_string *first_s = NULL; \
4936 int n; \
4938 base_face = base_face->ascii_face; \
4939 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4940 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4941 /* At first, fill in `char2b' and `faces'. */ \
4942 for (n = 0; n < glyph_len; n++) \
4944 int c = COMPOSITION_GLYPH (cmp, n); \
4945 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4946 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4947 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4948 this_face_id, char2b + n, 1); \
4951 /* Make glyph_strings for each glyph sequence that is drawable by \
4952 the same face, and append them to HEAD/TAIL. */ \
4953 for (n = 0; n < cmp->glyph_len;) \
4955 s = (struct glyph_string *) alloca (sizeof *s); \
4956 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4957 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4958 s->cmp = cmp; \
4959 s->gidx = n; \
4960 s->x = (X); \
4962 if (n == 0) \
4963 first_s = s; \
4965 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4968 ++START; \
4969 s = first_s; \
4970 } while (0)
4973 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4974 of AREA of glyph row ROW on window W between indices START and END.
4975 HL overrides the face for drawing glyph strings, e.g. it is
4976 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4977 x-positions of the drawing area.
4979 This is an ugly monster macro construct because we must use alloca
4980 to allocate glyph strings (because x_draw_glyphs can be called
4981 asynchronously). */
4983 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4984 do \
4986 HEAD = TAIL = NULL; \
4987 while (START < END) \
4989 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4990 switch (first_glyph->type) \
4992 case CHAR_GLYPH: \
4993 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4994 TAIL, HL, X, LAST_X, \
4995 OVERLAPS_P); \
4996 break; \
4998 case COMPOSITE_GLYPH: \
4999 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5000 HEAD, TAIL, HL, X, LAST_X,\
5001 OVERLAPS_P); \
5002 break; \
5004 case STRETCH_GLYPH: \
5005 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5006 HEAD, TAIL, HL, X, LAST_X); \
5007 break; \
5009 case IMAGE_GLYPH: \
5010 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5011 TAIL, HL, X, LAST_X); \
5012 break; \
5014 default: \
5015 abort (); \
5018 x_set_glyph_string_background_width (s, START, LAST_X); \
5019 (X) += s->width; \
5022 while (0)
5025 /* Draw glyphs between START and END in AREA of ROW on window W,
5026 starting at x-position X. X is relative to AREA in W. HL is a
5027 face-override with the following meaning:
5029 DRAW_NORMAL_TEXT draw normally
5030 DRAW_CURSOR draw in cursor face
5031 DRAW_MOUSE_FACE draw in mouse face.
5032 DRAW_INVERSE_VIDEO draw in mode line face
5033 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5034 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5036 If OVERLAPS_P is non-zero, draw only the foreground of characters
5037 and clip to the physical height of ROW.
5039 Value is the x-position reached, relative to AREA of W. */
5041 static int
5042 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5043 struct window *w;
5044 int x;
5045 struct glyph_row *row;
5046 enum glyph_row_area area;
5047 int start, end;
5048 enum draw_glyphs_face hl;
5049 int overlaps_p;
5051 struct glyph_string *head, *tail;
5052 struct glyph_string *s;
5053 int last_x, area_width;
5054 int x_reached;
5055 int i, j;
5057 /* Let's rather be paranoid than getting a SEGV. */
5058 end = min (end, row->used[area]);
5059 start = max (0, start);
5060 start = min (end, start);
5062 /* Translate X to frame coordinates. Set last_x to the right
5063 end of the drawing area. */
5064 if (row->full_width_p)
5066 /* X is relative to the left edge of W, without scroll bars
5067 or fringes. */
5068 struct frame *f = XFRAME (w->frame);
5069 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5071 x += window_left_x;
5072 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5073 last_x = window_left_x + area_width;
5075 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5077 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5078 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5079 last_x += width;
5080 else
5081 x -= width;
5084 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5085 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5087 else
5089 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5090 area_width = window_box_width (w, area);
5091 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5094 /* Build a doubly-linked list of glyph_string structures between
5095 head and tail from what we have to draw. Note that the macro
5096 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5097 the reason we use a separate variable `i'. */
5098 i = start;
5099 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5100 overlaps_p);
5101 if (tail)
5102 x_reached = tail->x + tail->background_width;
5103 else
5104 x_reached = x;
5106 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5107 the row, redraw some glyphs in front or following the glyph
5108 strings built above. */
5109 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5111 int dummy_x = 0;
5112 struct glyph_string *h, *t;
5114 /* Compute overhangs for all glyph strings. */
5115 for (s = head; s; s = s->next)
5116 x_compute_glyph_string_overhangs (s);
5118 /* Prepend glyph strings for glyphs in front of the first glyph
5119 string that are overwritten because of the first glyph
5120 string's left overhang. The background of all strings
5121 prepended must be drawn because the first glyph string
5122 draws over it. */
5123 i = x_left_overwritten (head);
5124 if (i >= 0)
5126 j = i;
5127 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5128 DRAW_NORMAL_TEXT, dummy_x, last_x,
5129 overlaps_p);
5130 start = i;
5131 x_compute_overhangs_and_x (t, head->x, 1);
5132 x_prepend_glyph_string_lists (&head, &tail, h, t);
5135 /* Prepend glyph strings for glyphs in front of the first glyph
5136 string that overwrite that glyph string because of their
5137 right overhang. For these strings, only the foreground must
5138 be drawn, because it draws over the glyph string at `head'.
5139 The background must not be drawn because this would overwrite
5140 right overhangs of preceding glyphs for which no glyph
5141 strings exist. */
5142 i = x_left_overwriting (head);
5143 if (i >= 0)
5145 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5146 DRAW_NORMAL_TEXT, dummy_x, last_x,
5147 overlaps_p);
5148 for (s = h; s; s = s->next)
5149 s->background_filled_p = 1;
5150 x_compute_overhangs_and_x (t, head->x, 1);
5151 x_prepend_glyph_string_lists (&head, &tail, h, t);
5154 /* Append glyphs strings for glyphs following the last glyph
5155 string tail that are overwritten by tail. The background of
5156 these strings has to be drawn because tail's foreground draws
5157 over it. */
5158 i = x_right_overwritten (tail);
5159 if (i >= 0)
5161 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5162 DRAW_NORMAL_TEXT, x, last_x,
5163 overlaps_p);
5164 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5165 x_append_glyph_string_lists (&head, &tail, h, t);
5168 /* Append glyph strings for glyphs following the last glyph
5169 string tail that overwrite tail. The foreground of such
5170 glyphs has to be drawn because it writes into the background
5171 of tail. The background must not be drawn because it could
5172 paint over the foreground of following glyphs. */
5173 i = x_right_overwriting (tail);
5174 if (i >= 0)
5176 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5177 DRAW_NORMAL_TEXT, x, last_x,
5178 overlaps_p);
5179 for (s = h; s; s = s->next)
5180 s->background_filled_p = 1;
5181 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5182 x_append_glyph_string_lists (&head, &tail, h, t);
5186 /* Draw all strings. */
5187 for (s = head; s; s = s->next)
5188 x_draw_glyph_string (s);
5190 if (area == TEXT_AREA
5191 && !row->full_width_p
5192 /* When drawing overlapping rows, only the glyph strings'
5193 foreground is drawn, which doesn't erase a cursor
5194 completely. */
5195 && !overlaps_p)
5197 int x0 = head ? head->x : x;
5198 int x1 = tail ? tail->x + tail->background_width : x;
5200 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5201 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5203 if (XFASTINT (w->left_margin_width) != 0)
5205 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5206 x0 -= left_area_width;
5207 x1 -= left_area_width;
5210 notice_overwritten_cursor (w, x0, x1);
5213 /* Value is the x-position up to which drawn, relative to AREA of W.
5214 This doesn't include parts drawn because of overhangs. */
5215 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5216 if (!row->full_width_p)
5218 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5219 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5220 if (area > TEXT_AREA)
5221 x_reached -= window_box_width (w, TEXT_AREA);
5224 return x_reached;
5228 /* Fix the display of area AREA of overlapping row ROW in window W. */
5230 static void
5231 x_fix_overlapping_area (w, row, area)
5232 struct window *w;
5233 struct glyph_row *row;
5234 enum glyph_row_area area;
5236 int i, x;
5238 BLOCK_INPUT;
5240 if (area == LEFT_MARGIN_AREA)
5241 x = 0;
5242 else if (area == TEXT_AREA)
5243 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5244 else
5245 x = (window_box_width (w, LEFT_MARGIN_AREA)
5246 + window_box_width (w, TEXT_AREA));
5248 for (i = 0; i < row->used[area];)
5250 if (row->glyphs[area][i].overlaps_vertically_p)
5252 int start = i, start_x = x;
5256 x += row->glyphs[area][i].pixel_width;
5257 ++i;
5259 while (i < row->used[area]
5260 && row->glyphs[area][i].overlaps_vertically_p);
5262 x_draw_glyphs (w, start_x, row, area, start, i,
5263 DRAW_NORMAL_TEXT, 1);
5265 else
5267 x += row->glyphs[area][i].pixel_width;
5268 ++i;
5272 UNBLOCK_INPUT;
5276 /* Output LEN glyphs starting at START at the nominal cursor position.
5277 Advance the nominal cursor over the text. The global variable
5278 updated_window contains the window being updated, updated_row is
5279 the glyph row being updated, and updated_area is the area of that
5280 row being updated. */
5282 static void
5283 x_write_glyphs (start, len)
5284 struct glyph *start;
5285 int len;
5287 int x, hpos;
5289 xassert (updated_window && updated_row);
5290 BLOCK_INPUT;
5292 /* Write glyphs. */
5294 hpos = start - updated_row->glyphs[updated_area];
5295 x = x_draw_glyphs (updated_window, output_cursor.x,
5296 updated_row, updated_area,
5297 hpos, hpos + len,
5298 DRAW_NORMAL_TEXT, 0);
5300 UNBLOCK_INPUT;
5302 /* Advance the output cursor. */
5303 output_cursor.hpos += len;
5304 output_cursor.x = x;
5308 /* Insert LEN glyphs from START at the nominal cursor position. */
5310 static void
5311 x_insert_glyphs (start, len)
5312 struct glyph *start;
5313 register int len;
5315 struct frame *f;
5316 struct window *w;
5317 int line_height, shift_by_width, shifted_region_width;
5318 struct glyph_row *row;
5319 struct glyph *glyph;
5320 int frame_x, frame_y, hpos;
5322 xassert (updated_window && updated_row);
5323 BLOCK_INPUT;
5324 w = updated_window;
5325 f = XFRAME (WINDOW_FRAME (w));
5327 /* Get the height of the line we are in. */
5328 row = updated_row;
5329 line_height = row->height;
5331 /* Get the width of the glyphs to insert. */
5332 shift_by_width = 0;
5333 for (glyph = start; glyph < start + len; ++glyph)
5334 shift_by_width += glyph->pixel_width;
5336 /* Get the width of the region to shift right. */
5337 shifted_region_width = (window_box_width (w, updated_area)
5338 - output_cursor.x
5339 - shift_by_width);
5341 /* Shift right. */
5342 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5343 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5344 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5345 f->output_data.x->normal_gc,
5346 frame_x, frame_y,
5347 shifted_region_width, line_height,
5348 frame_x + shift_by_width, frame_y);
5350 /* Write the glyphs. */
5351 hpos = start - row->glyphs[updated_area];
5352 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5353 DRAW_NORMAL_TEXT, 0);
5355 /* Advance the output cursor. */
5356 output_cursor.hpos += len;
5357 output_cursor.x += shift_by_width;
5358 UNBLOCK_INPUT;
5362 /* Delete N glyphs at the nominal cursor position. Not implemented
5363 for X frames. */
5365 static void
5366 x_delete_glyphs (n)
5367 register int n;
5369 abort ();
5373 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5374 If they are <= 0, this is probably an error. */
5376 void
5377 x_clear_area (dpy, window, x, y, width, height, exposures)
5378 Display *dpy;
5379 Window window;
5380 int x, y;
5381 int width, height;
5382 int exposures;
5384 xassert (width > 0 && height > 0);
5385 XClearArea (dpy, window, x, y, width, height, exposures);
5389 /* Erase the current text line from the nominal cursor position
5390 (inclusive) to pixel column TO_X (exclusive). The idea is that
5391 everything from TO_X onward is already erased.
5393 TO_X is a pixel position relative to updated_area of
5394 updated_window. TO_X == -1 means clear to the end of this area. */
5396 static void
5397 x_clear_end_of_line (to_x)
5398 int to_x;
5400 struct frame *f;
5401 struct window *w = updated_window;
5402 int max_x, min_y, max_y;
5403 int from_x, from_y, to_y;
5405 xassert (updated_window && updated_row);
5406 f = XFRAME (w->frame);
5408 if (updated_row->full_width_p)
5410 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5411 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5412 && !w->pseudo_window_p)
5413 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5415 else
5416 max_x = window_box_width (w, updated_area);
5417 max_y = window_text_bottom_y (w);
5419 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5420 of window. For TO_X > 0, truncate to end of drawing area. */
5421 if (to_x == 0)
5422 return;
5423 else if (to_x < 0)
5424 to_x = max_x;
5425 else
5426 to_x = min (to_x, max_x);
5428 to_y = min (max_y, output_cursor.y + updated_row->height);
5430 /* Notice if the cursor will be cleared by this operation. */
5431 if (!updated_row->full_width_p)
5432 notice_overwritten_cursor (w, output_cursor.x, -1);
5434 from_x = output_cursor.x;
5436 /* Translate to frame coordinates. */
5437 if (updated_row->full_width_p)
5439 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5440 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5442 else
5444 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5445 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5448 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5449 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5450 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5452 /* Prevent inadvertently clearing to end of the X window. */
5453 if (to_x > from_x && to_y > from_y)
5455 BLOCK_INPUT;
5456 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5457 from_x, from_y, to_x - from_x, to_y - from_y,
5458 False);
5459 UNBLOCK_INPUT;
5464 /* Clear entire frame. If updating_frame is non-null, clear that
5465 frame. Otherwise clear the selected frame. */
5467 static void
5468 x_clear_frame ()
5470 struct frame *f;
5472 if (updating_frame)
5473 f = updating_frame;
5474 else
5475 f = SELECTED_FRAME ();
5477 /* Clearing the frame will erase any cursor, so mark them all as no
5478 longer visible. */
5479 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5480 output_cursor.hpos = output_cursor.vpos = 0;
5481 output_cursor.x = -1;
5483 /* We don't set the output cursor here because there will always
5484 follow an explicit cursor_to. */
5485 BLOCK_INPUT;
5486 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5488 /* We have to clear the scroll bars, too. If we have changed
5489 colors or something like that, then they should be notified. */
5490 x_scroll_bar_clear (f);
5492 XFlush (FRAME_X_DISPLAY (f));
5493 UNBLOCK_INPUT;
5498 /* Invert the middle quarter of the frame for .15 sec. */
5500 /* We use the select system call to do the waiting, so we have to make
5501 sure it's available. If it isn't, we just won't do visual bells. */
5503 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5506 /* Subtract the `struct timeval' values X and Y, storing the result in
5507 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5509 static int
5510 timeval_subtract (result, x, y)
5511 struct timeval *result, x, y;
5513 /* Perform the carry for the later subtraction by updating y. This
5514 is safer because on some systems the tv_sec member is unsigned. */
5515 if (x.tv_usec < y.tv_usec)
5517 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5518 y.tv_usec -= 1000000 * nsec;
5519 y.tv_sec += nsec;
5522 if (x.tv_usec - y.tv_usec > 1000000)
5524 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5525 y.tv_usec += 1000000 * nsec;
5526 y.tv_sec -= nsec;
5529 /* Compute the time remaining to wait. tv_usec is certainly
5530 positive. */
5531 result->tv_sec = x.tv_sec - y.tv_sec;
5532 result->tv_usec = x.tv_usec - y.tv_usec;
5534 /* Return indication of whether the result should be considered
5535 negative. */
5536 return x.tv_sec < y.tv_sec;
5539 void
5540 XTflash (f)
5541 struct frame *f;
5543 BLOCK_INPUT;
5546 GC gc;
5548 /* Create a GC that will use the GXxor function to flip foreground
5549 pixels into background pixels. */
5551 XGCValues values;
5553 values.function = GXxor;
5554 values.foreground = (f->output_data.x->foreground_pixel
5555 ^ f->output_data.x->background_pixel);
5557 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5558 GCFunction | GCForeground, &values);
5562 /* Get the height not including a menu bar widget. */
5563 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5564 /* Height of each line to flash. */
5565 int flash_height = FRAME_LINE_HEIGHT (f);
5566 /* These will be the left and right margins of the rectangles. */
5567 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5568 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5570 int width;
5572 /* Don't flash the area between a scroll bar and the frame
5573 edge it is next to. */
5574 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5576 case vertical_scroll_bar_left:
5577 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5578 break;
5580 case vertical_scroll_bar_right:
5581 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5582 break;
5584 default:
5585 break;
5588 width = flash_right - flash_left;
5590 /* If window is tall, flash top and bottom line. */
5591 if (height > 3 * FRAME_LINE_HEIGHT (f))
5593 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5594 flash_left,
5595 (FRAME_INTERNAL_BORDER_WIDTH (f)
5596 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5597 width, flash_height);
5598 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5599 flash_left,
5600 (height - flash_height
5601 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5602 width, flash_height);
5604 else
5605 /* If it is short, flash it all. */
5606 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5607 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5608 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5610 x_flush (f);
5613 struct timeval wakeup;
5615 EMACS_GET_TIME (wakeup);
5617 /* Compute time to wait until, propagating carry from usecs. */
5618 wakeup.tv_usec += 150000;
5619 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5620 wakeup.tv_usec %= 1000000;
5622 /* Keep waiting until past the time wakeup or any input gets
5623 available. */
5624 while (! detect_input_pending ())
5626 struct timeval current;
5627 struct timeval timeout;
5629 EMACS_GET_TIME (current);
5631 /* Break if result would be negative. */
5632 if (timeval_subtract (&current, wakeup, current))
5633 break;
5635 /* How long `select' should wait. */
5636 timeout.tv_sec = 0;
5637 timeout.tv_usec = 10000;
5639 /* Try to wait that long--but we might wake up sooner. */
5640 select (0, NULL, NULL, NULL, &timeout);
5644 /* If window is tall, flash top and bottom line. */
5645 if (height > 3 * FRAME_LINE_HEIGHT (f))
5647 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5648 flash_left,
5649 (FRAME_INTERNAL_BORDER_WIDTH (f)
5650 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5651 width, flash_height);
5652 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5653 flash_left,
5654 (height - flash_height
5655 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5656 width, flash_height);
5658 else
5659 /* If it is short, flash it all. */
5660 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5661 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5662 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5664 XFreeGC (FRAME_X_DISPLAY (f), gc);
5665 x_flush (f);
5669 UNBLOCK_INPUT;
5672 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5675 /* Make audible bell. */
5677 void
5678 XTring_bell ()
5680 struct frame *f = SELECTED_FRAME ();
5682 if (FRAME_X_DISPLAY (f))
5684 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5685 if (visible_bell)
5686 XTflash (f);
5687 else
5688 #endif
5690 BLOCK_INPUT;
5691 XBell (FRAME_X_DISPLAY (f), 0);
5692 XFlush (FRAME_X_DISPLAY (f));
5693 UNBLOCK_INPUT;
5699 /* Specify how many text lines, from the top of the window,
5700 should be affected by insert-lines and delete-lines operations.
5701 This, and those operations, are used only within an update
5702 that is bounded by calls to x_update_begin and x_update_end. */
5704 static void
5705 XTset_terminal_window (n)
5706 register int n;
5708 /* This function intentionally left blank. */
5713 /***********************************************************************
5714 Line Dance
5715 ***********************************************************************/
5717 /* Perform an insert-lines or delete-lines operation, inserting N
5718 lines or deleting -N lines at vertical position VPOS. */
5720 static void
5721 x_ins_del_lines (vpos, n)
5722 int vpos, n;
5724 abort ();
5728 /* Scroll part of the display as described by RUN. */
5730 static void
5731 x_scroll_run (w, run)
5732 struct window *w;
5733 struct run *run;
5735 struct frame *f = XFRAME (w->frame);
5736 int x, y, width, height, from_y, to_y, bottom_y;
5738 /* Get frame-relative bounding box of the text display area of W,
5739 without mode lines. Include in this box the left and right
5740 fringe of W. */
5741 window_box (w, -1, &x, &y, &width, &height);
5742 width += FRAME_X_FRINGE_WIDTH (f);
5743 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5745 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5746 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5747 bottom_y = y + height;
5749 if (to_y < from_y)
5751 /* Scrolling up. Make sure we don't copy part of the mode
5752 line at the bottom. */
5753 if (from_y + run->height > bottom_y)
5754 height = bottom_y - from_y;
5755 else
5756 height = run->height;
5758 else
5760 /* Scolling down. Make sure we don't copy over the mode line.
5761 at the bottom. */
5762 if (to_y + run->height > bottom_y)
5763 height = bottom_y - to_y;
5764 else
5765 height = run->height;
5768 BLOCK_INPUT;
5770 /* Cursor off. Will be switched on again in x_update_window_end. */
5771 updated_window = w;
5772 x_clear_cursor (w);
5774 XCopyArea (FRAME_X_DISPLAY (f),
5775 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5776 f->output_data.x->normal_gc,
5777 x, from_y,
5778 width, height,
5779 x, to_y);
5781 UNBLOCK_INPUT;
5786 /***********************************************************************
5787 Exposure Events
5788 ***********************************************************************/
5790 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5791 corner of the exposed rectangle. W and H are width and height of
5792 the exposed area. All are pixel values. W or H zero means redraw
5793 the entire frame. */
5795 static void
5796 expose_frame (f, x, y, w, h)
5797 struct frame *f;
5798 int x, y, w, h;
5800 XRectangle r;
5801 int mouse_face_overwritten_p = 0;
5803 TRACE ((stderr, "expose_frame "));
5805 /* No need to redraw if frame will be redrawn soon. */
5806 if (FRAME_GARBAGED_P (f))
5808 TRACE ((stderr, " garbaged\n"));
5809 return;
5812 /* If basic faces haven't been realized yet, there is no point in
5813 trying to redraw anything. This can happen when we get an expose
5814 event while Emacs is starting, e.g. by moving another window. */
5815 if (FRAME_FACE_CACHE (f) == NULL
5816 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5818 TRACE ((stderr, " no faces\n"));
5819 return;
5822 if (w == 0 || h == 0)
5824 r.x = r.y = 0;
5825 r.width = CANON_X_UNIT (f) * f->width;
5826 r.height = CANON_Y_UNIT (f) * f->height;
5828 else
5830 r.x = x;
5831 r.y = y;
5832 r.width = w;
5833 r.height = h;
5836 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5837 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5839 if (WINDOWP (f->tool_bar_window))
5840 mouse_face_overwritten_p
5841 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5843 #ifndef USE_X_TOOLKIT
5844 if (WINDOWP (f->menu_bar_window))
5845 mouse_face_overwritten_p
5846 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5847 #endif /* not USE_X_TOOLKIT */
5849 /* Some window managers support a focus-follows-mouse style with
5850 delayed raising of frames. Imagine a partially obscured frame,
5851 and moving the mouse into partially obscured mouse-face on that
5852 frame. The visible part of the mouse-face will be highlighted,
5853 then the WM raises the obscured frame. With at least one WM, KDE
5854 2.1, Emacs is not getting any event for the raising of the frame
5855 (even tried with SubstructureRedirectMask), only Expose events.
5856 These expose events will draw text normally, i.e. not
5857 highlighted. Which means we must redo the highlight here.
5858 Subsume it under ``we love X''. --gerd 2001-08-15 */
5859 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5861 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5862 if (f == dpyinfo->mouse_face_mouse_frame)
5864 int x = dpyinfo->mouse_face_mouse_x;
5865 int y = dpyinfo->mouse_face_mouse_y;
5866 clear_mouse_face (dpyinfo);
5867 note_mouse_highlight (f, x, y);
5873 /* Redraw (parts) of all windows in the window tree rooted at W that
5874 intersect R. R contains frame pixel coordinates. Value is
5875 non-zero if the exposure overwrites mouse-face. */
5877 static int
5878 expose_window_tree (w, r)
5879 struct window *w;
5880 XRectangle *r;
5882 struct frame *f = XFRAME (w->frame);
5883 int mouse_face_overwritten_p = 0;
5885 while (w && !FRAME_GARBAGED_P (f))
5887 if (!NILP (w->hchild))
5888 mouse_face_overwritten_p
5889 |= expose_window_tree (XWINDOW (w->hchild), r);
5890 else if (!NILP (w->vchild))
5891 mouse_face_overwritten_p
5892 |= expose_window_tree (XWINDOW (w->vchild), r);
5893 else
5894 mouse_face_overwritten_p |= expose_window (w, r);
5896 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5899 return mouse_face_overwritten_p;
5903 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5904 which intersects rectangle R. R is in window-relative coordinates. */
5906 static void
5907 expose_area (w, row, r, area)
5908 struct window *w;
5909 struct glyph_row *row;
5910 XRectangle *r;
5911 enum glyph_row_area area;
5913 struct glyph *first = row->glyphs[area];
5914 struct glyph *end = row->glyphs[area] + row->used[area];
5915 struct glyph *last;
5916 int first_x, start_x, x;
5918 if (area == TEXT_AREA && row->fill_line_p)
5919 /* If row extends face to end of line write the whole line. */
5920 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5921 DRAW_NORMAL_TEXT, 0);
5922 else
5924 /* Set START_X to the window-relative start position for drawing glyphs of
5925 AREA. The first glyph of the text area can be partially visible.
5926 The first glyphs of other areas cannot. */
5927 if (area == LEFT_MARGIN_AREA)
5928 start_x = 0;
5929 else if (area == TEXT_AREA)
5930 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5931 else
5932 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5933 + window_box_width (w, TEXT_AREA));
5934 x = start_x;
5936 /* Find the first glyph that must be redrawn. */
5937 while (first < end
5938 && x + first->pixel_width < r->x)
5940 x += first->pixel_width;
5941 ++first;
5944 /* Find the last one. */
5945 last = first;
5946 first_x = x;
5947 while (last < end
5948 && x < r->x + r->width)
5950 x += last->pixel_width;
5951 ++last;
5954 /* Repaint. */
5955 if (last > first)
5956 x_draw_glyphs (w, first_x - start_x, row, area,
5957 first - row->glyphs[area],
5958 last - row->glyphs[area],
5959 DRAW_NORMAL_TEXT, 0);
5964 /* Redraw the parts of the glyph row ROW on window W intersecting
5965 rectangle R. R is in window-relative coordinates. Value is
5966 non-zero if mouse-face was overwritten. */
5968 static int
5969 expose_line (w, row, r)
5970 struct window *w;
5971 struct glyph_row *row;
5972 XRectangle *r;
5974 xassert (row->enabled_p);
5976 if (row->mode_line_p || w->pseudo_window_p)
5977 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5978 DRAW_NORMAL_TEXT, 0);
5979 else
5981 if (row->used[LEFT_MARGIN_AREA])
5982 expose_area (w, row, r, LEFT_MARGIN_AREA);
5983 if (row->used[TEXT_AREA])
5984 expose_area (w, row, r, TEXT_AREA);
5985 if (row->used[RIGHT_MARGIN_AREA])
5986 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5987 x_draw_row_fringe_bitmaps (w, row);
5990 return row->mouse_face_p;
5994 /* Return non-zero if W's cursor intersects rectangle R. */
5996 static int
5997 x_phys_cursor_in_rect_p (w, r)
5998 struct window *w;
5999 XRectangle *r;
6001 XRectangle cr, result;
6002 struct glyph *cursor_glyph;
6004 cursor_glyph = get_phys_cursor_glyph (w);
6005 if (cursor_glyph)
6007 cr.x = w->phys_cursor.x;
6008 cr.y = w->phys_cursor.y;
6009 cr.width = cursor_glyph->pixel_width;
6010 cr.height = w->phys_cursor_height;
6011 return x_intersect_rectangles (&cr, r, &result);
6013 else
6014 return 0;
6018 /* Redraw the part of window W intersection rectangle FR. Pixel
6019 coordinates in FR are frame-relative. Call this function with
6020 input blocked. Value is non-zero if the exposure overwrites
6021 mouse-face. */
6023 static int
6024 expose_window (w, fr)
6025 struct window *w;
6026 XRectangle *fr;
6028 struct frame *f = XFRAME (w->frame);
6029 XRectangle wr, r;
6030 int mouse_face_overwritten_p = 0;
6032 /* If window is not yet fully initialized, do nothing. This can
6033 happen when toolkit scroll bars are used and a window is split.
6034 Reconfiguring the scroll bar will generate an expose for a newly
6035 created window. */
6036 if (w->current_matrix == NULL)
6037 return 0;
6039 /* When we're currently updating the window, display and current
6040 matrix usually don't agree. Arrange for a thorough display
6041 later. */
6042 if (w == updated_window)
6044 SET_FRAME_GARBAGED (f);
6045 return 0;
6048 /* Frame-relative pixel rectangle of W. */
6049 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6050 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6051 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6052 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6054 if (x_intersect_rectangles (fr, &wr, &r))
6056 int yb = window_text_bottom_y (w);
6057 struct glyph_row *row;
6058 int cursor_cleared_p;
6060 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6061 r.x, r.y, r.width, r.height));
6063 /* Convert to window coordinates. */
6064 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6065 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6067 /* Turn off the cursor. */
6068 if (!w->pseudo_window_p
6069 && x_phys_cursor_in_rect_p (w, &r))
6071 x_clear_cursor (w);
6072 cursor_cleared_p = 1;
6074 else
6075 cursor_cleared_p = 0;
6077 /* Find the first row intersecting the rectangle R. */
6078 for (row = w->current_matrix->rows;
6079 row->enabled_p;
6080 ++row)
6082 int y0 = row->y;
6083 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6085 if ((y0 >= r.y && y0 < r.y + r.height)
6086 || (y1 > r.y && y1 < r.y + r.height)
6087 || (r.y >= y0 && r.y < y1)
6088 || (r.y + r.height > y0 && r.y + r.height < y1))
6090 if (expose_line (w, row, &r))
6091 mouse_face_overwritten_p = 1;
6094 if (y1 >= yb)
6095 break;
6098 /* Display the mode line if there is one. */
6099 if (WINDOW_WANTS_MODELINE_P (w)
6100 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6101 row->enabled_p)
6102 && row->y < r.y + r.height)
6104 if (expose_line (w, row, &r))
6105 mouse_face_overwritten_p = 1;
6108 if (!w->pseudo_window_p)
6110 /* Draw border between windows. */
6111 x_draw_vertical_border (w);
6113 /* Turn the cursor on again. */
6114 if (cursor_cleared_p)
6115 x_update_window_cursor (w, 1);
6119 return mouse_face_overwritten_p;
6123 /* Determine the intersection of two rectangles R1 and R2. Return
6124 the intersection in *RESULT. Value is non-zero if RESULT is not
6125 empty. */
6127 static int
6128 x_intersect_rectangles (r1, r2, result)
6129 XRectangle *r1, *r2, *result;
6131 XRectangle *left, *right;
6132 XRectangle *upper, *lower;
6133 int intersection_p = 0;
6135 /* Rearrange so that R1 is the left-most rectangle. */
6136 if (r1->x < r2->x)
6137 left = r1, right = r2;
6138 else
6139 left = r2, right = r1;
6141 /* X0 of the intersection is right.x0, if this is inside R1,
6142 otherwise there is no intersection. */
6143 if (right->x <= left->x + left->width)
6145 result->x = right->x;
6147 /* The right end of the intersection is the minimum of the
6148 the right ends of left and right. */
6149 result->width = (min (left->x + left->width, right->x + right->width)
6150 - result->x);
6152 /* Same game for Y. */
6153 if (r1->y < r2->y)
6154 upper = r1, lower = r2;
6155 else
6156 upper = r2, lower = r1;
6158 /* The upper end of the intersection is lower.y0, if this is inside
6159 of upper. Otherwise, there is no intersection. */
6160 if (lower->y <= upper->y + upper->height)
6162 result->y = lower->y;
6164 /* The lower end of the intersection is the minimum of the lower
6165 ends of upper and lower. */
6166 result->height = (min (lower->y + lower->height,
6167 upper->y + upper->height)
6168 - result->y);
6169 intersection_p = 1;
6173 return intersection_p;
6180 static void
6181 frame_highlight (f)
6182 struct frame *f;
6184 /* We used to only do this if Vx_no_window_manager was non-nil, but
6185 the ICCCM (section 4.1.6) says that the window's border pixmap
6186 and border pixel are window attributes which are "private to the
6187 client", so we can always change it to whatever we want. */
6188 BLOCK_INPUT;
6189 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6190 f->output_data.x->border_pixel);
6191 UNBLOCK_INPUT;
6192 x_update_cursor (f, 1);
6195 static void
6196 frame_unhighlight (f)
6197 struct frame *f;
6199 /* We used to only do this if Vx_no_window_manager was non-nil, but
6200 the ICCCM (section 4.1.6) says that the window's border pixmap
6201 and border pixel are window attributes which are "private to the
6202 client", so we can always change it to whatever we want. */
6203 BLOCK_INPUT;
6204 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6205 f->output_data.x->border_tile);
6206 UNBLOCK_INPUT;
6207 x_update_cursor (f, 1);
6210 /* The focus has changed. Update the frames as necessary to reflect
6211 the new situation. Note that we can't change the selected frame
6212 here, because the Lisp code we are interrupting might become confused.
6213 Each event gets marked with the frame in which it occurred, so the
6214 Lisp code can tell when the switch took place by examining the events. */
6216 static void
6217 x_new_focus_frame (dpyinfo, frame)
6218 struct x_display_info *dpyinfo;
6219 struct frame *frame;
6221 struct frame *old_focus = dpyinfo->x_focus_frame;
6223 if (frame != dpyinfo->x_focus_frame)
6225 /* Set this before calling other routines, so that they see
6226 the correct value of x_focus_frame. */
6227 dpyinfo->x_focus_frame = frame;
6229 if (old_focus && old_focus->auto_lower)
6230 x_lower_frame (old_focus);
6232 #if 0
6233 selected_frame = frame;
6234 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6235 selected_frame);
6236 Fselect_window (selected_frame->selected_window);
6237 choose_minibuf_frame ();
6238 #endif /* ! 0 */
6240 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6241 pending_autoraise_frame = dpyinfo->x_focus_frame;
6242 else
6243 pending_autoraise_frame = 0;
6246 x_frame_rehighlight (dpyinfo);
6249 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6251 void
6252 x_mouse_leave (dpyinfo)
6253 struct x_display_info *dpyinfo;
6255 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6258 /* The focus has changed, or we have redirected a frame's focus to
6259 another frame (this happens when a frame uses a surrogate
6260 mini-buffer frame). Shift the highlight as appropriate.
6262 The FRAME argument doesn't necessarily have anything to do with which
6263 frame is being highlighted or un-highlighted; we only use it to find
6264 the appropriate X display info. */
6266 static void
6267 XTframe_rehighlight (frame)
6268 struct frame *frame;
6270 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6273 static void
6274 x_frame_rehighlight (dpyinfo)
6275 struct x_display_info *dpyinfo;
6277 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6279 if (dpyinfo->x_focus_frame)
6281 dpyinfo->x_highlight_frame
6282 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6283 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6284 : dpyinfo->x_focus_frame);
6285 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6287 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6288 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6291 else
6292 dpyinfo->x_highlight_frame = 0;
6294 if (dpyinfo->x_highlight_frame != old_highlight)
6296 if (old_highlight)
6297 frame_unhighlight (old_highlight);
6298 if (dpyinfo->x_highlight_frame)
6299 frame_highlight (dpyinfo->x_highlight_frame);
6305 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6307 /* Initialize mode_switch_bit and modifier_meaning. */
6308 static void
6309 x_find_modifier_meanings (dpyinfo)
6310 struct x_display_info *dpyinfo;
6312 int min_code, max_code;
6313 KeySym *syms;
6314 int syms_per_code;
6315 XModifierKeymap *mods;
6317 dpyinfo->meta_mod_mask = 0;
6318 dpyinfo->shift_lock_mask = 0;
6319 dpyinfo->alt_mod_mask = 0;
6320 dpyinfo->super_mod_mask = 0;
6321 dpyinfo->hyper_mod_mask = 0;
6323 #ifdef HAVE_X11R4
6324 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6325 #else
6326 min_code = dpyinfo->display->min_keycode;
6327 max_code = dpyinfo->display->max_keycode;
6328 #endif
6330 syms = XGetKeyboardMapping (dpyinfo->display,
6331 min_code, max_code - min_code + 1,
6332 &syms_per_code);
6333 mods = XGetModifierMapping (dpyinfo->display);
6335 /* Scan the modifier table to see which modifier bits the Meta and
6336 Alt keysyms are on. */
6338 int row, col; /* The row and column in the modifier table. */
6340 for (row = 3; row < 8; row++)
6341 for (col = 0; col < mods->max_keypermod; col++)
6343 KeyCode code
6344 = mods->modifiermap[(row * mods->max_keypermod) + col];
6346 /* Zeroes are used for filler. Skip them. */
6347 if (code == 0)
6348 continue;
6350 /* Are any of this keycode's keysyms a meta key? */
6352 int code_col;
6354 for (code_col = 0; code_col < syms_per_code; code_col++)
6356 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6358 switch (sym)
6360 case XK_Meta_L:
6361 case XK_Meta_R:
6362 dpyinfo->meta_mod_mask |= (1 << row);
6363 break;
6365 case XK_Alt_L:
6366 case XK_Alt_R:
6367 dpyinfo->alt_mod_mask |= (1 << row);
6368 break;
6370 case XK_Hyper_L:
6371 case XK_Hyper_R:
6372 dpyinfo->hyper_mod_mask |= (1 << row);
6373 break;
6375 case XK_Super_L:
6376 case XK_Super_R:
6377 dpyinfo->super_mod_mask |= (1 << row);
6378 break;
6380 case XK_Shift_Lock:
6381 /* Ignore this if it's not on the lock modifier. */
6382 if ((1 << row) == LockMask)
6383 dpyinfo->shift_lock_mask = LockMask;
6384 break;
6391 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6392 if (! dpyinfo->meta_mod_mask)
6394 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6395 dpyinfo->alt_mod_mask = 0;
6398 /* If some keys are both alt and meta,
6399 make them just meta, not alt. */
6400 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6402 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6405 XFree ((char *) syms);
6406 XFreeModifiermap (mods);
6409 /* Convert between the modifier bits X uses and the modifier bits
6410 Emacs uses. */
6412 static unsigned int
6413 x_x_to_emacs_modifiers (dpyinfo, state)
6414 struct x_display_info *dpyinfo;
6415 unsigned int state;
6417 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6418 | ((state & ControlMask) ? ctrl_modifier : 0)
6419 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6420 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6421 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6422 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6425 static unsigned int
6426 x_emacs_to_x_modifiers (dpyinfo, state)
6427 struct x_display_info *dpyinfo;
6428 unsigned int state;
6430 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6431 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6432 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6433 | ((state & shift_modifier) ? ShiftMask : 0)
6434 | ((state & ctrl_modifier) ? ControlMask : 0)
6435 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6438 /* Convert a keysym to its name. */
6440 char *
6441 x_get_keysym_name (keysym)
6442 KeySym keysym;
6444 char *value;
6446 BLOCK_INPUT;
6447 value = XKeysymToString (keysym);
6448 UNBLOCK_INPUT;
6450 return value;
6455 /* Mouse clicks and mouse movement. Rah. */
6457 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6458 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6459 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6460 not force the value into range. */
6462 void
6463 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6464 FRAME_PTR f;
6465 register int pix_x, pix_y;
6466 register int *x, *y;
6467 XRectangle *bounds;
6468 int noclip;
6470 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6471 even for negative values. */
6472 if (pix_x < 0)
6473 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6474 if (pix_y < 0)
6475 pix_y -= (f)->output_data.x->line_height - 1;
6477 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6478 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6480 if (bounds)
6482 bounds->width = FONT_WIDTH (f->output_data.x->font);
6483 bounds->height = f->output_data.x->line_height;
6484 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6485 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6488 if (!noclip)
6490 if (pix_x < 0)
6491 pix_x = 0;
6492 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6493 pix_x = FRAME_WINDOW_WIDTH (f);
6495 if (pix_y < 0)
6496 pix_y = 0;
6497 else if (pix_y > f->height)
6498 pix_y = f->height;
6501 *x = pix_x;
6502 *y = pix_y;
6506 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6507 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6508 can't tell the positions because W's display is not up to date,
6509 return 0. */
6512 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6513 struct window *w;
6514 int hpos, vpos;
6515 int *frame_x, *frame_y;
6517 int success_p;
6519 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6520 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6522 if (display_completed)
6524 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6525 struct glyph *glyph = row->glyphs[TEXT_AREA];
6526 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6528 *frame_y = row->y;
6529 *frame_x = row->x;
6530 while (glyph < end)
6532 *frame_x += glyph->pixel_width;
6533 ++glyph;
6536 success_p = 1;
6538 else
6540 *frame_y = *frame_x = 0;
6541 success_p = 0;
6544 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6545 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6546 return success_p;
6550 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6552 If the event is a button press, then note that we have grabbed
6553 the mouse. */
6555 static Lisp_Object
6556 construct_mouse_click (result, event, f)
6557 struct input_event *result;
6558 XButtonEvent *event;
6559 struct frame *f;
6561 /* Make the event type no_event; we'll change that when we decide
6562 otherwise. */
6563 result->kind = mouse_click;
6564 result->code = event->button - Button1;
6565 result->timestamp = event->time;
6566 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6567 event->state)
6568 | (event->type == ButtonRelease
6569 ? up_modifier
6570 : down_modifier));
6572 XSETINT (result->x, event->x);
6573 XSETINT (result->y, event->y);
6574 XSETFRAME (result->frame_or_window, f);
6575 result->arg = Qnil;
6576 return Qnil;
6580 /* Function to report a mouse movement to the mainstream Emacs code.
6581 The input handler calls this.
6583 We have received a mouse movement event, which is given in *event.
6584 If the mouse is over a different glyph than it was last time, tell
6585 the mainstream emacs code by setting mouse_moved. If not, ask for
6586 another motion event, so we can check again the next time it moves. */
6588 static XMotionEvent last_mouse_motion_event;
6589 static Lisp_Object last_mouse_motion_frame;
6591 static void
6592 note_mouse_movement (frame, event)
6593 FRAME_PTR frame;
6594 XMotionEvent *event;
6596 last_mouse_movement_time = event->time;
6597 last_mouse_motion_event = *event;
6598 XSETFRAME (last_mouse_motion_frame, frame);
6600 if (event->window != FRAME_X_WINDOW (frame))
6602 frame->mouse_moved = 1;
6603 last_mouse_scroll_bar = Qnil;
6604 note_mouse_highlight (frame, -1, -1);
6607 /* Has the mouse moved off the glyph it was on at the last sighting? */
6608 else if (event->x < last_mouse_glyph.x
6609 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6610 || event->y < last_mouse_glyph.y
6611 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6613 frame->mouse_moved = 1;
6614 last_mouse_scroll_bar = Qnil;
6615 note_mouse_highlight (frame, event->x, event->y);
6619 /* This is used for debugging, to turn off note_mouse_highlight. */
6621 int disable_mouse_highlight;
6625 /************************************************************************
6626 Mouse Face
6627 ************************************************************************/
6629 /* Find the glyph under window-relative coordinates X/Y in window W.
6630 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6631 strings. Return in *HPOS and *VPOS the row and column number of
6632 the glyph found. Return in *AREA the glyph area containing X.
6633 Value is a pointer to the glyph found or null if X/Y is not on
6634 text, or we can't tell because W's current matrix is not up to
6635 date. */
6637 static struct glyph *
6638 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6639 struct window *w;
6640 int x, y;
6641 int *hpos, *vpos, *area;
6642 int buffer_only_p;
6644 struct glyph *glyph, *end;
6645 struct glyph_row *row = NULL;
6646 int x0, i, left_area_width;
6648 /* Find row containing Y. Give up if some row is not enabled. */
6649 for (i = 0; i < w->current_matrix->nrows; ++i)
6651 row = MATRIX_ROW (w->current_matrix, i);
6652 if (!row->enabled_p)
6653 return NULL;
6654 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6655 break;
6658 *vpos = i;
6659 *hpos = 0;
6661 /* Give up if Y is not in the window. */
6662 if (i == w->current_matrix->nrows)
6663 return NULL;
6665 /* Get the glyph area containing X. */
6666 if (w->pseudo_window_p)
6668 *area = TEXT_AREA;
6669 x0 = 0;
6671 else
6673 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6674 if (x < left_area_width)
6676 *area = LEFT_MARGIN_AREA;
6677 x0 = 0;
6679 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6681 *area = TEXT_AREA;
6682 x0 = row->x + left_area_width;
6684 else
6686 *area = RIGHT_MARGIN_AREA;
6687 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6691 /* Find glyph containing X. */
6692 glyph = row->glyphs[*area];
6693 end = glyph + row->used[*area];
6694 while (glyph < end)
6696 if (x < x0 + glyph->pixel_width)
6698 if (w->pseudo_window_p)
6699 break;
6700 else if (!buffer_only_p || BUFFERP (glyph->object))
6701 break;
6704 x0 += glyph->pixel_width;
6705 ++glyph;
6708 if (glyph == end)
6709 return NULL;
6711 *hpos = glyph - row->glyphs[*area];
6712 return glyph;
6716 /* Convert frame-relative x/y to coordinates relative to window W.
6717 Takes pseudo-windows into account. */
6719 static void
6720 frame_to_window_pixel_xy (w, x, y)
6721 struct window *w;
6722 int *x, *y;
6724 if (w->pseudo_window_p)
6726 /* A pseudo-window is always full-width, and starts at the
6727 left edge of the frame, plus a frame border. */
6728 struct frame *f = XFRAME (w->frame);
6729 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6730 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6732 else
6734 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6735 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6740 /* Take proper action when mouse has moved to the mode or header line of
6741 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6742 mode line. X is relative to the start of the text display area of
6743 W, so the width of fringes and scroll bars must be subtracted
6744 to get a position relative to the start of the mode line. */
6746 static void
6747 note_mode_line_highlight (w, x, mode_line_p)
6748 struct window *w;
6749 int x, mode_line_p;
6751 struct frame *f = XFRAME (w->frame);
6752 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6753 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6754 struct glyph_row *row;
6756 if (mode_line_p)
6757 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6758 else
6759 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6761 if (row->enabled_p)
6763 struct glyph *glyph, *end;
6764 Lisp_Object help, map;
6765 int x0;
6767 /* Find the glyph under X. */
6768 glyph = row->glyphs[TEXT_AREA];
6769 end = glyph + row->used[TEXT_AREA];
6770 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6771 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6773 while (glyph < end
6774 && x >= x0 + glyph->pixel_width)
6776 x0 += glyph->pixel_width;
6777 ++glyph;
6780 if (glyph < end
6781 && STRINGP (glyph->object)
6782 && XSTRING (glyph->object)->intervals
6783 && glyph->charpos >= 0
6784 && glyph->charpos < XSTRING (glyph->object)->size)
6786 /* If we're on a string with `help-echo' text property,
6787 arrange for the help to be displayed. This is done by
6788 setting the global variable help_echo to the help string. */
6789 help = Fget_text_property (make_number (glyph->charpos),
6790 Qhelp_echo, glyph->object);
6791 if (!NILP (help))
6793 help_echo = help;
6794 XSETWINDOW (help_echo_window, w);
6795 help_echo_object = glyph->object;
6796 help_echo_pos = glyph->charpos;
6799 /* Change the mouse pointer according to what is under X/Y. */
6800 map = Fget_text_property (make_number (glyph->charpos),
6801 Qlocal_map, glyph->object);
6802 if (KEYMAPP (map))
6803 cursor = f->output_data.x->nontext_cursor;
6804 else
6806 map = Fget_text_property (make_number (glyph->charpos),
6807 Qkeymap, glyph->object);
6808 if (KEYMAPP (map))
6809 cursor = f->output_data.x->nontext_cursor;
6814 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6818 /* Take proper action when the mouse has moved to position X, Y on
6819 frame F as regards highlighting characters that have mouse-face
6820 properties. Also de-highlighting chars where the mouse was before.
6821 X and Y can be negative or out of range. */
6823 static void
6824 note_mouse_highlight (f, x, y)
6825 struct frame *f;
6826 int x, y;
6828 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6829 int portion;
6830 Lisp_Object window;
6831 struct window *w;
6832 Cursor cursor = None;
6833 struct buffer *b;
6835 /* When a menu is active, don't highlight because this looks odd. */
6836 #ifdef USE_X_TOOLKIT
6837 if (popup_activated ())
6838 return;
6839 #endif
6841 if (disable_mouse_highlight
6842 || !f->glyphs_initialized_p)
6843 return;
6845 dpyinfo->mouse_face_mouse_x = x;
6846 dpyinfo->mouse_face_mouse_y = y;
6847 dpyinfo->mouse_face_mouse_frame = f;
6849 if (dpyinfo->mouse_face_defer)
6850 return;
6852 if (gc_in_progress)
6854 dpyinfo->mouse_face_deferred_gc = 1;
6855 return;
6858 /* Which window is that in? */
6859 window = window_from_coordinates (f, x, y, &portion, 1);
6861 /* If we were displaying active text in another window, clear that. */
6862 if (! EQ (window, dpyinfo->mouse_face_window))
6863 clear_mouse_face (dpyinfo);
6865 /* Not on a window -> return. */
6866 if (!WINDOWP (window))
6867 return;
6869 /* Convert to window-relative pixel coordinates. */
6870 w = XWINDOW (window);
6871 frame_to_window_pixel_xy (w, &x, &y);
6873 /* Handle tool-bar window differently since it doesn't display a
6874 buffer. */
6875 if (EQ (window, f->tool_bar_window))
6877 note_tool_bar_highlight (f, x, y);
6878 return;
6881 /* Mouse is on the mode or header line? */
6882 if (portion == 1 || portion == 3)
6884 note_mode_line_highlight (w, x, portion == 1);
6885 return;
6888 if (portion == 2)
6889 cursor = f->output_data.x->horizontal_drag_cursor;
6890 else
6891 cursor = f->output_data.x->text_cursor;
6893 /* Are we in a window whose display is up to date?
6894 And verify the buffer's text has not changed. */
6895 b = XBUFFER (w->buffer);
6896 if (/* Within text portion of the window. */
6897 portion == 0
6898 && EQ (w->window_end_valid, w->buffer)
6899 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6900 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6902 int hpos, vpos, pos, i, area;
6903 struct glyph *glyph;
6904 Lisp_Object object;
6905 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6906 Lisp_Object *overlay_vec = NULL;
6907 int len, noverlays;
6908 struct buffer *obuf;
6909 int obegv, ozv, same_region;
6911 /* Find the glyph under X/Y. */
6912 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6914 /* Clear mouse face if X/Y not over text. */
6915 if (glyph == NULL
6916 || area != TEXT_AREA
6917 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6919 if (clear_mouse_face (dpyinfo))
6920 cursor = None;
6921 goto set_cursor;
6924 pos = glyph->charpos;
6925 object = glyph->object;
6926 if (!STRINGP (object) && !BUFFERP (object))
6927 goto set_cursor;
6929 /* If we get an out-of-range value, return now; avoid an error. */
6930 if (BUFFERP (object) && pos > BUF_Z (b))
6931 goto set_cursor;
6933 /* Make the window's buffer temporarily current for
6934 overlays_at and compute_char_face. */
6935 obuf = current_buffer;
6936 current_buffer = b;
6937 obegv = BEGV;
6938 ozv = ZV;
6939 BEGV = BEG;
6940 ZV = Z;
6942 /* Is this char mouse-active or does it have help-echo? */
6943 position = make_number (pos);
6945 if (BUFFERP (object))
6947 /* Put all the overlays we want in a vector in overlay_vec.
6948 Store the length in len. If there are more than 10, make
6949 enough space for all, and try again. */
6950 len = 10;
6951 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6952 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6953 if (noverlays > len)
6955 len = noverlays;
6956 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6957 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6960 /* Sort overlays into increasing priority order. */
6961 noverlays = sort_overlays (overlay_vec, noverlays, w);
6963 else
6964 noverlays = 0;
6966 same_region = (EQ (window, dpyinfo->mouse_face_window)
6967 && vpos >= dpyinfo->mouse_face_beg_row
6968 && vpos <= dpyinfo->mouse_face_end_row
6969 && (vpos > dpyinfo->mouse_face_beg_row
6970 || hpos >= dpyinfo->mouse_face_beg_col)
6971 && (vpos < dpyinfo->mouse_face_end_row
6972 || hpos < dpyinfo->mouse_face_end_col
6973 || dpyinfo->mouse_face_past_end));
6975 if (same_region)
6976 cursor = None;
6978 /* Check mouse-face highlighting. */
6979 if (! same_region
6980 /* If there exists an overlay with mouse-face overlapping
6981 the one we are currently highlighting, we have to
6982 check if we enter the overlapping overlay, and then
6983 highlight only that. */
6984 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6985 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6987 /* Find the highest priority overlay that has a mouse-face
6988 property. */
6989 overlay = Qnil;
6990 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6992 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6993 if (!NILP (mouse_face))
6994 overlay = overlay_vec[i];
6997 /* If we're actually highlighting the same overlay as
6998 before, there's no need to do that again. */
6999 if (!NILP (overlay)
7000 && EQ (overlay, dpyinfo->mouse_face_overlay))
7001 goto check_help_echo;
7003 dpyinfo->mouse_face_overlay = overlay;
7005 /* Clear the display of the old active region, if any. */
7006 if (clear_mouse_face (dpyinfo))
7007 cursor = None;
7009 /* If no overlay applies, get a text property. */
7010 if (NILP (overlay))
7011 mouse_face = Fget_text_property (position, Qmouse_face, object);
7013 /* Handle the overlay case. */
7014 if (!NILP (overlay))
7016 /* Find the range of text around this char that
7017 should be active. */
7018 Lisp_Object before, after;
7019 int ignore;
7021 before = Foverlay_start (overlay);
7022 after = Foverlay_end (overlay);
7023 /* Record this as the current active region. */
7024 fast_find_position (w, XFASTINT (before),
7025 &dpyinfo->mouse_face_beg_col,
7026 &dpyinfo->mouse_face_beg_row,
7027 &dpyinfo->mouse_face_beg_x,
7028 &dpyinfo->mouse_face_beg_y, Qnil);
7030 dpyinfo->mouse_face_past_end
7031 = !fast_find_position (w, XFASTINT (after),
7032 &dpyinfo->mouse_face_end_col,
7033 &dpyinfo->mouse_face_end_row,
7034 &dpyinfo->mouse_face_end_x,
7035 &dpyinfo->mouse_face_end_y, Qnil);
7036 dpyinfo->mouse_face_window = window;
7037 dpyinfo->mouse_face_face_id
7038 = face_at_buffer_position (w, pos, 0, 0,
7039 &ignore, pos + 1, 1);
7041 /* Display it as active. */
7042 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7043 cursor = None;
7045 /* Handle the text property case. */
7046 else if (!NILP (mouse_face) && BUFFERP (object))
7048 /* Find the range of text around this char that
7049 should be active. */
7050 Lisp_Object before, after, beginning, end;
7051 int ignore;
7053 beginning = Fmarker_position (w->start);
7054 end = make_number (BUF_Z (XBUFFER (object))
7055 - XFASTINT (w->window_end_pos));
7056 before
7057 = Fprevious_single_property_change (make_number (pos + 1),
7058 Qmouse_face,
7059 object, beginning);
7060 after
7061 = Fnext_single_property_change (position, Qmouse_face,
7062 object, end);
7064 /* Record this as the current active region. */
7065 fast_find_position (w, XFASTINT (before),
7066 &dpyinfo->mouse_face_beg_col,
7067 &dpyinfo->mouse_face_beg_row,
7068 &dpyinfo->mouse_face_beg_x,
7069 &dpyinfo->mouse_face_beg_y, Qnil);
7070 dpyinfo->mouse_face_past_end
7071 = !fast_find_position (w, XFASTINT (after),
7072 &dpyinfo->mouse_face_end_col,
7073 &dpyinfo->mouse_face_end_row,
7074 &dpyinfo->mouse_face_end_x,
7075 &dpyinfo->mouse_face_end_y, Qnil);
7076 dpyinfo->mouse_face_window = window;
7078 if (BUFFERP (object))
7079 dpyinfo->mouse_face_face_id
7080 = face_at_buffer_position (w, pos, 0, 0,
7081 &ignore, pos + 1, 1);
7083 /* Display it as active. */
7084 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7085 cursor = None;
7087 else if (!NILP (mouse_face) && STRINGP (object))
7089 Lisp_Object b, e;
7090 int ignore;
7092 b = Fprevious_single_property_change (make_number (pos + 1),
7093 Qmouse_face,
7094 object, Qnil);
7095 e = Fnext_single_property_change (position, Qmouse_face,
7096 object, Qnil);
7097 if (NILP (b))
7098 b = make_number (0);
7099 if (NILP (e))
7100 e = make_number (XSTRING (object)->size - 1);
7101 fast_find_string_pos (w, XINT (b), object,
7102 &dpyinfo->mouse_face_beg_col,
7103 &dpyinfo->mouse_face_beg_row,
7104 &dpyinfo->mouse_face_beg_x,
7105 &dpyinfo->mouse_face_beg_y, 0);
7106 fast_find_string_pos (w, XINT (e), object,
7107 &dpyinfo->mouse_face_end_col,
7108 &dpyinfo->mouse_face_end_row,
7109 &dpyinfo->mouse_face_end_x,
7110 &dpyinfo->mouse_face_end_y, 1);
7111 dpyinfo->mouse_face_past_end = 0;
7112 dpyinfo->mouse_face_window = window;
7113 dpyinfo->mouse_face_face_id
7114 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7115 glyph->face_id, 1);
7116 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7117 cursor = None;
7119 else if (STRINGP (object) && NILP (mouse_face))
7121 /* A string which doesn't have mouse-face, but
7122 the text ``under'' it might have. */
7123 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7124 int start = MATRIX_ROW_START_CHARPOS (r);
7126 pos = string_buffer_position (w, object, start);
7127 if (pos > 0)
7128 mouse_face = get_char_property_and_overlay (make_number (pos),
7129 Qmouse_face,
7130 w->buffer,
7131 &overlay);
7132 if (!NILP (mouse_face) && !NILP (overlay))
7134 Lisp_Object before = Foverlay_start (overlay);
7135 Lisp_Object after = Foverlay_end (overlay);
7136 int ignore;
7138 /* Note that we might not be able to find position
7139 BEFORE in the glyph matrix if the overlay is
7140 entirely covered by a `display' property. In
7141 this case, we overshoot. So let's stop in
7142 the glyph matrix before glyphs for OBJECT. */
7143 fast_find_position (w, XFASTINT (before),
7144 &dpyinfo->mouse_face_beg_col,
7145 &dpyinfo->mouse_face_beg_row,
7146 &dpyinfo->mouse_face_beg_x,
7147 &dpyinfo->mouse_face_beg_y,
7148 object);
7150 dpyinfo->mouse_face_past_end
7151 = !fast_find_position (w, XFASTINT (after),
7152 &dpyinfo->mouse_face_end_col,
7153 &dpyinfo->mouse_face_end_row,
7154 &dpyinfo->mouse_face_end_x,
7155 &dpyinfo->mouse_face_end_y,
7156 Qnil);
7157 dpyinfo->mouse_face_window = window;
7158 dpyinfo->mouse_face_face_id
7159 = face_at_buffer_position (w, pos, 0, 0,
7160 &ignore, pos + 1, 1);
7162 /* Display it as active. */
7163 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7164 cursor = None;
7169 check_help_echo:
7171 /* Look for a `help-echo' property. */
7173 Lisp_Object help, overlay;
7175 /* Check overlays first. */
7176 help = overlay = Qnil;
7177 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7179 overlay = overlay_vec[i];
7180 help = Foverlay_get (overlay, Qhelp_echo);
7183 if (!NILP (help))
7185 help_echo = help;
7186 help_echo_window = window;
7187 help_echo_object = overlay;
7188 help_echo_pos = pos;
7190 else
7192 Lisp_Object object = glyph->object;
7193 int charpos = glyph->charpos;
7195 /* Try text properties. */
7196 if (STRINGP (object)
7197 && charpos >= 0
7198 && charpos < XSTRING (object)->size)
7200 help = Fget_text_property (make_number (charpos),
7201 Qhelp_echo, object);
7202 if (NILP (help))
7204 /* If the string itself doesn't specify a help-echo,
7205 see if the buffer text ``under'' it does. */
7206 struct glyph_row *r
7207 = MATRIX_ROW (w->current_matrix, vpos);
7208 int start = MATRIX_ROW_START_CHARPOS (r);
7209 int pos = string_buffer_position (w, object, start);
7210 if (pos > 0)
7212 help = Fget_char_property (make_number (pos),
7213 Qhelp_echo, w->buffer);
7214 if (!NILP (help))
7216 charpos = pos;
7217 object = w->buffer;
7222 else if (BUFFERP (object)
7223 && charpos >= BEGV
7224 && charpos < ZV)
7225 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7226 object);
7228 if (!NILP (help))
7230 help_echo = help;
7231 help_echo_window = window;
7232 help_echo_object = object;
7233 help_echo_pos = charpos;
7238 BEGV = obegv;
7239 ZV = ozv;
7240 current_buffer = obuf;
7243 set_cursor:
7245 if (cursor != None)
7246 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7249 static void
7250 redo_mouse_highlight ()
7252 if (!NILP (last_mouse_motion_frame)
7253 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7254 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7255 last_mouse_motion_event.x,
7256 last_mouse_motion_event.y);
7261 /***********************************************************************
7262 Tool-bars
7263 ***********************************************************************/
7265 static int x_tool_bar_item P_ ((struct frame *, int, int,
7266 struct glyph **, int *, int *, int *));
7268 /* Tool-bar item index of the item on which a mouse button was pressed
7269 or -1. */
7271 static int last_tool_bar_item;
7274 /* Get information about the tool-bar item at position X/Y on frame F.
7275 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7276 the current matrix of the tool-bar window of F, or NULL if not
7277 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7278 item in F->tool_bar_items. Value is
7280 -1 if X/Y is not on a tool-bar item
7281 0 if X/Y is on the same item that was highlighted before.
7282 1 otherwise. */
7284 static int
7285 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7286 struct frame *f;
7287 int x, y;
7288 struct glyph **glyph;
7289 int *hpos, *vpos, *prop_idx;
7291 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7292 struct window *w = XWINDOW (f->tool_bar_window);
7293 int area;
7295 /* Find the glyph under X/Y. */
7296 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7297 if (*glyph == NULL)
7298 return -1;
7300 /* Get the start of this tool-bar item's properties in
7301 f->tool_bar_items. */
7302 if (!tool_bar_item_info (f, *glyph, prop_idx))
7303 return -1;
7305 /* Is mouse on the highlighted item? */
7306 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7307 && *vpos >= dpyinfo->mouse_face_beg_row
7308 && *vpos <= dpyinfo->mouse_face_end_row
7309 && (*vpos > dpyinfo->mouse_face_beg_row
7310 || *hpos >= dpyinfo->mouse_face_beg_col)
7311 && (*vpos < dpyinfo->mouse_face_end_row
7312 || *hpos < dpyinfo->mouse_face_end_col
7313 || dpyinfo->mouse_face_past_end))
7314 return 0;
7316 return 1;
7320 /* Handle mouse button event on the tool-bar of frame F, at
7321 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7322 or ButtonRelase. */
7324 static void
7325 x_handle_tool_bar_click (f, button_event)
7326 struct frame *f;
7327 XButtonEvent *button_event;
7329 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7330 struct window *w = XWINDOW (f->tool_bar_window);
7331 int hpos, vpos, prop_idx;
7332 struct glyph *glyph;
7333 Lisp_Object enabled_p;
7334 int x = button_event->x;
7335 int y = button_event->y;
7337 /* If not on the highlighted tool-bar item, return. */
7338 frame_to_window_pixel_xy (w, &x, &y);
7339 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7340 return;
7342 /* If item is disabled, do nothing. */
7343 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7344 if (NILP (enabled_p))
7345 return;
7347 if (button_event->type == ButtonPress)
7349 /* Show item in pressed state. */
7350 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7351 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7352 last_tool_bar_item = prop_idx;
7354 else
7356 Lisp_Object key, frame;
7357 struct input_event event;
7359 /* Show item in released state. */
7360 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7361 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7363 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7365 XSETFRAME (frame, f);
7366 event.kind = TOOL_BAR_EVENT;
7367 event.frame_or_window = frame;
7368 event.arg = frame;
7369 kbd_buffer_store_event (&event);
7371 event.kind = TOOL_BAR_EVENT;
7372 event.frame_or_window = frame;
7373 event.arg = key;
7374 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7375 button_event->state);
7376 kbd_buffer_store_event (&event);
7377 last_tool_bar_item = -1;
7382 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7383 tool-bar window-relative coordinates X/Y. Called from
7384 note_mouse_highlight. */
7386 static void
7387 note_tool_bar_highlight (f, x, y)
7388 struct frame *f;
7389 int x, y;
7391 Lisp_Object window = f->tool_bar_window;
7392 struct window *w = XWINDOW (window);
7393 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7394 int hpos, vpos;
7395 struct glyph *glyph;
7396 struct glyph_row *row;
7397 int i;
7398 Lisp_Object enabled_p;
7399 int prop_idx;
7400 enum draw_glyphs_face draw;
7401 int mouse_down_p, rc;
7403 /* Function note_mouse_highlight is called with negative x(y
7404 values when mouse moves outside of the frame. */
7405 if (x <= 0 || y <= 0)
7407 clear_mouse_face (dpyinfo);
7408 return;
7411 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7412 if (rc < 0)
7414 /* Not on tool-bar item. */
7415 clear_mouse_face (dpyinfo);
7416 return;
7418 else if (rc == 0)
7419 goto set_help_echo;
7421 clear_mouse_face (dpyinfo);
7423 /* Mouse is down, but on different tool-bar item? */
7424 mouse_down_p = (dpyinfo->grabbed
7425 && f == last_mouse_frame
7426 && FRAME_LIVE_P (f));
7427 if (mouse_down_p
7428 && last_tool_bar_item != prop_idx)
7429 return;
7431 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7432 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7434 /* If tool-bar item is not enabled, don't highlight it. */
7435 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7436 if (!NILP (enabled_p))
7438 /* Compute the x-position of the glyph. In front and past the
7439 image is a space. We include this is the highlighted area. */
7440 row = MATRIX_ROW (w->current_matrix, vpos);
7441 for (i = x = 0; i < hpos; ++i)
7442 x += row->glyphs[TEXT_AREA][i].pixel_width;
7444 /* Record this as the current active region. */
7445 dpyinfo->mouse_face_beg_col = hpos;
7446 dpyinfo->mouse_face_beg_row = vpos;
7447 dpyinfo->mouse_face_beg_x = x;
7448 dpyinfo->mouse_face_beg_y = row->y;
7449 dpyinfo->mouse_face_past_end = 0;
7451 dpyinfo->mouse_face_end_col = hpos + 1;
7452 dpyinfo->mouse_face_end_row = vpos;
7453 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7454 dpyinfo->mouse_face_end_y = row->y;
7455 dpyinfo->mouse_face_window = window;
7456 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7458 /* Display it as active. */
7459 show_mouse_face (dpyinfo, draw);
7460 dpyinfo->mouse_face_image_state = draw;
7463 set_help_echo:
7465 /* Set help_echo to a help string.to display for this tool-bar item.
7466 XTread_socket does the rest. */
7467 help_echo_object = help_echo_window = Qnil;
7468 help_echo_pos = -1;
7469 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7470 if (NILP (help_echo))
7471 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7476 /* Find the glyph matrix position of buffer position CHARPOS in window
7477 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7478 current glyphs must be up to date. If CHARPOS is above window
7479 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7480 of last line in W. In the row containing CHARPOS, stop before glyphs
7481 having STOP as object. */
7483 #if 0 /* This is a version of fast_find_position that's more correct
7484 in the presence of hscrolling, for example. I didn't install
7485 it right away because the problem fixed is minor, it failed
7486 in 20.x as well, and I think it's too risky to install
7487 so near the release of 21.1. 2001-09-25 gerd. */
7489 static int
7490 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7491 struct window *w;
7492 int charpos;
7493 int *hpos, *vpos, *x, *y;
7494 Lisp_Object stop;
7496 struct glyph_row *row, *first;
7497 struct glyph *glyph, *end;
7498 int i, past_end = 0;
7500 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7501 row = row_containing_pos (w, charpos, first, NULL, 0);
7502 if (row == NULL)
7504 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7506 *x = *y = *hpos = *vpos = 0;
7507 return 0;
7509 else
7511 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7512 past_end = 1;
7516 *x = row->x;
7517 *y = row->y;
7518 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7520 glyph = row->glyphs[TEXT_AREA];
7521 end = glyph + row->used[TEXT_AREA];
7523 /* Skip over glyphs not having an object at the start of the row.
7524 These are special glyphs like truncation marks on terminal
7525 frames. */
7526 if (row->displays_text_p)
7527 while (glyph < end
7528 && INTEGERP (glyph->object)
7529 && !EQ (stop, glyph->object)
7530 && glyph->charpos < 0)
7532 *x += glyph->pixel_width;
7533 ++glyph;
7536 while (glyph < end
7537 && !INTEGERP (glyph->object)
7538 && !EQ (stop, glyph->object)
7539 && (!BUFFERP (glyph->object)
7540 || glyph->charpos < charpos))
7542 *x += glyph->pixel_width;
7543 ++glyph;
7546 *hpos = glyph - row->glyphs[TEXT_AREA];
7547 return past_end;
7550 #else /* not 0 */
7552 static int
7553 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7554 struct window *w;
7555 int pos;
7556 int *hpos, *vpos, *x, *y;
7557 Lisp_Object stop;
7559 int i;
7560 int lastcol;
7561 int maybe_next_line_p = 0;
7562 int line_start_position;
7563 int yb = window_text_bottom_y (w);
7564 struct glyph_row *row, *best_row;
7565 int row_vpos, best_row_vpos;
7566 int current_x;
7568 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7569 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7571 while (row->y < yb)
7573 if (row->used[TEXT_AREA])
7574 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7575 else
7576 line_start_position = 0;
7578 if (line_start_position > pos)
7579 break;
7580 /* If the position sought is the end of the buffer,
7581 don't include the blank lines at the bottom of the window. */
7582 else if (line_start_position == pos
7583 && pos == BUF_ZV (XBUFFER (w->buffer)))
7585 maybe_next_line_p = 1;
7586 break;
7588 else if (line_start_position > 0)
7590 best_row = row;
7591 best_row_vpos = row_vpos;
7594 if (row->y + row->height >= yb)
7595 break;
7597 ++row;
7598 ++row_vpos;
7601 /* Find the right column within BEST_ROW. */
7602 lastcol = 0;
7603 current_x = best_row->x;
7604 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7606 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7607 int charpos = glyph->charpos;
7609 if (BUFFERP (glyph->object))
7611 if (charpos == pos)
7613 *hpos = i;
7614 *vpos = best_row_vpos;
7615 *x = current_x;
7616 *y = best_row->y;
7617 return 1;
7619 else if (charpos > pos)
7620 break;
7622 else if (EQ (glyph->object, stop))
7623 break;
7625 if (charpos > 0)
7626 lastcol = i;
7627 current_x += glyph->pixel_width;
7630 /* If we're looking for the end of the buffer,
7631 and we didn't find it in the line we scanned,
7632 use the start of the following line. */
7633 if (maybe_next_line_p)
7635 ++best_row;
7636 ++best_row_vpos;
7637 lastcol = 0;
7638 current_x = best_row->x;
7641 *vpos = best_row_vpos;
7642 *hpos = lastcol + 1;
7643 *x = current_x;
7644 *y = best_row->y;
7645 return 0;
7648 #endif /* not 0 */
7651 /* Find the position of the the glyph for position POS in OBJECT in
7652 window W's current matrix, and return in *X/*Y the pixel
7653 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7655 RIGHT_P non-zero means return the position of the right edge of the
7656 glyph, RIGHT_P zero means return the left edge position.
7658 If no glyph for POS exists in the matrix, return the position of
7659 the glyph with the next smaller position that is in the matrix, if
7660 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7661 exists in the matrix, return the position of the glyph with the
7662 next larger position in OBJECT.
7664 Value is non-zero if a glyph was found. */
7666 static int
7667 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7668 struct window *w;
7669 int pos;
7670 Lisp_Object object;
7671 int *hpos, *vpos, *x, *y;
7672 int right_p;
7674 int yb = window_text_bottom_y (w);
7675 struct glyph_row *r;
7676 struct glyph *best_glyph = NULL;
7677 struct glyph_row *best_row = NULL;
7678 int best_x = 0;
7680 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7681 r->enabled_p && r->y < yb;
7682 ++r)
7684 struct glyph *g = r->glyphs[TEXT_AREA];
7685 struct glyph *e = g + r->used[TEXT_AREA];
7686 int gx;
7688 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7689 if (EQ (g->object, object))
7691 if (g->charpos == pos)
7693 best_glyph = g;
7694 best_x = gx;
7695 best_row = r;
7696 goto found;
7698 else if (best_glyph == NULL
7699 || ((abs (g->charpos - pos)
7700 < abs (best_glyph->charpos - pos))
7701 && (right_p
7702 ? g->charpos < pos
7703 : g->charpos > pos)))
7705 best_glyph = g;
7706 best_x = gx;
7707 best_row = r;
7712 found:
7714 if (best_glyph)
7716 *x = best_x;
7717 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7719 if (right_p)
7721 *x += best_glyph->pixel_width;
7722 ++*hpos;
7725 *y = best_row->y;
7726 *vpos = best_row - w->current_matrix->rows;
7729 return best_glyph != NULL;
7733 /* Display the active region described by mouse_face_*
7734 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7736 static void
7737 show_mouse_face (dpyinfo, draw)
7738 struct x_display_info *dpyinfo;
7739 enum draw_glyphs_face draw;
7741 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7742 struct frame *f = XFRAME (WINDOW_FRAME (w));
7744 if (/* If window is in the process of being destroyed, don't bother
7745 to do anything. */
7746 w->current_matrix != NULL
7747 /* Recognize when we are called to operate on rows that don't exist
7748 anymore. This can happen when a window is split. */
7749 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7751 int phys_cursor_on_p = w->phys_cursor_on_p;
7752 struct glyph_row *row, *first, *last;
7754 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7755 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7757 for (row = first; row <= last && row->enabled_p; ++row)
7759 int start_hpos, end_hpos, start_x;
7761 /* For all but the first row, the highlight starts at column 0. */
7762 if (row == first)
7764 start_hpos = dpyinfo->mouse_face_beg_col;
7765 start_x = dpyinfo->mouse_face_beg_x;
7767 else
7769 start_hpos = 0;
7770 start_x = 0;
7773 if (row == last)
7774 end_hpos = dpyinfo->mouse_face_end_col;
7775 else
7776 end_hpos = row->used[TEXT_AREA];
7778 if (end_hpos > start_hpos)
7780 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7781 start_hpos, end_hpos, draw, 0);
7783 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7787 /* When we've written over the cursor, arrange for it to
7788 be displayed again. */
7789 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7790 x_display_cursor (w, 1,
7791 w->phys_cursor.hpos, w->phys_cursor.vpos,
7792 w->phys_cursor.x, w->phys_cursor.y);
7795 /* Change the mouse cursor. */
7796 if (draw == DRAW_NORMAL_TEXT)
7797 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7798 f->output_data.x->text_cursor);
7799 else if (draw == DRAW_MOUSE_FACE)
7800 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7801 f->output_data.x->cross_cursor);
7802 else
7803 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7804 f->output_data.x->nontext_cursor);
7807 /* Clear out the mouse-highlighted active region.
7808 Redraw it un-highlighted first. Value is non-zero if mouse
7809 face was actually drawn unhighlighted. */
7811 static int
7812 clear_mouse_face (dpyinfo)
7813 struct x_display_info *dpyinfo;
7815 int cleared = 0;
7817 if (!NILP (dpyinfo->mouse_face_window))
7819 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7820 cleared = 1;
7823 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7824 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7825 dpyinfo->mouse_face_window = Qnil;
7826 dpyinfo->mouse_face_overlay = Qnil;
7827 return cleared;
7831 /* Clear any mouse-face on window W. This function is part of the
7832 redisplay interface, and is called from try_window_id and similar
7833 functions to ensure the mouse-highlight is off. */
7835 static void
7836 x_clear_mouse_face (w)
7837 struct window *w;
7839 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7840 Lisp_Object window;
7842 BLOCK_INPUT;
7843 XSETWINDOW (window, w);
7844 if (EQ (window, dpyinfo->mouse_face_window))
7845 clear_mouse_face (dpyinfo);
7846 UNBLOCK_INPUT;
7850 /* Just discard the mouse face information for frame F, if any.
7851 This is used when the size of F is changed. */
7853 void
7854 cancel_mouse_face (f)
7855 FRAME_PTR f;
7857 Lisp_Object window;
7858 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7860 window = dpyinfo->mouse_face_window;
7861 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7863 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7864 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7865 dpyinfo->mouse_face_window = Qnil;
7870 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7873 /* Try to determine frame pixel position and size of the glyph under
7874 frame pixel coordinates X/Y on frame F . Return the position and
7875 size in *RECT. Value is non-zero if we could compute these
7876 values. */
7878 static int
7879 glyph_rect (f, x, y, rect)
7880 struct frame *f;
7881 int x, y;
7882 XRectangle *rect;
7884 Lisp_Object window;
7885 int part, found = 0;
7887 window = window_from_coordinates (f, x, y, &part, 0);
7888 if (!NILP (window))
7890 struct window *w = XWINDOW (window);
7891 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7892 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7894 frame_to_window_pixel_xy (w, &x, &y);
7896 for (; !found && r < end && r->enabled_p; ++r)
7897 if (r->y >= y)
7899 struct glyph *g = r->glyphs[TEXT_AREA];
7900 struct glyph *end = g + r->used[TEXT_AREA];
7901 int gx;
7903 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7904 if (gx >= x)
7906 rect->width = g->pixel_width;
7907 rect->height = r->height;
7908 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7909 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7910 found = 1;
7915 return found;
7919 /* Return the current position of the mouse.
7920 *FP should be a frame which indicates which display to ask about.
7922 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7923 and *PART to the frame, window, and scroll bar part that the mouse
7924 is over. Set *X and *Y to the portion and whole of the mouse's
7925 position on the scroll bar.
7927 If the mouse movement started elsewhere, set *FP to the frame the
7928 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7929 the mouse is over.
7931 Set *TIME to the server time-stamp for the time at which the mouse
7932 was at this position.
7934 Don't store anything if we don't have a valid set of values to report.
7936 This clears the mouse_moved flag, so we can wait for the next mouse
7937 movement. */
7939 static void
7940 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7941 FRAME_PTR *fp;
7942 int insist;
7943 Lisp_Object *bar_window;
7944 enum scroll_bar_part *part;
7945 Lisp_Object *x, *y;
7946 unsigned long *time;
7948 FRAME_PTR f1;
7950 BLOCK_INPUT;
7952 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7953 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7954 else
7956 Window root;
7957 int root_x, root_y;
7959 Window dummy_window;
7960 int dummy;
7962 Lisp_Object frame, tail;
7964 /* Clear the mouse-moved flag for every frame on this display. */
7965 FOR_EACH_FRAME (tail, frame)
7966 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7967 XFRAME (frame)->mouse_moved = 0;
7969 last_mouse_scroll_bar = Qnil;
7971 /* Figure out which root window we're on. */
7972 XQueryPointer (FRAME_X_DISPLAY (*fp),
7973 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7975 /* The root window which contains the pointer. */
7976 &root,
7978 /* Trash which we can't trust if the pointer is on
7979 a different screen. */
7980 &dummy_window,
7982 /* The position on that root window. */
7983 &root_x, &root_y,
7985 /* More trash we can't trust. */
7986 &dummy, &dummy,
7988 /* Modifier keys and pointer buttons, about which
7989 we don't care. */
7990 (unsigned int *) &dummy);
7992 /* Now we have a position on the root; find the innermost window
7993 containing the pointer. */
7995 Window win, child;
7996 int win_x, win_y;
7997 int parent_x = 0, parent_y = 0;
7998 int count;
8000 win = root;
8002 /* XTranslateCoordinates can get errors if the window
8003 structure is changing at the same time this function
8004 is running. So at least we must not crash from them. */
8006 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8008 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8009 && FRAME_LIVE_P (last_mouse_frame))
8011 /* If mouse was grabbed on a frame, give coords for that frame
8012 even if the mouse is now outside it. */
8013 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8015 /* From-window, to-window. */
8016 root, FRAME_X_WINDOW (last_mouse_frame),
8018 /* From-position, to-position. */
8019 root_x, root_y, &win_x, &win_y,
8021 /* Child of win. */
8022 &child);
8023 f1 = last_mouse_frame;
8025 else
8027 while (1)
8029 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8031 /* From-window, to-window. */
8032 root, win,
8034 /* From-position, to-position. */
8035 root_x, root_y, &win_x, &win_y,
8037 /* Child of win. */
8038 &child);
8040 if (child == None || child == win)
8041 break;
8043 win = child;
8044 parent_x = win_x;
8045 parent_y = win_y;
8048 /* Now we know that:
8049 win is the innermost window containing the pointer
8050 (XTC says it has no child containing the pointer),
8051 win_x and win_y are the pointer's position in it
8052 (XTC did this the last time through), and
8053 parent_x and parent_y are the pointer's position in win's parent.
8054 (They are what win_x and win_y were when win was child.
8055 If win is the root window, it has no parent, and
8056 parent_{x,y} are invalid, but that's okay, because we'll
8057 never use them in that case.) */
8059 /* Is win one of our frames? */
8060 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8062 #ifdef USE_X_TOOLKIT
8063 /* If we end up with the menu bar window, say it's not
8064 on the frame. */
8065 if (f1 != NULL
8066 && f1->output_data.x->menubar_widget
8067 && win == XtWindow (f1->output_data.x->menubar_widget))
8068 f1 = NULL;
8069 #endif /* USE_X_TOOLKIT */
8072 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8073 f1 = 0;
8075 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8077 /* If not, is it one of our scroll bars? */
8078 if (! f1)
8080 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8082 if (bar)
8084 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8085 win_x = parent_x;
8086 win_y = parent_y;
8090 if (f1 == 0 && insist > 0)
8091 f1 = SELECTED_FRAME ();
8093 if (f1)
8095 /* Ok, we found a frame. Store all the values.
8096 last_mouse_glyph is a rectangle used to reduce the
8097 generation of mouse events. To not miss any motion
8098 events, we must divide the frame into rectangles of the
8099 size of the smallest character that could be displayed
8100 on it, i.e. into the same rectangles that matrices on
8101 the frame are divided into. */
8103 int width, height, gx, gy;
8104 XRectangle rect;
8106 if (glyph_rect (f1, win_x, win_y, &rect))
8107 last_mouse_glyph = rect;
8108 else
8110 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8111 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8112 gx = win_x;
8113 gy = win_y;
8115 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8116 round down even for negative values. */
8117 if (gx < 0)
8118 gx -= width - 1;
8119 if (gy < 0)
8120 gy -= height - 1;
8121 gx = (gx + width - 1) / width * width;
8122 gy = (gy + height - 1) / height * height;
8124 last_mouse_glyph.width = width;
8125 last_mouse_glyph.height = height;
8126 last_mouse_glyph.x = gx;
8127 last_mouse_glyph.y = gy;
8130 *bar_window = Qnil;
8131 *part = 0;
8132 *fp = f1;
8133 XSETINT (*x, win_x);
8134 XSETINT (*y, win_y);
8135 *time = last_mouse_movement_time;
8140 UNBLOCK_INPUT;
8144 #ifdef USE_X_TOOLKIT
8146 /* Atimer callback function for TIMER. Called every 0.1s to process
8147 Xt timeouts, if needed. We must avoid calling XtAppPending as
8148 much as possible because that function does an implicit XFlush
8149 that slows us down. */
8151 static void
8152 x_process_timeouts (timer)
8153 struct atimer *timer;
8155 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8157 BLOCK_INPUT;
8158 while (XtAppPending (Xt_app_con) & XtIMTimer)
8159 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8160 UNBLOCK_INPUT;
8164 #endif /* USE_X_TOOLKIT */
8167 /* Scroll bar support. */
8169 /* Given an X window ID, find the struct scroll_bar which manages it.
8170 This can be called in GC, so we have to make sure to strip off mark
8171 bits. */
8173 static struct scroll_bar *
8174 x_window_to_scroll_bar (window_id)
8175 Window window_id;
8177 Lisp_Object tail;
8179 for (tail = Vframe_list;
8180 XGCTYPE (tail) == Lisp_Cons;
8181 tail = XCDR (tail))
8183 Lisp_Object frame, bar, condemned;
8185 frame = XCAR (tail);
8186 /* All elements of Vframe_list should be frames. */
8187 if (! GC_FRAMEP (frame))
8188 abort ();
8190 /* Scan this frame's scroll bar list for a scroll bar with the
8191 right window ID. */
8192 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8193 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8194 /* This trick allows us to search both the ordinary and
8195 condemned scroll bar lists with one loop. */
8196 ! GC_NILP (bar) || (bar = condemned,
8197 condemned = Qnil,
8198 ! GC_NILP (bar));
8199 bar = XSCROLL_BAR (bar)->next)
8200 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8201 return XSCROLL_BAR (bar);
8204 return 0;
8208 #if defined USE_LUCID
8210 /* Return the Lucid menu bar WINDOW is part of. Return null
8211 if WINDOW is not part of a menu bar. */
8213 static Widget
8214 x_window_to_menu_bar (window)
8215 Window window;
8217 Lisp_Object tail;
8219 for (tail = Vframe_list;
8220 XGCTYPE (tail) == Lisp_Cons;
8221 tail = XCDR (tail))
8223 Lisp_Object frame = XCAR (tail);
8224 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8226 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8227 return menu_bar;
8230 return NULL;
8233 #endif /* USE_LUCID */
8236 /************************************************************************
8237 Toolkit scroll bars
8238 ************************************************************************/
8240 #ifdef USE_TOOLKIT_SCROLL_BARS
8242 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8243 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8244 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8245 struct scroll_bar *));
8246 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8247 int, int, int));
8250 /* Id of action hook installed for scroll bars. */
8252 static XtActionHookId action_hook_id;
8254 /* Lisp window being scrolled. Set when starting to interact with
8255 a toolkit scroll bar, reset to nil when ending the interaction. */
8257 static Lisp_Object window_being_scrolled;
8259 /* Last scroll bar part sent in xm_scroll_callback. */
8261 static int last_scroll_bar_part;
8263 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8264 that movements of 1/20 of the screen size are mapped to up/down. */
8266 static Boolean xaw3d_arrow_scroll;
8268 /* Whether the drag scrolling maintains the mouse at the top of the
8269 thumb. If not, resizing the thumb needs to be done more carefully
8270 to avoid jerkyness. */
8272 static Boolean xaw3d_pick_top;
8275 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8276 bars are used.. The hook is responsible for detecting when
8277 the user ends an interaction with the scroll bar, and generates
8278 a `end-scroll' scroll_bar_click' event if so. */
8280 static void
8281 xt_action_hook (widget, client_data, action_name, event, params,
8282 num_params)
8283 Widget widget;
8284 XtPointer client_data;
8285 String action_name;
8286 XEvent *event;
8287 String *params;
8288 Cardinal *num_params;
8290 int scroll_bar_p;
8291 char *end_action;
8293 #ifdef USE_MOTIF
8294 scroll_bar_p = XmIsScrollBar (widget);
8295 end_action = "Release";
8296 #else /* !USE_MOTIF i.e. use Xaw */
8297 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8298 end_action = "EndScroll";
8299 #endif /* USE_MOTIF */
8301 if (scroll_bar_p
8302 && strcmp (action_name, end_action) == 0
8303 && WINDOWP (window_being_scrolled))
8305 struct window *w;
8307 x_send_scroll_bar_event (window_being_scrolled,
8308 scroll_bar_end_scroll, 0, 0);
8309 w = XWINDOW (window_being_scrolled);
8310 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8311 window_being_scrolled = Qnil;
8312 last_scroll_bar_part = -1;
8314 /* Xt timeouts no longer needed. */
8315 toolkit_scroll_bar_interaction = 0;
8319 /* A vector of windows used for communication between
8320 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8322 static struct window **scroll_bar_windows;
8323 static int scroll_bar_windows_size;
8326 /* Send a client message with message type Xatom_Scrollbar for a
8327 scroll action to the frame of WINDOW. PART is a value identifying
8328 the part of the scroll bar that was clicked on. PORTION is the
8329 amount to scroll of a whole of WHOLE. */
8331 static void
8332 x_send_scroll_bar_event (window, part, portion, whole)
8333 Lisp_Object window;
8334 int part, portion, whole;
8336 XEvent event;
8337 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8338 struct window *w = XWINDOW (window);
8339 struct frame *f = XFRAME (w->frame);
8340 int i;
8342 BLOCK_INPUT;
8344 /* Construct a ClientMessage event to send to the frame. */
8345 ev->type = ClientMessage;
8346 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8347 ev->display = FRAME_X_DISPLAY (f);
8348 ev->window = FRAME_X_WINDOW (f);
8349 ev->format = 32;
8351 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8352 not enough to store a pointer or Lisp_Object on a 64 bit system.
8353 So, store the window in scroll_bar_windows and pass the index
8354 into that array in the event. */
8355 for (i = 0; i < scroll_bar_windows_size; ++i)
8356 if (scroll_bar_windows[i] == NULL)
8357 break;
8359 if (i == scroll_bar_windows_size)
8361 int new_size = max (10, 2 * scroll_bar_windows_size);
8362 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8363 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8365 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8366 nbytes);
8367 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8368 scroll_bar_windows_size = new_size;
8371 scroll_bar_windows[i] = w;
8372 ev->data.l[0] = (long) i;
8373 ev->data.l[1] = (long) part;
8374 ev->data.l[2] = (long) 0;
8375 ev->data.l[3] = (long) portion;
8376 ev->data.l[4] = (long) whole;
8378 /* Make Xt timeouts work while the scroll bar is active. */
8379 toolkit_scroll_bar_interaction = 1;
8381 /* Setting the event mask to zero means that the message will
8382 be sent to the client that created the window, and if that
8383 window no longer exists, no event will be sent. */
8384 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8385 UNBLOCK_INPUT;
8389 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8390 in *IEVENT. */
8392 static void
8393 x_scroll_bar_to_input_event (event, ievent)
8394 XEvent *event;
8395 struct input_event *ievent;
8397 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8398 Lisp_Object window;
8399 struct frame *f;
8400 struct window *w;
8402 w = scroll_bar_windows[ev->data.l[0]];
8403 scroll_bar_windows[ev->data.l[0]] = NULL;
8405 XSETWINDOW (window, w);
8406 f = XFRAME (w->frame);
8408 ievent->kind = scroll_bar_click;
8409 ievent->frame_or_window = window;
8410 ievent->arg = Qnil;
8411 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8412 ievent->part = ev->data.l[1];
8413 ievent->code = ev->data.l[2];
8414 ievent->x = make_number ((int) ev->data.l[3]);
8415 ievent->y = make_number ((int) ev->data.l[4]);
8416 ievent->modifiers = 0;
8420 #ifdef USE_MOTIF
8422 /* Minimum and maximum values used for Motif scroll bars. */
8424 #define XM_SB_MIN 1
8425 #define XM_SB_MAX 10000000
8426 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8429 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8430 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8431 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8433 static void
8434 xm_scroll_callback (widget, client_data, call_data)
8435 Widget widget;
8436 XtPointer client_data, call_data;
8438 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8439 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8440 int part = -1, whole = 0, portion = 0;
8442 switch (cs->reason)
8444 case XmCR_DECREMENT:
8445 bar->dragging = Qnil;
8446 part = scroll_bar_up_arrow;
8447 break;
8449 case XmCR_INCREMENT:
8450 bar->dragging = Qnil;
8451 part = scroll_bar_down_arrow;
8452 break;
8454 case XmCR_PAGE_DECREMENT:
8455 bar->dragging = Qnil;
8456 part = scroll_bar_above_handle;
8457 break;
8459 case XmCR_PAGE_INCREMENT:
8460 bar->dragging = Qnil;
8461 part = scroll_bar_below_handle;
8462 break;
8464 case XmCR_TO_TOP:
8465 bar->dragging = Qnil;
8466 part = scroll_bar_to_top;
8467 break;
8469 case XmCR_TO_BOTTOM:
8470 bar->dragging = Qnil;
8471 part = scroll_bar_to_bottom;
8472 break;
8474 case XmCR_DRAG:
8476 int slider_size;
8477 int dragging_down_p = (INTEGERP (bar->dragging)
8478 && XINT (bar->dragging) <= cs->value);
8480 /* Get the slider size. */
8481 BLOCK_INPUT;
8482 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8483 UNBLOCK_INPUT;
8485 /* At the max position of the scroll bar, do a line-wise
8486 movement. Without doing anything, we would be called with
8487 the same cs->value again and again. If we want to make
8488 sure that we can reach the end of the buffer, we have to do
8489 something.
8491 Implementation note: setting bar->dragging always to
8492 cs->value gives a smoother movement at the max position.
8493 Setting it to nil when doing line-wise movement gives
8494 a better slider behavior. */
8496 if (cs->value + slider_size == XM_SB_MAX
8497 || (dragging_down_p
8498 && last_scroll_bar_part == scroll_bar_down_arrow))
8500 part = scroll_bar_down_arrow;
8501 bar->dragging = Qnil;
8503 else
8505 whole = XM_SB_RANGE;
8506 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8507 part = scroll_bar_handle;
8508 bar->dragging = make_number (cs->value);
8511 break;
8513 case XmCR_VALUE_CHANGED:
8514 break;
8517 if (part >= 0)
8519 window_being_scrolled = bar->window;
8520 last_scroll_bar_part = part;
8521 x_send_scroll_bar_event (bar->window, part, portion, whole);
8526 #else /* !USE_MOTIF, i.e. Xaw. */
8529 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8530 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8531 scroll bar struct. CALL_DATA is a pointer to a float saying where
8532 the thumb is. */
8534 static void
8535 xaw_jump_callback (widget, client_data, call_data)
8536 Widget widget;
8537 XtPointer client_data, call_data;
8539 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8540 float top = *(float *) call_data;
8541 float shown;
8542 int whole, portion, height;
8543 int part;
8545 /* Get the size of the thumb, a value between 0 and 1. */
8546 BLOCK_INPUT;
8547 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8548 UNBLOCK_INPUT;
8550 whole = 10000000;
8551 portion = shown < 1 ? top * whole : 0;
8553 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8554 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8555 the bottom, so we force the scrolling whenever we see that we're
8556 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8557 we try to ensure that we always stay two pixels away from the
8558 bottom). */
8559 part = scroll_bar_down_arrow;
8560 else
8561 part = scroll_bar_handle;
8563 window_being_scrolled = bar->window;
8564 bar->dragging = make_number (portion);
8565 last_scroll_bar_part = part;
8566 x_send_scroll_bar_event (bar->window, part, portion, whole);
8570 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8571 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8572 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8573 the scroll bar. CALL_DATA is an integer specifying the action that
8574 has taken place. It's magnitude is in the range 0..height of the
8575 scroll bar. Negative values mean scroll towards buffer start.
8576 Values < height of scroll bar mean line-wise movement. */
8578 static void
8579 xaw_scroll_callback (widget, client_data, call_data)
8580 Widget widget;
8581 XtPointer client_data, call_data;
8583 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8584 int position = (int) call_data;
8585 Dimension height;
8586 int part;
8588 /* Get the height of the scroll bar. */
8589 BLOCK_INPUT;
8590 XtVaGetValues (widget, XtNheight, &height, NULL);
8591 UNBLOCK_INPUT;
8593 if (abs (position) >= height)
8594 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8596 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8597 it maps line-movement to call_data = max(5, height/20). */
8598 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8599 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8600 else
8601 part = scroll_bar_move_ratio;
8603 window_being_scrolled = bar->window;
8604 bar->dragging = Qnil;
8605 last_scroll_bar_part = part;
8606 x_send_scroll_bar_event (bar->window, part, position, height);
8610 #endif /* not USE_MOTIF */
8613 /* Create the widget for scroll bar BAR on frame F. Record the widget
8614 and X window of the scroll bar in BAR. */
8616 static void
8617 x_create_toolkit_scroll_bar (f, bar)
8618 struct frame *f;
8619 struct scroll_bar *bar;
8621 Window xwindow;
8622 Widget widget;
8623 Arg av[20];
8624 int ac = 0;
8625 char *scroll_bar_name = "verticalScrollBar";
8626 unsigned long pixel;
8628 BLOCK_INPUT;
8630 #ifdef USE_MOTIF
8631 /* Set resources. Create the widget. */
8632 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8633 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8634 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8635 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8636 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8637 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8638 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8640 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8641 if (pixel != -1)
8643 XtSetArg (av[ac], XmNforeground, pixel);
8644 ++ac;
8647 pixel = f->output_data.x->scroll_bar_background_pixel;
8648 if (pixel != -1)
8650 XtSetArg (av[ac], XmNbackground, pixel);
8651 ++ac;
8654 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8655 scroll_bar_name, av, ac);
8657 /* Add one callback for everything that can happen. */
8658 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8659 (XtPointer) bar);
8660 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8661 (XtPointer) bar);
8662 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8663 (XtPointer) bar);
8664 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8665 (XtPointer) bar);
8666 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8667 (XtPointer) bar);
8668 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8669 (XtPointer) bar);
8670 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8671 (XtPointer) bar);
8673 /* Realize the widget. Only after that is the X window created. */
8674 XtRealizeWidget (widget);
8676 /* Set the cursor to an arrow. I didn't find a resource to do that.
8677 And I'm wondering why it hasn't an arrow cursor by default. */
8678 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8679 f->output_data.x->nontext_cursor);
8681 #else /* !USE_MOTIF i.e. use Xaw */
8683 /* Set resources. Create the widget. The background of the
8684 Xaw3d scroll bar widget is a little bit light for my taste.
8685 We don't alter it here to let users change it according
8686 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8687 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8688 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8689 /* For smoother scrolling with Xaw3d -sm */
8690 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8692 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8693 if (pixel != -1)
8695 XtSetArg (av[ac], XtNforeground, pixel);
8696 ++ac;
8699 pixel = f->output_data.x->scroll_bar_background_pixel;
8700 if (pixel != -1)
8702 XtSetArg (av[ac], XtNbackground, pixel);
8703 ++ac;
8706 /* Top/bottom shadow colors. */
8708 /* Allocate them, if necessary. */
8709 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8711 pixel = f->output_data.x->scroll_bar_background_pixel;
8712 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8713 &pixel, 1.2, 0x8000))
8714 pixel = -1;
8715 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8717 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8719 pixel = f->output_data.x->scroll_bar_background_pixel;
8720 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8721 &pixel, 0.6, 0x4000))
8722 pixel = -1;
8723 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8726 /* Tell the toolkit about them. */
8727 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8728 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8729 /* We tried to allocate a color for the top/bottom shadow, and
8730 failed, so tell Xaw3d to use dithering instead. */
8732 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8733 ++ac;
8735 else
8736 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8737 be more consistent with other emacs 3d colors, and since Xaw3d is
8738 not good at dealing with allocation failure. */
8740 /* This tells Xaw3d to use real colors instead of dithering for
8741 the shadows. */
8742 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8743 ++ac;
8745 /* Specify the colors. */
8746 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8747 if (pixel != -1)
8749 XtSetArg (av[ac], "topShadowPixel", pixel);
8750 ++ac;
8752 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8753 if (pixel != -1)
8755 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8756 ++ac;
8760 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8761 f->output_data.x->edit_widget, av, ac);
8764 char *initial = "";
8765 char *val = initial;
8766 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8767 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8768 if (val == initial)
8769 { /* ARROW_SCROLL */
8770 xaw3d_arrow_scroll = True;
8771 /* Isn't that just a personal preference ? -sm */
8772 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8776 /* Define callbacks. */
8777 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8778 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8779 (XtPointer) bar);
8781 /* Realize the widget. Only after that is the X window created. */
8782 XtRealizeWidget (widget);
8784 #endif /* !USE_MOTIF */
8786 /* Install an action hook that let's us detect when the user
8787 finishes interacting with a scroll bar. */
8788 if (action_hook_id == 0)
8789 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8791 /* Remember X window and widget in the scroll bar vector. */
8792 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8793 xwindow = XtWindow (widget);
8794 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8796 UNBLOCK_INPUT;
8800 /* Set the thumb size and position of scroll bar BAR. We are currently
8801 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8803 static void
8804 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8805 struct scroll_bar *bar;
8806 int portion, position, whole;
8808 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8809 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8810 float top, shown;
8812 if (whole == 0)
8813 top = 0, shown = 1;
8814 else
8816 top = (float) position / whole;
8817 shown = (float) portion / whole;
8820 BLOCK_INPUT;
8822 #ifdef USE_MOTIF
8824 int size, value;
8826 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8827 is the scroll bar's maximum and MIN is the scroll bar's minimum
8828 value. */
8829 size = shown * XM_SB_RANGE;
8830 size = min (size, XM_SB_RANGE);
8831 size = max (size, 1);
8833 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8834 value = top * XM_SB_RANGE;
8835 value = min (value, XM_SB_MAX - size);
8836 value = max (value, XM_SB_MIN);
8838 if (NILP (bar->dragging))
8839 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8840 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8841 /* This has the negative side effect that the slider value is
8842 not what it would be if we scrolled here using line-wise or
8843 page-wise movement. */
8844 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8845 else
8847 /* If currently dragging, only update the slider size.
8848 This reduces flicker effects. */
8849 int old_value, old_size, increment, page_increment;
8851 XmScrollBarGetValues (widget, &old_value, &old_size,
8852 &increment, &page_increment);
8853 XmScrollBarSetValues (widget, old_value,
8854 min (size, XM_SB_RANGE - old_value),
8855 0, 0, False);
8858 #else /* !USE_MOTIF i.e. use Xaw */
8860 float old_top, old_shown;
8861 Dimension height;
8862 XtVaGetValues (widget,
8863 XtNtopOfThumb, &old_top,
8864 XtNshown, &old_shown,
8865 XtNheight, &height,
8866 NULL);
8868 /* Massage the top+shown values. */
8869 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8870 top = max (0, min (1, top));
8871 else
8872 top = old_top;
8873 /* Keep two pixels available for moving the thumb down. */
8874 shown = max (0, min (1 - top - (2.0 / height), shown));
8876 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8877 check that your system's configuration file contains a define
8878 for `NARROWPROTO'. See s/freebsd.h for an example. */
8879 if (top != old_top || shown != old_shown)
8881 if (NILP (bar->dragging))
8882 XawScrollbarSetThumb (widget, top, shown);
8883 else
8885 #ifdef HAVE_XAW3D
8886 ScrollbarWidget sb = (ScrollbarWidget) widget;
8887 int scroll_mode = 0;
8889 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8890 if (xaw3d_arrow_scroll)
8892 /* Xaw3d stupidly ignores resize requests while dragging
8893 so we have to make it believe it's not in dragging mode. */
8894 scroll_mode = sb->scrollbar.scroll_mode;
8895 if (scroll_mode == 2)
8896 sb->scrollbar.scroll_mode = 0;
8898 #endif
8899 /* Try to make the scrolling a tad smoother. */
8900 if (!xaw3d_pick_top)
8901 shown = min (shown, old_shown);
8903 XawScrollbarSetThumb (widget, top, shown);
8905 #ifdef HAVE_XAW3D
8906 if (xaw3d_arrow_scroll && scroll_mode == 2)
8907 sb->scrollbar.scroll_mode = scroll_mode;
8908 #endif
8912 #endif /* !USE_MOTIF */
8914 UNBLOCK_INPUT;
8917 #endif /* USE_TOOLKIT_SCROLL_BARS */
8921 /************************************************************************
8922 Scroll bars, general
8923 ************************************************************************/
8925 /* Create a scroll bar and return the scroll bar vector for it. W is
8926 the Emacs window on which to create the scroll bar. TOP, LEFT,
8927 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8928 scroll bar. */
8930 static struct scroll_bar *
8931 x_scroll_bar_create (w, top, left, width, height)
8932 struct window *w;
8933 int top, left, width, height;
8935 struct frame *f = XFRAME (w->frame);
8936 struct scroll_bar *bar
8937 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8939 BLOCK_INPUT;
8941 #ifdef USE_TOOLKIT_SCROLL_BARS
8942 x_create_toolkit_scroll_bar (f, bar);
8943 #else /* not USE_TOOLKIT_SCROLL_BARS */
8945 XSetWindowAttributes a;
8946 unsigned long mask;
8947 Window window;
8949 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8950 if (a.background_pixel == -1)
8951 a.background_pixel = f->output_data.x->background_pixel;
8953 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8954 | ButtonMotionMask | PointerMotionHintMask
8955 | ExposureMask);
8956 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8958 mask = (CWBackPixel | CWEventMask | CWCursor);
8960 /* Clear the area of W that will serve as a scroll bar. This is
8961 for the case that a window has been split horizontally. In
8962 this case, no clear_frame is generated to reduce flickering. */
8963 if (width > 0 && height > 0)
8964 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8965 left, top, width,
8966 window_box_height (w), False);
8968 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8969 /* Position and size of scroll bar. */
8970 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8971 top,
8972 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8973 height,
8974 /* Border width, depth, class, and visual. */
8976 CopyFromParent,
8977 CopyFromParent,
8978 CopyFromParent,
8979 /* Attributes. */
8980 mask, &a);
8981 SET_SCROLL_BAR_X_WINDOW (bar, window);
8983 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8985 XSETWINDOW (bar->window, w);
8986 XSETINT (bar->top, top);
8987 XSETINT (bar->left, left);
8988 XSETINT (bar->width, width);
8989 XSETINT (bar->height, height);
8990 XSETINT (bar->start, 0);
8991 XSETINT (bar->end, 0);
8992 bar->dragging = Qnil;
8994 /* Add bar to its frame's list of scroll bars. */
8995 bar->next = FRAME_SCROLL_BARS (f);
8996 bar->prev = Qnil;
8997 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8998 if (!NILP (bar->next))
8999 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9001 /* Map the window/widget. */
9002 #ifdef USE_TOOLKIT_SCROLL_BARS
9004 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9005 XtConfigureWidget (scroll_bar,
9006 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9007 top,
9008 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9009 max (height, 1), 0);
9010 XtMapWidget (scroll_bar);
9012 #else /* not USE_TOOLKIT_SCROLL_BARS */
9013 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9014 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9016 UNBLOCK_INPUT;
9017 return bar;
9021 /* Draw BAR's handle in the proper position.
9023 If the handle is already drawn from START to END, don't bother
9024 redrawing it, unless REBUILD is non-zero; in that case, always
9025 redraw it. (REBUILD is handy for drawing the handle after expose
9026 events.)
9028 Normally, we want to constrain the start and end of the handle to
9029 fit inside its rectangle, but if the user is dragging the scroll
9030 bar handle, we want to let them drag it down all the way, so that
9031 the bar's top is as far down as it goes; otherwise, there's no way
9032 to move to the very end of the buffer. */
9034 #ifndef USE_TOOLKIT_SCROLL_BARS
9036 static void
9037 x_scroll_bar_set_handle (bar, start, end, rebuild)
9038 struct scroll_bar *bar;
9039 int start, end;
9040 int rebuild;
9042 int dragging = ! NILP (bar->dragging);
9043 Window w = SCROLL_BAR_X_WINDOW (bar);
9044 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9045 GC gc = f->output_data.x->normal_gc;
9047 /* If the display is already accurate, do nothing. */
9048 if (! rebuild
9049 && start == XINT (bar->start)
9050 && end == XINT (bar->end))
9051 return;
9053 BLOCK_INPUT;
9056 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9057 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9058 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9060 /* Make sure the values are reasonable, and try to preserve
9061 the distance between start and end. */
9063 int length = end - start;
9065 if (start < 0)
9066 start = 0;
9067 else if (start > top_range)
9068 start = top_range;
9069 end = start + length;
9071 if (end < start)
9072 end = start;
9073 else if (end > top_range && ! dragging)
9074 end = top_range;
9077 /* Store the adjusted setting in the scroll bar. */
9078 XSETINT (bar->start, start);
9079 XSETINT (bar->end, end);
9081 /* Clip the end position, just for display. */
9082 if (end > top_range)
9083 end = top_range;
9085 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9086 below top positions, to make sure the handle is always at least
9087 that many pixels tall. */
9088 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9090 /* Draw the empty space above the handle. Note that we can't clear
9091 zero-height areas; that means "clear to end of window." */
9092 if (0 < start)
9093 x_clear_area (FRAME_X_DISPLAY (f), w,
9094 /* x, y, width, height, and exposures. */
9095 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9096 VERTICAL_SCROLL_BAR_TOP_BORDER,
9097 inside_width, start,
9098 False);
9100 /* Change to proper foreground color if one is specified. */
9101 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9102 XSetForeground (FRAME_X_DISPLAY (f), gc,
9103 f->output_data.x->scroll_bar_foreground_pixel);
9105 /* Draw the handle itself. */
9106 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9107 /* x, y, width, height */
9108 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9109 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9110 inside_width, end - start);
9112 /* Restore the foreground color of the GC if we changed it above. */
9113 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9114 XSetForeground (FRAME_X_DISPLAY (f), gc,
9115 f->output_data.x->foreground_pixel);
9117 /* Draw the empty space below the handle. Note that we can't
9118 clear zero-height areas; that means "clear to end of window." */
9119 if (end < inside_height)
9120 x_clear_area (FRAME_X_DISPLAY (f), w,
9121 /* x, y, width, height, and exposures. */
9122 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9123 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9124 inside_width, inside_height - end,
9125 False);
9129 UNBLOCK_INPUT;
9132 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9134 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9135 nil. */
9137 static void
9138 x_scroll_bar_remove (bar)
9139 struct scroll_bar *bar;
9141 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9142 BLOCK_INPUT;
9144 #ifdef USE_TOOLKIT_SCROLL_BARS
9145 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9146 #else
9147 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9148 #endif
9150 /* Disassociate this scroll bar from its window. */
9151 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9153 UNBLOCK_INPUT;
9157 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9158 that we are displaying PORTION characters out of a total of WHOLE
9159 characters, starting at POSITION. If WINDOW has no scroll bar,
9160 create one. */
9162 static void
9163 XTset_vertical_scroll_bar (w, portion, whole, position)
9164 struct window *w;
9165 int portion, whole, position;
9167 struct frame *f = XFRAME (w->frame);
9168 struct scroll_bar *bar;
9169 int top, height, left, sb_left, width, sb_width;
9170 int window_x, window_y, window_width, window_height;
9172 /* Get window dimensions. */
9173 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9174 top = window_y;
9175 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9176 height = window_height;
9178 /* Compute the left edge of the scroll bar area. */
9179 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9180 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9181 else
9182 left = XFASTINT (w->left);
9183 left *= CANON_X_UNIT (f);
9184 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9186 /* Compute the width of the scroll bar which might be less than
9187 the width of the area reserved for the scroll bar. */
9188 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9189 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9190 else
9191 sb_width = width;
9193 /* Compute the left edge of the scroll bar. */
9194 #ifdef USE_TOOLKIT_SCROLL_BARS
9195 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9196 sb_left = left + width - sb_width - (width - sb_width) / 2;
9197 else
9198 sb_left = left + (width - sb_width) / 2;
9199 #else
9200 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9201 sb_left = left + width - sb_width;
9202 else
9203 sb_left = left;
9204 #endif
9206 /* Does the scroll bar exist yet? */
9207 if (NILP (w->vertical_scroll_bar))
9209 if (width > 0 && height > 0)
9211 BLOCK_INPUT;
9212 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9213 left, top, width, height, False);
9214 UNBLOCK_INPUT;
9217 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9219 else
9221 /* It may just need to be moved and resized. */
9222 unsigned int mask = 0;
9224 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9226 BLOCK_INPUT;
9228 if (sb_left != XINT (bar->left))
9229 mask |= CWX;
9230 if (top != XINT (bar->top))
9231 mask |= CWY;
9232 if (sb_width != XINT (bar->width))
9233 mask |= CWWidth;
9234 if (height != XINT (bar->height))
9235 mask |= CWHeight;
9237 #ifdef USE_TOOLKIT_SCROLL_BARS
9239 /* Since toolkit scroll bars are smaller than the space reserved
9240 for them on the frame, we have to clear "under" them. */
9241 if (width > 0 && height > 0)
9242 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9243 left, top, width, height, False);
9245 /* Move/size the scroll bar widget. */
9246 if (mask)
9247 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9248 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9249 top,
9250 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9251 max (height, 1), 0);
9253 #else /* not USE_TOOLKIT_SCROLL_BARS */
9255 /* Clear areas not covered by the scroll bar because of
9256 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9257 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9259 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9260 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9261 height, False);
9262 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9263 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9264 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9265 height, False);
9268 /* Clear areas not covered by the scroll bar because it's not as
9269 wide as the area reserved for it . This makes sure a
9270 previous mode line display is cleared after C-x 2 C-x 1, for
9271 example. */
9273 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9274 int rest = area_width - sb_width;
9275 if (rest > 0 && height > 0)
9277 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9278 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9279 left + area_width - rest, top,
9280 rest, height, False);
9281 else
9282 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9283 left, top, rest, height, False);
9287 /* Move/size the scroll bar window. */
9288 if (mask)
9290 XWindowChanges wc;
9292 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9293 wc.y = top;
9294 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9295 wc.height = height;
9296 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9297 mask, &wc);
9300 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9302 /* Remember new settings. */
9303 XSETINT (bar->left, sb_left);
9304 XSETINT (bar->top, top);
9305 XSETINT (bar->width, sb_width);
9306 XSETINT (bar->height, height);
9308 UNBLOCK_INPUT;
9311 #ifdef USE_TOOLKIT_SCROLL_BARS
9312 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9313 #else /* not USE_TOOLKIT_SCROLL_BARS */
9314 /* Set the scroll bar's current state, unless we're currently being
9315 dragged. */
9316 if (NILP (bar->dragging))
9318 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9320 if (whole == 0)
9321 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9322 else
9324 int start = ((double) position * top_range) / whole;
9325 int end = ((double) (position + portion) * top_range) / whole;
9326 x_scroll_bar_set_handle (bar, start, end, 0);
9329 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9331 XSETVECTOR (w->vertical_scroll_bar, bar);
9335 /* The following three hooks are used when we're doing a thorough
9336 redisplay of the frame. We don't explicitly know which scroll bars
9337 are going to be deleted, because keeping track of when windows go
9338 away is a real pain - "Can you say set-window-configuration, boys
9339 and girls?" Instead, we just assert at the beginning of redisplay
9340 that *all* scroll bars are to be removed, and then save a scroll bar
9341 from the fiery pit when we actually redisplay its window. */
9343 /* Arrange for all scroll bars on FRAME to be removed at the next call
9344 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9345 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9347 static void
9348 XTcondemn_scroll_bars (frame)
9349 FRAME_PTR frame;
9351 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9352 while (! NILP (FRAME_SCROLL_BARS (frame)))
9354 Lisp_Object bar;
9355 bar = FRAME_SCROLL_BARS (frame);
9356 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9357 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9358 XSCROLL_BAR (bar)->prev = Qnil;
9359 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9360 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9361 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9366 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9367 Note that WINDOW isn't necessarily condemned at all. */
9369 static void
9370 XTredeem_scroll_bar (window)
9371 struct window *window;
9373 struct scroll_bar *bar;
9374 struct frame *f;
9376 /* We can't redeem this window's scroll bar if it doesn't have one. */
9377 if (NILP (window->vertical_scroll_bar))
9378 abort ();
9380 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9382 /* Unlink it from the condemned list. */
9383 f = XFRAME (WINDOW_FRAME (window));
9384 if (NILP (bar->prev))
9386 /* If the prev pointer is nil, it must be the first in one of
9387 the lists. */
9388 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9389 /* It's not condemned. Everything's fine. */
9390 return;
9391 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9392 window->vertical_scroll_bar))
9393 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9394 else
9395 /* If its prev pointer is nil, it must be at the front of
9396 one or the other! */
9397 abort ();
9399 else
9400 XSCROLL_BAR (bar->prev)->next = bar->next;
9402 if (! NILP (bar->next))
9403 XSCROLL_BAR (bar->next)->prev = bar->prev;
9405 bar->next = FRAME_SCROLL_BARS (f);
9406 bar->prev = Qnil;
9407 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9408 if (! NILP (bar->next))
9409 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9412 /* Remove all scroll bars on FRAME that haven't been saved since the
9413 last call to `*condemn_scroll_bars_hook'. */
9415 static void
9416 XTjudge_scroll_bars (f)
9417 FRAME_PTR f;
9419 Lisp_Object bar, next;
9421 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9423 /* Clear out the condemned list now so we won't try to process any
9424 more events on the hapless scroll bars. */
9425 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9427 for (; ! NILP (bar); bar = next)
9429 struct scroll_bar *b = XSCROLL_BAR (bar);
9431 x_scroll_bar_remove (b);
9433 next = b->next;
9434 b->next = b->prev = Qnil;
9437 /* Now there should be no references to the condemned scroll bars,
9438 and they should get garbage-collected. */
9442 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9443 is a no-op when using toolkit scroll bars.
9445 This may be called from a signal handler, so we have to ignore GC
9446 mark bits. */
9448 static void
9449 x_scroll_bar_expose (bar, event)
9450 struct scroll_bar *bar;
9451 XEvent *event;
9453 #ifndef USE_TOOLKIT_SCROLL_BARS
9455 Window w = SCROLL_BAR_X_WINDOW (bar);
9456 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9457 GC gc = f->output_data.x->normal_gc;
9458 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9460 BLOCK_INPUT;
9462 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9464 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9465 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9467 /* x, y, width, height */
9468 0, 0,
9469 XINT (bar->width) - 1 - width_trim - width_trim,
9470 XINT (bar->height) - 1);
9472 UNBLOCK_INPUT;
9474 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9477 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9478 is set to something other than no_event, it is enqueued.
9480 This may be called from a signal handler, so we have to ignore GC
9481 mark bits. */
9483 #ifndef USE_TOOLKIT_SCROLL_BARS
9485 static void
9486 x_scroll_bar_handle_click (bar, event, emacs_event)
9487 struct scroll_bar *bar;
9488 XEvent *event;
9489 struct input_event *emacs_event;
9491 if (! GC_WINDOWP (bar->window))
9492 abort ();
9494 emacs_event->kind = scroll_bar_click;
9495 emacs_event->code = event->xbutton.button - Button1;
9496 emacs_event->modifiers
9497 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9498 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9499 event->xbutton.state)
9500 | (event->type == ButtonRelease
9501 ? up_modifier
9502 : down_modifier));
9503 emacs_event->frame_or_window = bar->window;
9504 emacs_event->arg = Qnil;
9505 emacs_event->timestamp = event->xbutton.time;
9507 #if 0
9508 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9509 int internal_height
9510 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9511 #endif
9512 int top_range
9513 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9514 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9516 if (y < 0) y = 0;
9517 if (y > top_range) y = top_range;
9519 if (y < XINT (bar->start))
9520 emacs_event->part = scroll_bar_above_handle;
9521 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9522 emacs_event->part = scroll_bar_handle;
9523 else
9524 emacs_event->part = scroll_bar_below_handle;
9526 /* Just because the user has clicked on the handle doesn't mean
9527 they want to drag it. Lisp code needs to be able to decide
9528 whether or not we're dragging. */
9529 #if 0
9530 /* If the user has just clicked on the handle, record where they're
9531 holding it. */
9532 if (event->type == ButtonPress
9533 && emacs_event->part == scroll_bar_handle)
9534 XSETINT (bar->dragging, y - XINT (bar->start));
9535 #endif
9537 /* If the user has released the handle, set it to its final position. */
9538 if (event->type == ButtonRelease
9539 && ! NILP (bar->dragging))
9541 int new_start = y - XINT (bar->dragging);
9542 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9544 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9545 bar->dragging = Qnil;
9548 /* Same deal here as the other #if 0. */
9549 #if 0
9550 /* Clicks on the handle are always reported as occurring at the top of
9551 the handle. */
9552 if (emacs_event->part == scroll_bar_handle)
9553 emacs_event->x = bar->start;
9554 else
9555 XSETINT (emacs_event->x, y);
9556 #else
9557 XSETINT (emacs_event->x, y);
9558 #endif
9560 XSETINT (emacs_event->y, top_range);
9564 /* Handle some mouse motion while someone is dragging the scroll bar.
9566 This may be called from a signal handler, so we have to ignore GC
9567 mark bits. */
9569 static void
9570 x_scroll_bar_note_movement (bar, event)
9571 struct scroll_bar *bar;
9572 XEvent *event;
9574 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9576 last_mouse_movement_time = event->xmotion.time;
9578 f->mouse_moved = 1;
9579 XSETVECTOR (last_mouse_scroll_bar, bar);
9581 /* If we're dragging the bar, display it. */
9582 if (! GC_NILP (bar->dragging))
9584 /* Where should the handle be now? */
9585 int new_start = event->xmotion.y - XINT (bar->dragging);
9587 if (new_start != XINT (bar->start))
9589 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9591 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9596 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9598 /* Return information to the user about the current position of the mouse
9599 on the scroll bar. */
9601 static void
9602 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9603 FRAME_PTR *fp;
9604 Lisp_Object *bar_window;
9605 enum scroll_bar_part *part;
9606 Lisp_Object *x, *y;
9607 unsigned long *time;
9609 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9610 Window w = SCROLL_BAR_X_WINDOW (bar);
9611 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9612 int win_x, win_y;
9613 Window dummy_window;
9614 int dummy_coord;
9615 unsigned int dummy_mask;
9617 BLOCK_INPUT;
9619 /* Get the mouse's position relative to the scroll bar window, and
9620 report that. */
9621 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9623 /* Root, child, root x and root y. */
9624 &dummy_window, &dummy_window,
9625 &dummy_coord, &dummy_coord,
9627 /* Position relative to scroll bar. */
9628 &win_x, &win_y,
9630 /* Mouse buttons and modifier keys. */
9631 &dummy_mask))
9633 else
9635 #if 0
9636 int inside_height
9637 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9638 #endif
9639 int top_range
9640 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9642 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9644 if (! NILP (bar->dragging))
9645 win_y -= XINT (bar->dragging);
9647 if (win_y < 0)
9648 win_y = 0;
9649 if (win_y > top_range)
9650 win_y = top_range;
9652 *fp = f;
9653 *bar_window = bar->window;
9655 if (! NILP (bar->dragging))
9656 *part = scroll_bar_handle;
9657 else if (win_y < XINT (bar->start))
9658 *part = scroll_bar_above_handle;
9659 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9660 *part = scroll_bar_handle;
9661 else
9662 *part = scroll_bar_below_handle;
9664 XSETINT (*x, win_y);
9665 XSETINT (*y, top_range);
9667 f->mouse_moved = 0;
9668 last_mouse_scroll_bar = Qnil;
9671 *time = last_mouse_movement_time;
9673 UNBLOCK_INPUT;
9677 /* The screen has been cleared so we may have changed foreground or
9678 background colors, and the scroll bars may need to be redrawn.
9679 Clear out the scroll bars, and ask for expose events, so we can
9680 redraw them. */
9682 void
9683 x_scroll_bar_clear (f)
9684 FRAME_PTR f;
9686 #ifndef USE_TOOLKIT_SCROLL_BARS
9687 Lisp_Object bar;
9689 /* We can have scroll bars even if this is 0,
9690 if we just turned off scroll bar mode.
9691 But in that case we should not clear them. */
9692 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9693 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9694 bar = XSCROLL_BAR (bar)->next)
9695 XClearArea (FRAME_X_DISPLAY (f),
9696 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9697 0, 0, 0, 0, True);
9698 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9701 /* This processes Expose events from the menu-bar specific X event
9702 loop in xmenu.c. This allows to redisplay the frame if necessary
9703 when handling menu-bar or pop-up items. */
9706 process_expose_from_menu (event)
9707 XEvent event;
9709 FRAME_PTR f;
9710 struct x_display_info *dpyinfo;
9711 int frame_exposed_p = 0;
9713 BLOCK_INPUT;
9715 dpyinfo = x_display_info_for_display (event.xexpose.display);
9716 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9717 if (f)
9719 if (f->async_visible == 0)
9721 f->async_visible = 1;
9722 f->async_iconified = 0;
9723 f->output_data.x->has_been_visible = 1;
9724 SET_FRAME_GARBAGED (f);
9726 else
9728 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9729 event.xexpose.x, event.xexpose.y,
9730 event.xexpose.width, event.xexpose.height);
9731 frame_exposed_p = 1;
9734 else
9736 struct scroll_bar *bar
9737 = x_window_to_scroll_bar (event.xexpose.window);
9739 if (bar)
9740 x_scroll_bar_expose (bar, &event);
9743 UNBLOCK_INPUT;
9744 return frame_exposed_p;
9747 /* Define a queue to save up SelectionRequest events for later handling. */
9749 struct selection_event_queue
9751 XEvent event;
9752 struct selection_event_queue *next;
9755 static struct selection_event_queue *queue;
9757 /* Nonzero means queue up certain events--don't process them yet. */
9759 static int x_queue_selection_requests;
9761 /* Queue up an X event *EVENT, to be processed later. */
9763 static void
9764 x_queue_event (f, event)
9765 FRAME_PTR f;
9766 XEvent *event;
9768 struct selection_event_queue *queue_tmp
9769 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9771 if (queue_tmp != NULL)
9773 queue_tmp->event = *event;
9774 queue_tmp->next = queue;
9775 queue = queue_tmp;
9779 /* Take all the queued events and put them back
9780 so that they get processed afresh. */
9782 static void
9783 x_unqueue_events (display)
9784 Display *display;
9786 while (queue != NULL)
9788 struct selection_event_queue *queue_tmp = queue;
9789 XPutBackEvent (display, &queue_tmp->event);
9790 queue = queue_tmp->next;
9791 xfree ((char *)queue_tmp);
9795 /* Start queuing SelectionRequest events. */
9797 void
9798 x_start_queuing_selection_requests (display)
9799 Display *display;
9801 x_queue_selection_requests++;
9804 /* Stop queuing SelectionRequest events. */
9806 void
9807 x_stop_queuing_selection_requests (display)
9808 Display *display;
9810 x_queue_selection_requests--;
9811 x_unqueue_events (display);
9814 /* The main X event-reading loop - XTread_socket. */
9816 /* Time stamp of enter window event. This is only used by XTread_socket,
9817 but we have to put it out here, since static variables within functions
9818 sometimes don't work. */
9820 static Time enter_timestamp;
9822 /* This holds the state XLookupString needs to implement dead keys
9823 and other tricks known as "compose processing". _X Window System_
9824 says that a portable program can't use this, but Stephen Gildea assures
9825 me that letting the compiler initialize it to zeros will work okay.
9827 This must be defined outside of XTread_socket, for the same reasons
9828 given for enter_timestamp, above. */
9830 static XComposeStatus compose_status;
9832 /* Record the last 100 characters stored
9833 to help debug the loss-of-chars-during-GC problem. */
9835 static int temp_index;
9836 static short temp_buffer[100];
9838 /* Set this to nonzero to fake an "X I/O error"
9839 on a particular display. */
9841 struct x_display_info *XTread_socket_fake_io_error;
9843 /* When we find no input here, we occasionally do a no-op command
9844 to verify that the X server is still running and we can still talk with it.
9845 We try all the open displays, one by one.
9846 This variable is used for cycling thru the displays. */
9848 static struct x_display_info *next_noop_dpyinfo;
9850 #define SET_SAVED_MENU_EVENT(size) \
9851 do \
9853 if (f->output_data.x->saved_menu_event == 0) \
9854 f->output_data.x->saved_menu_event \
9855 = (XEvent *) xmalloc (sizeof (XEvent)); \
9856 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9857 if (numchars >= 1) \
9859 bufp->kind = menu_bar_activate_event; \
9860 XSETFRAME (bufp->frame_or_window, f); \
9861 bufp->arg = Qnil; \
9862 bufp++; \
9863 count++; \
9864 numchars--; \
9867 while (0)
9869 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9870 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9872 /* Read events coming from the X server.
9873 This routine is called by the SIGIO handler.
9874 We return as soon as there are no more events to be read.
9876 Events representing keys are stored in buffer BUFP,
9877 which can hold up to NUMCHARS characters.
9878 We return the number of characters stored into the buffer,
9879 thus pretending to be `read'.
9881 EXPECTED is nonzero if the caller knows input is available. */
9884 XTread_socket (sd, bufp, numchars, expected)
9885 register int sd;
9886 /* register */ struct input_event *bufp;
9887 /* register */ int numchars;
9888 int expected;
9890 int count = 0;
9891 int nbytes = 0;
9892 XEvent event;
9893 struct frame *f;
9894 int event_found = 0;
9895 struct x_display_info *dpyinfo;
9896 struct coding_system coding;
9898 if (interrupt_input_blocked)
9900 interrupt_input_pending = 1;
9901 return -1;
9904 interrupt_input_pending = 0;
9905 BLOCK_INPUT;
9907 /* So people can tell when we have read the available input. */
9908 input_signal_count++;
9910 if (numchars <= 0)
9911 abort (); /* Don't think this happens. */
9913 ++handling_signal;
9915 /* The input should be decoded if it is from XIM. Currently the
9916 locale of XIM is the same as that of the system. So, we can use
9917 Vlocale_coding_system which is initialized properly at Emacs
9918 startup time. */
9919 setup_coding_system (Vlocale_coding_system, &coding);
9920 coding.src_multibyte = 0;
9921 coding.dst_multibyte = 1;
9922 /* The input is converted to events, thus we can't handle
9923 composition. Anyway, there's no XIM that gives us composition
9924 information. */
9925 coding.composing = COMPOSITION_DISABLED;
9927 /* Find the display we are supposed to read input for.
9928 It's the one communicating on descriptor SD. */
9929 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9931 #if 0 /* This ought to be unnecessary; let's verify it. */
9932 #ifdef FIOSNBIO
9933 /* If available, Xlib uses FIOSNBIO to make the socket
9934 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9935 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9936 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9937 fcntl (dpyinfo->connection, F_SETFL, 0);
9938 #endif /* ! defined (FIOSNBIO) */
9939 #endif
9941 #if 0 /* This code can't be made to work, with multiple displays,
9942 and appears not to be used on any system any more.
9943 Also keyboard.c doesn't turn O_NDELAY on and off
9944 for X connections. */
9945 #ifndef SIGIO
9946 #ifndef HAVE_SELECT
9947 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9949 extern int read_alarm_should_throw;
9950 read_alarm_should_throw = 1;
9951 XPeekEvent (dpyinfo->display, &event);
9952 read_alarm_should_throw = 0;
9954 #endif /* HAVE_SELECT */
9955 #endif /* SIGIO */
9956 #endif
9958 /* For debugging, this gives a way to fake an I/O error. */
9959 if (dpyinfo == XTread_socket_fake_io_error)
9961 XTread_socket_fake_io_error = 0;
9962 x_io_error_quitter (dpyinfo->display);
9965 while (XPending (dpyinfo->display))
9967 XNextEvent (dpyinfo->display, &event);
9969 #ifdef HAVE_X_I18N
9971 /* Filter events for the current X input method.
9972 XFilterEvent returns non-zero if the input method has
9973 consumed the event. We pass the frame's X window to
9974 XFilterEvent because that's the one for which the IC
9975 was created. */
9976 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9977 event.xclient.window);
9978 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9979 break;
9981 #endif
9982 event_found = 1;
9984 switch (event.type)
9986 case ClientMessage:
9988 if (event.xclient.message_type
9989 == dpyinfo->Xatom_wm_protocols
9990 && event.xclient.format == 32)
9992 if (event.xclient.data.l[0]
9993 == dpyinfo->Xatom_wm_take_focus)
9995 /* Use x_any_window_to_frame because this
9996 could be the shell widget window
9997 if the frame has no title bar. */
9998 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9999 #ifdef HAVE_X_I18N
10000 /* Not quite sure this is needed -pd */
10001 if (f && FRAME_XIC (f))
10002 XSetICFocus (FRAME_XIC (f));
10003 #endif
10004 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10005 instructs the WM to set the input focus automatically for
10006 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10007 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10008 it has set the focus. So, XSetInputFocus below is not
10009 needed.
10011 The call to XSetInputFocus below has also caused trouble. In
10012 cases where the XSetInputFocus done by the WM and the one
10013 below are temporally close (on a fast machine), the call
10014 below can generate additional FocusIn events which confuse
10015 Emacs. */
10017 /* Since we set WM_TAKE_FOCUS, we must call
10018 XSetInputFocus explicitly. But not if f is null,
10019 since that might be an event for a deleted frame. */
10020 if (f)
10022 Display *d = event.xclient.display;
10023 /* Catch and ignore errors, in case window has been
10024 iconified by a window manager such as GWM. */
10025 int count = x_catch_errors (d);
10026 XSetInputFocus (d, event.xclient.window,
10027 /* The ICCCM says this is
10028 the only valid choice. */
10029 RevertToParent,
10030 event.xclient.data.l[1]);
10031 /* This is needed to detect the error
10032 if there is an error. */
10033 XSync (d, False);
10034 x_uncatch_errors (d, count);
10036 /* Not certain about handling scroll bars here */
10037 #endif /* 0 */
10039 else if (event.xclient.data.l[0]
10040 == dpyinfo->Xatom_wm_save_yourself)
10042 /* Save state modify the WM_COMMAND property to
10043 something which can reinstate us. This notifies
10044 the session manager, who's looking for such a
10045 PropertyNotify. Can restart processing when
10046 a keyboard or mouse event arrives. */
10047 if (numchars > 0)
10049 f = x_top_window_to_frame (dpyinfo,
10050 event.xclient.window);
10052 /* This is just so we only give real data once
10053 for a single Emacs process. */
10054 if (f == SELECTED_FRAME ())
10055 XSetCommand (FRAME_X_DISPLAY (f),
10056 event.xclient.window,
10057 initial_argv, initial_argc);
10058 else if (f)
10059 XSetCommand (FRAME_X_DISPLAY (f),
10060 event.xclient.window,
10061 0, 0);
10064 else if (event.xclient.data.l[0]
10065 == dpyinfo->Xatom_wm_delete_window)
10067 struct frame *f
10068 = x_any_window_to_frame (dpyinfo,
10069 event.xclient.window);
10071 if (f)
10073 if (numchars == 0)
10074 abort ();
10076 bufp->kind = delete_window_event;
10077 XSETFRAME (bufp->frame_or_window, f);
10078 bufp->arg = Qnil;
10079 bufp++;
10081 count += 1;
10082 numchars -= 1;
10086 else if (event.xclient.message_type
10087 == dpyinfo->Xatom_wm_configure_denied)
10090 else if (event.xclient.message_type
10091 == dpyinfo->Xatom_wm_window_moved)
10093 int new_x, new_y;
10094 struct frame *f
10095 = x_window_to_frame (dpyinfo, event.xclient.window);
10097 new_x = event.xclient.data.s[0];
10098 new_y = event.xclient.data.s[1];
10100 if (f)
10102 f->output_data.x->left_pos = new_x;
10103 f->output_data.x->top_pos = new_y;
10106 #ifdef HACK_EDITRES
10107 else if (event.xclient.message_type
10108 == dpyinfo->Xatom_editres)
10110 struct frame *f
10111 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10112 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10113 &event, NULL);
10115 #endif /* HACK_EDITRES */
10116 else if ((event.xclient.message_type
10117 == dpyinfo->Xatom_DONE)
10118 || (event.xclient.message_type
10119 == dpyinfo->Xatom_PAGE))
10121 /* Ghostview job completed. Kill it. We could
10122 reply with "Next" if we received "Page", but we
10123 currently never do because we are interested in
10124 images, only, which should have 1 page. */
10125 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10126 struct frame *f
10127 = x_window_to_frame (dpyinfo, event.xclient.window);
10128 x_kill_gs_process (pixmap, f);
10129 expose_frame (f, 0, 0, 0, 0);
10131 #ifdef USE_TOOLKIT_SCROLL_BARS
10132 /* Scroll bar callbacks send a ClientMessage from which
10133 we construct an input_event. */
10134 else if (event.xclient.message_type
10135 == dpyinfo->Xatom_Scrollbar)
10137 x_scroll_bar_to_input_event (&event, bufp);
10138 ++bufp, ++count, --numchars;
10139 goto out;
10141 #endif /* USE_TOOLKIT_SCROLL_BARS */
10142 else
10143 goto OTHER;
10145 break;
10147 case SelectionNotify:
10148 #ifdef USE_X_TOOLKIT
10149 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10150 goto OTHER;
10151 #endif /* not USE_X_TOOLKIT */
10152 x_handle_selection_notify (&event.xselection);
10153 break;
10155 case SelectionClear: /* Someone has grabbed ownership. */
10156 #ifdef USE_X_TOOLKIT
10157 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10158 goto OTHER;
10159 #endif /* USE_X_TOOLKIT */
10161 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10163 if (numchars == 0)
10164 abort ();
10166 bufp->kind = selection_clear_event;
10167 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10168 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10169 SELECTION_EVENT_TIME (bufp) = eventp->time;
10170 bufp->frame_or_window = Qnil;
10171 bufp->arg = Qnil;
10172 bufp++;
10174 count += 1;
10175 numchars -= 1;
10177 break;
10179 case SelectionRequest: /* Someone wants our selection. */
10180 #ifdef USE_X_TOOLKIT
10181 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10182 goto OTHER;
10183 #endif /* USE_X_TOOLKIT */
10184 if (x_queue_selection_requests)
10185 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10186 &event);
10187 else
10189 XSelectionRequestEvent *eventp
10190 = (XSelectionRequestEvent *) &event;
10192 if (numchars == 0)
10193 abort ();
10195 bufp->kind = selection_request_event;
10196 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10197 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10198 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10199 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10200 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10201 SELECTION_EVENT_TIME (bufp) = eventp->time;
10202 bufp->frame_or_window = Qnil;
10203 bufp->arg = Qnil;
10204 bufp++;
10206 count += 1;
10207 numchars -= 1;
10209 break;
10211 case PropertyNotify:
10212 #if 0 /* This is plain wrong. In the case that we are waiting for a
10213 PropertyNotify used as an ACK in incremental selection
10214 transfer, the property will be on the receiver's window. */
10215 #if defined USE_X_TOOLKIT
10216 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10217 goto OTHER;
10218 #endif
10219 #endif
10220 x_handle_property_notify (&event.xproperty);
10221 goto OTHER;
10223 case ReparentNotify:
10224 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10225 if (f)
10227 int x, y;
10228 f->output_data.x->parent_desc = event.xreparent.parent;
10229 x_real_positions (f, &x, &y);
10230 f->output_data.x->left_pos = x;
10231 f->output_data.x->top_pos = y;
10233 break;
10235 case Expose:
10236 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10237 if (f)
10239 if (f->async_visible == 0)
10241 f->async_visible = 1;
10242 f->async_iconified = 0;
10243 f->output_data.x->has_been_visible = 1;
10244 SET_FRAME_GARBAGED (f);
10246 else
10247 expose_frame (x_window_to_frame (dpyinfo,
10248 event.xexpose.window),
10249 event.xexpose.x, event.xexpose.y,
10250 event.xexpose.width, event.xexpose.height);
10252 else
10254 #ifndef USE_TOOLKIT_SCROLL_BARS
10255 struct scroll_bar *bar;
10256 #endif
10257 #if defined USE_LUCID
10258 /* Submenus of the Lucid menu bar aren't widgets
10259 themselves, so there's no way to dispatch events
10260 to them. Recognize this case separately. */
10262 Widget widget
10263 = x_window_to_menu_bar (event.xexpose.window);
10264 if (widget)
10265 xlwmenu_redisplay (widget);
10267 #endif /* USE_LUCID */
10269 #ifdef USE_TOOLKIT_SCROLL_BARS
10270 /* Dispatch event to the widget. */
10271 goto OTHER;
10272 #else /* not USE_TOOLKIT_SCROLL_BARS */
10273 bar = x_window_to_scroll_bar (event.xexpose.window);
10275 if (bar)
10276 x_scroll_bar_expose (bar, &event);
10277 #ifdef USE_X_TOOLKIT
10278 else
10279 goto OTHER;
10280 #endif /* USE_X_TOOLKIT */
10281 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10283 break;
10285 case GraphicsExpose: /* This occurs when an XCopyArea's
10286 source area was obscured or not
10287 available. */
10288 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10289 if (f)
10291 expose_frame (f,
10292 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10293 event.xgraphicsexpose.width,
10294 event.xgraphicsexpose.height);
10296 #ifdef USE_X_TOOLKIT
10297 else
10298 goto OTHER;
10299 #endif /* USE_X_TOOLKIT */
10300 break;
10302 case NoExpose: /* This occurs when an XCopyArea's
10303 source area was completely
10304 available. */
10305 break;
10307 case UnmapNotify:
10308 /* Redo the mouse-highlight after the tooltip has gone. */
10309 if (event.xmap.window == tip_window)
10311 tip_window = 0;
10312 redo_mouse_highlight ();
10315 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10316 if (f) /* F may no longer exist if
10317 the frame was deleted. */
10319 /* While a frame is unmapped, display generation is
10320 disabled; you don't want to spend time updating a
10321 display that won't ever be seen. */
10322 f->async_visible = 0;
10323 /* We can't distinguish, from the event, whether the window
10324 has become iconified or invisible. So assume, if it
10325 was previously visible, than now it is iconified.
10326 But x_make_frame_invisible clears both
10327 the visible flag and the iconified flag;
10328 and that way, we know the window is not iconified now. */
10329 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10331 f->async_iconified = 1;
10333 bufp->kind = iconify_event;
10334 XSETFRAME (bufp->frame_or_window, f);
10335 bufp->arg = Qnil;
10336 bufp++;
10337 count++;
10338 numchars--;
10341 goto OTHER;
10343 case MapNotify:
10344 if (event.xmap.window == tip_window)
10345 /* The tooltip has been drawn already. Avoid
10346 the SET_FRAME_GARBAGED below. */
10347 goto OTHER;
10349 /* We use x_top_window_to_frame because map events can
10350 come for sub-windows and they don't mean that the
10351 frame is visible. */
10352 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10353 if (f)
10355 f->async_visible = 1;
10356 f->async_iconified = 0;
10357 f->output_data.x->has_been_visible = 1;
10359 /* wait_reading_process_input will notice this and update
10360 the frame's display structures. */
10361 SET_FRAME_GARBAGED (f);
10363 if (f->iconified)
10365 bufp->kind = deiconify_event;
10366 XSETFRAME (bufp->frame_or_window, f);
10367 bufp->arg = Qnil;
10368 bufp++;
10369 count++;
10370 numchars--;
10372 else if (! NILP (Vframe_list)
10373 && ! NILP (XCDR (Vframe_list)))
10374 /* Force a redisplay sooner or later
10375 to update the frame titles
10376 in case this is the second frame. */
10377 record_asynch_buffer_change ();
10379 goto OTHER;
10381 case KeyPress:
10382 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10384 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10385 if (f == 0)
10387 /* Scroll bars consume key events, but we want
10388 the keys to go to the scroll bar's frame. */
10389 Widget widget = XtWindowToWidget (dpyinfo->display,
10390 event.xkey.window);
10391 if (widget && XmIsScrollBar (widget))
10393 widget = XtParent (widget);
10394 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10397 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10399 if (f != 0)
10401 KeySym keysym, orig_keysym;
10402 /* al%imercury@uunet.uu.net says that making this 81
10403 instead of 80 fixed a bug whereby meta chars made
10404 his Emacs hang.
10406 It seems that some version of XmbLookupString has
10407 a bug of not returning XBufferOverflow in
10408 status_return even if the input is too long to
10409 fit in 81 bytes. So, we must prepare sufficient
10410 bytes for copy_buffer. 513 bytes (256 chars for
10411 two-byte character set) seems to be a fairly good
10412 approximation. -- 2000.8.10 handa@etl.go.jp */
10413 unsigned char copy_buffer[513];
10414 unsigned char *copy_bufptr = copy_buffer;
10415 int copy_bufsiz = sizeof (copy_buffer);
10416 int modifiers;
10418 event.xkey.state
10419 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10420 extra_keyboard_modifiers);
10421 modifiers = event.xkey.state;
10423 /* This will have to go some day... */
10425 /* make_lispy_event turns chars into control chars.
10426 Don't do it here because XLookupString is too eager. */
10427 event.xkey.state &= ~ControlMask;
10428 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10429 | dpyinfo->super_mod_mask
10430 | dpyinfo->hyper_mod_mask
10431 | dpyinfo->alt_mod_mask);
10433 /* In case Meta is ComposeCharacter,
10434 clear its status. According to Markus Ehrnsperger
10435 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10436 this enables ComposeCharacter to work whether or
10437 not it is combined with Meta. */
10438 if (modifiers & dpyinfo->meta_mod_mask)
10439 bzero (&compose_status, sizeof (compose_status));
10441 #ifdef HAVE_X_I18N
10442 if (FRAME_XIC (f))
10444 Status status_return;
10446 nbytes = XmbLookupString (FRAME_XIC (f),
10447 &event.xkey, copy_bufptr,
10448 copy_bufsiz, &keysym,
10449 &status_return);
10450 if (status_return == XBufferOverflow)
10452 copy_bufsiz = nbytes + 1;
10453 copy_bufptr = (char *) alloca (copy_bufsiz);
10454 nbytes = XmbLookupString (FRAME_XIC (f),
10455 &event.xkey, copy_bufptr,
10456 copy_bufsiz, &keysym,
10457 &status_return);
10460 if (status_return == XLookupNone)
10461 break;
10462 else if (status_return == XLookupChars)
10464 keysym = NoSymbol;
10465 modifiers = 0;
10467 else if (status_return != XLookupKeySym
10468 && status_return != XLookupBoth)
10469 abort ();
10471 else
10472 nbytes = XLookupString (&event.xkey, copy_bufptr,
10473 copy_bufsiz, &keysym,
10474 &compose_status);
10475 #else
10476 nbytes = XLookupString (&event.xkey, copy_bufptr,
10477 copy_bufsiz, &keysym,
10478 &compose_status);
10479 #endif
10481 orig_keysym = keysym;
10483 if (numchars > 1)
10485 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10486 || keysym == XK_Delete
10487 #ifdef XK_ISO_Left_Tab
10488 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10489 #endif
10490 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10491 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10492 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10493 #ifdef HPUX
10494 /* This recognizes the "extended function keys".
10495 It seems there's no cleaner way.
10496 Test IsModifierKey to avoid handling mode_switch
10497 incorrectly. */
10498 || ((unsigned) (keysym) >= XK_Select
10499 && (unsigned)(keysym) < XK_KP_Space)
10500 #endif
10501 #ifdef XK_dead_circumflex
10502 || orig_keysym == XK_dead_circumflex
10503 #endif
10504 #ifdef XK_dead_grave
10505 || orig_keysym == XK_dead_grave
10506 #endif
10507 #ifdef XK_dead_tilde
10508 || orig_keysym == XK_dead_tilde
10509 #endif
10510 #ifdef XK_dead_diaeresis
10511 || orig_keysym == XK_dead_diaeresis
10512 #endif
10513 #ifdef XK_dead_macron
10514 || orig_keysym == XK_dead_macron
10515 #endif
10516 #ifdef XK_dead_degree
10517 || orig_keysym == XK_dead_degree
10518 #endif
10519 #ifdef XK_dead_acute
10520 || orig_keysym == XK_dead_acute
10521 #endif
10522 #ifdef XK_dead_cedilla
10523 || orig_keysym == XK_dead_cedilla
10524 #endif
10525 #ifdef XK_dead_breve
10526 || orig_keysym == XK_dead_breve
10527 #endif
10528 #ifdef XK_dead_ogonek
10529 || orig_keysym == XK_dead_ogonek
10530 #endif
10531 #ifdef XK_dead_caron
10532 || orig_keysym == XK_dead_caron
10533 #endif
10534 #ifdef XK_dead_doubleacute
10535 || orig_keysym == XK_dead_doubleacute
10536 #endif
10537 #ifdef XK_dead_abovedot
10538 || orig_keysym == XK_dead_abovedot
10539 #endif
10540 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10541 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10542 /* Any "vendor-specific" key is ok. */
10543 || (orig_keysym & (1 << 28))
10544 || (keysym != NoSymbol && nbytes == 0))
10545 && ! (IsModifierKey (orig_keysym)
10546 #ifndef HAVE_X11R5
10547 #ifdef XK_Mode_switch
10548 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10549 #endif
10550 #ifdef XK_Num_Lock
10551 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10552 #endif
10553 #endif /* not HAVE_X11R5 */
10556 if (temp_index == sizeof temp_buffer / sizeof (short))
10557 temp_index = 0;
10558 temp_buffer[temp_index++] = keysym;
10559 bufp->kind = non_ascii_keystroke;
10560 bufp->code = keysym;
10561 XSETFRAME (bufp->frame_or_window, f);
10562 bufp->arg = Qnil;
10563 bufp->modifiers
10564 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10565 modifiers);
10566 bufp->timestamp = event.xkey.time;
10567 bufp++;
10568 count++;
10569 numchars--;
10571 else if (numchars > nbytes)
10573 register int i;
10574 register int c;
10575 int nchars, len;
10577 for (i = 0; i < nbytes; i++)
10579 if (temp_index == (sizeof temp_buffer
10580 / sizeof (short)))
10581 temp_index = 0;
10582 temp_buffer[temp_index++] = copy_bufptr[i];
10585 if (/* If the event is not from XIM, */
10586 event.xkey.keycode != 0
10587 /* or the current locale doesn't request
10588 decoding of the intup data, ... */
10589 || coding.type == coding_type_raw_text
10590 || coding.type == coding_type_no_conversion)
10592 /* ... we can use the input data as is. */
10593 nchars = nbytes;
10595 else
10597 /* We have to decode the input data. */
10598 int require;
10599 unsigned char *p;
10601 require = decoding_buffer_size (&coding, nbytes);
10602 p = (unsigned char *) alloca (require);
10603 coding.mode |= CODING_MODE_LAST_BLOCK;
10604 decode_coding (&coding, copy_bufptr, p,
10605 nbytes, require);
10606 nbytes = coding.produced;
10607 nchars = coding.produced_char;
10608 copy_bufptr = p;
10611 /* Convert the input data to a sequence of
10612 character events. */
10613 for (i = 0; i < nbytes; i += len)
10615 if (nchars == nbytes)
10616 c = copy_bufptr[i], len = 1;
10617 else
10618 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10619 nbytes - i, len);
10621 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10622 ? ascii_keystroke
10623 : multibyte_char_keystroke);
10624 bufp->code = c;
10625 XSETFRAME (bufp->frame_or_window, f);
10626 bufp->arg = Qnil;
10627 bufp->modifiers
10628 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10629 modifiers);
10630 bufp->timestamp = event.xkey.time;
10631 bufp++;
10634 count += nchars;
10635 numchars -= nchars;
10637 if (keysym == NoSymbol)
10638 break;
10640 else
10641 abort ();
10643 else
10644 abort ();
10646 #ifdef HAVE_X_I18N
10647 /* Don't dispatch this event since XtDispatchEvent calls
10648 XFilterEvent, and two calls in a row may freeze the
10649 client. */
10650 break;
10651 #else
10652 goto OTHER;
10653 #endif
10655 case KeyRelease:
10656 #ifdef HAVE_X_I18N
10657 /* Don't dispatch this event since XtDispatchEvent calls
10658 XFilterEvent, and two calls in a row may freeze the
10659 client. */
10660 break;
10661 #else
10662 goto OTHER;
10663 #endif
10665 /* Here's a possible interpretation of the whole
10666 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10667 you get a FocusIn event, you have to get a FocusOut
10668 event before you relinquish the focus. If you
10669 haven't received a FocusIn event, then a mere
10670 LeaveNotify is enough to free you. */
10672 case EnterNotify:
10674 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10676 #if 0
10677 if (event.xcrossing.focus)
10679 /* Avoid nasty pop/raise loops. */
10680 if (f && (!(f->auto_raise)
10681 || !(f->auto_lower)
10682 || (event.xcrossing.time - enter_timestamp) > 500))
10684 x_new_focus_frame (dpyinfo, f);
10685 enter_timestamp = event.xcrossing.time;
10688 else if (f == dpyinfo->x_focus_frame)
10689 x_new_focus_frame (dpyinfo, 0);
10690 #endif
10692 /* EnterNotify counts as mouse movement,
10693 so update things that depend on mouse position. */
10694 if (f && !f->output_data.x->hourglass_p)
10695 note_mouse_movement (f, &event.xmotion);
10696 goto OTHER;
10699 case FocusIn:
10700 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10701 if (event.xfocus.detail != NotifyPointer)
10702 dpyinfo->x_focus_event_frame = f;
10703 if (f)
10705 x_new_focus_frame (dpyinfo, f);
10707 /* Don't stop displaying the initial startup message
10708 for a switch-frame event we don't need. */
10709 if (GC_NILP (Vterminal_frame)
10710 && GC_CONSP (Vframe_list)
10711 && !GC_NILP (XCDR (Vframe_list)))
10713 bufp->kind = FOCUS_IN_EVENT;
10714 XSETFRAME (bufp->frame_or_window, f);
10715 bufp->arg = Qnil;
10716 ++bufp, ++count, --numchars;
10720 #ifdef HAVE_X_I18N
10721 if (f && FRAME_XIC (f))
10722 XSetICFocus (FRAME_XIC (f));
10723 #endif
10725 goto OTHER;
10727 case LeaveNotify:
10728 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10729 if (f)
10731 if (f == dpyinfo->mouse_face_mouse_frame)
10733 /* If we move outside the frame, then we're
10734 certainly no longer on any text in the frame. */
10735 clear_mouse_face (dpyinfo);
10736 dpyinfo->mouse_face_mouse_frame = 0;
10739 /* Generate a nil HELP_EVENT to cancel a help-echo.
10740 Do it only if there's something to cancel.
10741 Otherwise, the startup message is cleared when
10742 the mouse leaves the frame. */
10743 if (any_help_event_p)
10745 Lisp_Object frame;
10746 int n;
10748 XSETFRAME (frame, f);
10749 help_echo = Qnil;
10750 n = gen_help_event (bufp, numchars,
10751 Qnil, frame, Qnil, Qnil, 0);
10752 bufp += n, count += n, numchars -= n;
10755 #if 0
10756 if (event.xcrossing.focus)
10757 x_mouse_leave (dpyinfo);
10758 else
10760 if (f == dpyinfo->x_focus_event_frame)
10761 dpyinfo->x_focus_event_frame = 0;
10762 if (f == dpyinfo->x_focus_frame)
10763 x_new_focus_frame (dpyinfo, 0);
10765 #endif
10767 goto OTHER;
10769 case FocusOut:
10770 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10771 if (event.xfocus.detail != NotifyPointer
10772 && f == dpyinfo->x_focus_event_frame)
10773 dpyinfo->x_focus_event_frame = 0;
10774 if (f && f == dpyinfo->x_focus_frame)
10775 x_new_focus_frame (dpyinfo, 0);
10777 #ifdef HAVE_X_I18N
10778 if (f && FRAME_XIC (f))
10779 XUnsetICFocus (FRAME_XIC (f));
10780 #endif
10782 goto OTHER;
10784 case MotionNotify:
10786 previous_help_echo = help_echo;
10787 help_echo = help_echo_object = help_echo_window = Qnil;
10788 help_echo_pos = -1;
10790 if (dpyinfo->grabbed && last_mouse_frame
10791 && FRAME_LIVE_P (last_mouse_frame))
10792 f = last_mouse_frame;
10793 else
10794 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10796 if (f)
10797 note_mouse_movement (f, &event.xmotion);
10798 else
10800 #ifndef USE_TOOLKIT_SCROLL_BARS
10801 struct scroll_bar *bar
10802 = x_window_to_scroll_bar (event.xmotion.window);
10804 if (bar)
10805 x_scroll_bar_note_movement (bar, &event);
10806 #endif /* USE_TOOLKIT_SCROLL_BARS */
10808 /* If we move outside the frame, then we're
10809 certainly no longer on any text in the frame. */
10810 clear_mouse_face (dpyinfo);
10813 /* If the contents of the global variable help_echo
10814 has changed, generate a HELP_EVENT. */
10815 if (!NILP (help_echo)
10816 || !NILP (previous_help_echo))
10818 Lisp_Object frame;
10819 int n;
10821 if (f)
10822 XSETFRAME (frame, f);
10823 else
10824 frame = Qnil;
10826 any_help_event_p = 1;
10827 n = gen_help_event (bufp, numchars, help_echo, frame,
10828 help_echo_window, help_echo_object,
10829 help_echo_pos);
10830 bufp += n, count += n, numchars -= n;
10833 goto OTHER;
10836 case ConfigureNotify:
10837 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10838 if (f)
10840 #ifndef USE_X_TOOLKIT
10841 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10842 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10844 /* In the toolkit version, change_frame_size
10845 is called by the code that handles resizing
10846 of the EmacsFrame widget. */
10848 /* Even if the number of character rows and columns has
10849 not changed, the font size may have changed, so we need
10850 to check the pixel dimensions as well. */
10851 if (columns != f->width
10852 || rows != f->height
10853 || event.xconfigure.width != f->output_data.x->pixel_width
10854 || event.xconfigure.height != f->output_data.x->pixel_height)
10856 change_frame_size (f, rows, columns, 0, 1, 0);
10857 SET_FRAME_GARBAGED (f);
10858 cancel_mouse_face (f);
10860 #endif
10862 f->output_data.x->pixel_width = event.xconfigure.width;
10863 f->output_data.x->pixel_height = event.xconfigure.height;
10865 /* What we have now is the position of Emacs's own window.
10866 Convert that to the position of the window manager window. */
10867 x_real_positions (f, &f->output_data.x->left_pos,
10868 &f->output_data.x->top_pos);
10870 #ifdef HAVE_X_I18N
10871 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10872 xic_set_statusarea (f);
10873 #endif
10875 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10877 /* Since the WM decorations come below top_pos now,
10878 we must put them below top_pos in the future. */
10879 f->output_data.x->win_gravity = NorthWestGravity;
10880 x_wm_set_size_hint (f, (long) 0, 0);
10882 #ifdef USE_MOTIF
10883 /* Some window managers pass (0,0) as the location of
10884 the window, and the Motif event handler stores it
10885 in the emacs widget, which messes up Motif menus. */
10886 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10888 event.xconfigure.x = f->output_data.x->widget->core.x;
10889 event.xconfigure.y = f->output_data.x->widget->core.y;
10891 #endif /* USE_MOTIF */
10893 goto OTHER;
10895 case ButtonPress:
10896 case ButtonRelease:
10898 /* If we decide we want to generate an event to be seen
10899 by the rest of Emacs, we put it here. */
10900 struct input_event emacs_event;
10901 int tool_bar_p = 0;
10903 emacs_event.kind = no_event;
10904 bzero (&compose_status, sizeof (compose_status));
10906 if (dpyinfo->grabbed
10907 && last_mouse_frame
10908 && FRAME_LIVE_P (last_mouse_frame))
10909 f = last_mouse_frame;
10910 else
10911 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10913 if (f)
10915 /* Is this in the tool-bar? */
10916 if (WINDOWP (f->tool_bar_window)
10917 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10919 Lisp_Object window;
10920 int p, x, y;
10922 x = event.xbutton.x;
10923 y = event.xbutton.y;
10925 /* Set x and y. */
10926 window = window_from_coordinates (f, x, y, &p, 1);
10927 if (EQ (window, f->tool_bar_window))
10929 x_handle_tool_bar_click (f, &event.xbutton);
10930 tool_bar_p = 1;
10934 if (!tool_bar_p)
10935 if (!dpyinfo->x_focus_frame
10936 || f == dpyinfo->x_focus_frame)
10937 construct_mouse_click (&emacs_event, &event, f);
10939 else
10941 #ifndef USE_TOOLKIT_SCROLL_BARS
10942 struct scroll_bar *bar
10943 = x_window_to_scroll_bar (event.xbutton.window);
10945 if (bar)
10946 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10947 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10950 if (event.type == ButtonPress)
10952 dpyinfo->grabbed |= (1 << event.xbutton.button);
10953 last_mouse_frame = f;
10954 /* Ignore any mouse motion that happened
10955 before this event; any subsequent mouse-movement
10956 Emacs events should reflect only motion after
10957 the ButtonPress. */
10958 if (f != 0)
10959 f->mouse_moved = 0;
10961 if (!tool_bar_p)
10962 last_tool_bar_item = -1;
10964 else
10966 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10969 if (numchars >= 1 && emacs_event.kind != no_event)
10971 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10972 bufp++;
10973 count++;
10974 numchars--;
10977 #ifdef USE_X_TOOLKIT
10978 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10979 /* For a down-event in the menu bar,
10980 don't pass it to Xt right now.
10981 Instead, save it away
10982 and we will pass it to Xt from kbd_buffer_get_event.
10983 That way, we can run some Lisp code first. */
10984 if (f && event.type == ButtonPress
10985 /* Verify the event is really within the menu bar
10986 and not just sent to it due to grabbing. */
10987 && event.xbutton.x >= 0
10988 && event.xbutton.x < f->output_data.x->pixel_width
10989 && event.xbutton.y >= 0
10990 && event.xbutton.y < f->output_data.x->menubar_height
10991 && event.xbutton.same_screen)
10993 SET_SAVED_BUTTON_EVENT;
10994 XSETFRAME (last_mouse_press_frame, f);
10996 else if (event.type == ButtonPress)
10998 last_mouse_press_frame = Qnil;
10999 goto OTHER;
11002 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11003 but I am trying to be cautious. */
11004 else if (event.type == ButtonRelease)
11006 if (!NILP (last_mouse_press_frame))
11008 f = XFRAME (last_mouse_press_frame);
11009 if (f->output_data.x)
11010 SET_SAVED_BUTTON_EVENT;
11012 else
11013 goto OTHER;
11015 #endif /* USE_MOTIF */
11016 else
11017 goto OTHER;
11018 #endif /* USE_X_TOOLKIT */
11020 break;
11022 case CirculateNotify:
11023 goto OTHER;
11025 case CirculateRequest:
11026 goto OTHER;
11028 case VisibilityNotify:
11029 goto OTHER;
11031 case MappingNotify:
11032 /* Someone has changed the keyboard mapping - update the
11033 local cache. */
11034 switch (event.xmapping.request)
11036 case MappingModifier:
11037 x_find_modifier_meanings (dpyinfo);
11038 /* This is meant to fall through. */
11039 case MappingKeyboard:
11040 XRefreshKeyboardMapping (&event.xmapping);
11042 goto OTHER;
11044 default:
11045 OTHER:
11046 #ifdef USE_X_TOOLKIT
11047 BLOCK_INPUT;
11048 XtDispatchEvent (&event);
11049 UNBLOCK_INPUT;
11050 #endif /* USE_X_TOOLKIT */
11051 break;
11056 out:;
11058 /* On some systems, an X bug causes Emacs to get no more events
11059 when the window is destroyed. Detect that. (1994.) */
11060 if (! event_found)
11062 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11063 One XNOOP in 100 loops will make Emacs terminate.
11064 B. Bretthauer, 1994 */
11065 x_noop_count++;
11066 if (x_noop_count >= 100)
11068 x_noop_count=0;
11070 if (next_noop_dpyinfo == 0)
11071 next_noop_dpyinfo = x_display_list;
11073 XNoOp (next_noop_dpyinfo->display);
11075 /* Each time we get here, cycle through the displays now open. */
11076 next_noop_dpyinfo = next_noop_dpyinfo->next;
11080 /* If the focus was just given to an auto-raising frame,
11081 raise it now. */
11082 /* ??? This ought to be able to handle more than one such frame. */
11083 if (pending_autoraise_frame)
11085 x_raise_frame (pending_autoraise_frame);
11086 pending_autoraise_frame = 0;
11089 UNBLOCK_INPUT;
11090 --handling_signal;
11091 return count;
11097 /***********************************************************************
11098 Text Cursor
11099 ***********************************************************************/
11101 /* Notice if the text cursor of window W has been overwritten by a
11102 drawing operation that outputs N glyphs starting at START_X and
11103 ending at END_X in the line given by output_cursor.vpos.
11104 Coordinates are area-relative. END_X < 0 means all the rest
11105 of the line after START_X has been written. */
11107 static void
11108 notice_overwritten_cursor (w, start_x, end_x)
11109 struct window *w;
11110 int start_x, end_x;
11112 if (updated_area == TEXT_AREA
11113 && w->phys_cursor_on_p
11114 && output_cursor.vpos == w->phys_cursor.vpos
11115 && start_x <= w->phys_cursor.x
11116 && (end_x < 0 || end_x > w->phys_cursor.x))
11117 w->phys_cursor_on_p = 0;
11121 /* Set clipping for output in glyph row ROW. W is the window in which
11122 we operate. GC is the graphics context to set clipping in.
11123 WHOLE_LINE_P non-zero means include the areas used for truncation
11124 mark display and alike in the clipping rectangle.
11126 ROW may be a text row or, e.g., a mode line. Text rows must be
11127 clipped to the interior of the window dedicated to text display,
11128 mode lines must be clipped to the whole window. */
11130 static void
11131 x_clip_to_row (w, row, gc, whole_line_p)
11132 struct window *w;
11133 struct glyph_row *row;
11134 GC gc;
11135 int whole_line_p;
11137 struct frame *f = XFRAME (WINDOW_FRAME (w));
11138 XRectangle clip_rect;
11139 int window_x, window_y, window_width, window_height;
11141 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11143 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11144 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11145 clip_rect.y = max (clip_rect.y, window_y);
11146 clip_rect.width = window_width;
11147 clip_rect.height = row->visible_height;
11149 /* If clipping to the whole line, including trunc marks, extend
11150 the rectangle to the left and increase its width. */
11151 if (whole_line_p)
11153 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11154 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11157 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11161 /* Draw a hollow box cursor on window W in glyph row ROW. */
11163 static void
11164 x_draw_hollow_cursor (w, row)
11165 struct window *w;
11166 struct glyph_row *row;
11168 struct frame *f = XFRAME (WINDOW_FRAME (w));
11169 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11170 Display *dpy = FRAME_X_DISPLAY (f);
11171 int x, y, wd, h;
11172 XGCValues xgcv;
11173 struct glyph *cursor_glyph;
11174 GC gc;
11176 /* Compute frame-relative coordinates from window-relative
11177 coordinates. */
11178 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11179 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11180 + row->ascent - w->phys_cursor_ascent);
11181 h = row->height - 1;
11183 /* Get the glyph the cursor is on. If we can't tell because
11184 the current matrix is invalid or such, give up. */
11185 cursor_glyph = get_phys_cursor_glyph (w);
11186 if (cursor_glyph == NULL)
11187 return;
11189 /* Compute the width of the rectangle to draw. If on a stretch
11190 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11191 rectangle as wide as the glyph, but use a canonical character
11192 width instead. */
11193 wd = cursor_glyph->pixel_width - 1;
11194 if (cursor_glyph->type == STRETCH_GLYPH
11195 && !x_stretch_cursor_p)
11196 wd = min (CANON_X_UNIT (f), wd);
11198 /* The foreground of cursor_gc is typically the same as the normal
11199 background color, which can cause the cursor box to be invisible. */
11200 xgcv.foreground = f->output_data.x->cursor_pixel;
11201 if (dpyinfo->scratch_cursor_gc)
11202 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11203 else
11204 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11205 GCForeground, &xgcv);
11206 gc = dpyinfo->scratch_cursor_gc;
11208 /* Set clipping, draw the rectangle, and reset clipping again. */
11209 x_clip_to_row (w, row, gc, 0);
11210 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11211 XSetClipMask (dpy, gc, None);
11215 /* Draw a bar cursor on window W in glyph row ROW.
11217 Implementation note: One would like to draw a bar cursor with an
11218 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11219 Unfortunately, I didn't find a font yet that has this property set.
11220 --gerd. */
11222 static void
11223 x_draw_bar_cursor (w, row, width)
11224 struct window *w;
11225 struct glyph_row *row;
11226 int width;
11228 struct frame *f = XFRAME (w->frame);
11229 struct glyph *cursor_glyph;
11231 /* If cursor is out of bounds, don't draw garbage. This can happen
11232 in mini-buffer windows when switching between echo area glyphs
11233 and mini-buffer. */
11234 cursor_glyph = get_phys_cursor_glyph (w);
11235 if (cursor_glyph == NULL)
11236 return;
11238 /* If on an image, draw like a normal cursor. That's usually better
11239 visible than drawing a bar, esp. if the image is large so that
11240 the bar might not be in the window. */
11241 if (cursor_glyph->type == IMAGE_GLYPH)
11243 struct glyph_row *row;
11244 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11245 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11247 else
11249 Display *dpy = FRAME_X_DISPLAY (f);
11250 Window window = FRAME_X_WINDOW (f);
11251 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11252 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11253 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11254 XGCValues xgcv;
11256 /* If the glyph's background equals the color we normally draw
11257 the bar cursor in, the bar cursor in its normal color is
11258 invisible. Use the glyph's foreground color instead in this
11259 case, on the assumption that the glyph's colors are chosen so
11260 that the glyph is legible. */
11261 if (face->background == f->output_data.x->cursor_pixel)
11262 xgcv.background = xgcv.foreground = face->foreground;
11263 else
11264 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11265 xgcv.graphics_exposures = 0;
11267 if (gc)
11268 XChangeGC (dpy, gc, mask, &xgcv);
11269 else
11271 gc = XCreateGC (dpy, window, mask, &xgcv);
11272 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11275 if (width < 0)
11276 width = f->output_data.x->cursor_width;
11277 width = min (cursor_glyph->pixel_width, width);
11279 x_clip_to_row (w, row, gc, 0);
11280 XFillRectangle (dpy, window, gc,
11281 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11282 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11283 width, row->height);
11284 XSetClipMask (dpy, gc, None);
11289 /* Clear the cursor of window W to background color, and mark the
11290 cursor as not shown. This is used when the text where the cursor
11291 is is about to be rewritten. */
11293 static void
11294 x_clear_cursor (w)
11295 struct window *w;
11297 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11298 x_update_window_cursor (w, 0);
11302 /* Draw the cursor glyph of window W in glyph row ROW. See the
11303 comment of x_draw_glyphs for the meaning of HL. */
11305 static void
11306 x_draw_phys_cursor_glyph (w, row, hl)
11307 struct window *w;
11308 struct glyph_row *row;
11309 enum draw_glyphs_face hl;
11311 /* If cursor hpos is out of bounds, don't draw garbage. This can
11312 happen in mini-buffer windows when switching between echo area
11313 glyphs and mini-buffer. */
11314 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11316 int on_p = w->phys_cursor_on_p;
11318 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11319 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11320 hl, 0);
11321 w->phys_cursor_on_p = on_p;
11323 /* When we erase the cursor, and ROW is overlapped by other
11324 rows, make sure that these overlapping parts of other rows
11325 are redrawn. */
11326 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11328 if (row > w->current_matrix->rows
11329 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11330 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11332 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11333 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11334 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11340 /* Erase the image of a cursor of window W from the screen. */
11342 static void
11343 x_erase_phys_cursor (w)
11344 struct window *w;
11346 struct frame *f = XFRAME (w->frame);
11347 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11348 int hpos = w->phys_cursor.hpos;
11349 int vpos = w->phys_cursor.vpos;
11350 int mouse_face_here_p = 0;
11351 struct glyph_matrix *active_glyphs = w->current_matrix;
11352 struct glyph_row *cursor_row;
11353 struct glyph *cursor_glyph;
11354 enum draw_glyphs_face hl;
11356 /* No cursor displayed or row invalidated => nothing to do on the
11357 screen. */
11358 if (w->phys_cursor_type == NO_CURSOR)
11359 goto mark_cursor_off;
11361 /* VPOS >= active_glyphs->nrows means that window has been resized.
11362 Don't bother to erase the cursor. */
11363 if (vpos >= active_glyphs->nrows)
11364 goto mark_cursor_off;
11366 /* If row containing cursor is marked invalid, there is nothing we
11367 can do. */
11368 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11369 if (!cursor_row->enabled_p)
11370 goto mark_cursor_off;
11372 /* This can happen when the new row is shorter than the old one.
11373 In this case, either x_draw_glyphs or clear_end_of_line
11374 should have cleared the cursor. Note that we wouldn't be
11375 able to erase the cursor in this case because we don't have a
11376 cursor glyph at hand. */
11377 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11378 goto mark_cursor_off;
11380 /* If the cursor is in the mouse face area, redisplay that when
11381 we clear the cursor. */
11382 if (! NILP (dpyinfo->mouse_face_window)
11383 && w == XWINDOW (dpyinfo->mouse_face_window)
11384 && (vpos > dpyinfo->mouse_face_beg_row
11385 || (vpos == dpyinfo->mouse_face_beg_row
11386 && hpos >= dpyinfo->mouse_face_beg_col))
11387 && (vpos < dpyinfo->mouse_face_end_row
11388 || (vpos == dpyinfo->mouse_face_end_row
11389 && hpos < dpyinfo->mouse_face_end_col))
11390 /* Don't redraw the cursor's spot in mouse face if it is at the
11391 end of a line (on a newline). The cursor appears there, but
11392 mouse highlighting does not. */
11393 && cursor_row->used[TEXT_AREA] > hpos)
11394 mouse_face_here_p = 1;
11396 /* Maybe clear the display under the cursor. */
11397 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11399 int x;
11400 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11402 cursor_glyph = get_phys_cursor_glyph (w);
11403 if (cursor_glyph == NULL)
11404 goto mark_cursor_off;
11406 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11408 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11410 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11411 cursor_row->y)),
11412 cursor_glyph->pixel_width,
11413 cursor_row->visible_height,
11414 False);
11417 /* Erase the cursor by redrawing the character underneath it. */
11418 if (mouse_face_here_p)
11419 hl = DRAW_MOUSE_FACE;
11420 else
11421 hl = DRAW_NORMAL_TEXT;
11422 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11424 mark_cursor_off:
11425 w->phys_cursor_on_p = 0;
11426 w->phys_cursor_type = NO_CURSOR;
11430 /* Non-zero if physical cursor of window W is within mouse face. */
11432 static int
11433 cursor_in_mouse_face_p (w)
11434 struct window *w;
11436 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11437 int in_mouse_face = 0;
11439 if (WINDOWP (dpyinfo->mouse_face_window)
11440 && XWINDOW (dpyinfo->mouse_face_window) == w)
11442 int hpos = w->phys_cursor.hpos;
11443 int vpos = w->phys_cursor.vpos;
11445 if (vpos >= dpyinfo->mouse_face_beg_row
11446 && vpos <= dpyinfo->mouse_face_end_row
11447 && (vpos > dpyinfo->mouse_face_beg_row
11448 || hpos >= dpyinfo->mouse_face_beg_col)
11449 && (vpos < dpyinfo->mouse_face_end_row
11450 || hpos < dpyinfo->mouse_face_end_col
11451 || dpyinfo->mouse_face_past_end))
11452 in_mouse_face = 1;
11455 return in_mouse_face;
11459 /* Display or clear cursor of window W. If ON is zero, clear the
11460 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11461 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11463 void
11464 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11465 struct window *w;
11466 int on, hpos, vpos, x, y;
11468 struct frame *f = XFRAME (w->frame);
11469 int new_cursor_type;
11470 int new_cursor_width;
11471 struct glyph_matrix *current_glyphs;
11472 struct glyph_row *glyph_row;
11473 struct glyph *glyph;
11474 int cursor_non_selected;
11476 /* This is pointless on invisible frames, and dangerous on garbaged
11477 windows and frames; in the latter case, the frame or window may
11478 be in the midst of changing its size, and x and y may be off the
11479 window. */
11480 if (! FRAME_VISIBLE_P (f)
11481 || FRAME_GARBAGED_P (f)
11482 || vpos >= w->current_matrix->nrows
11483 || hpos >= w->current_matrix->matrix_w)
11484 return;
11486 /* If cursor is off and we want it off, return quickly. */
11487 if (!on && !w->phys_cursor_on_p)
11488 return;
11490 current_glyphs = w->current_matrix;
11491 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11492 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11494 /* If cursor row is not enabled, we don't really know where to
11495 display the cursor. */
11496 if (!glyph_row->enabled_p)
11498 w->phys_cursor_on_p = 0;
11499 return;
11502 xassert (interrupt_input_blocked);
11504 /* Set new_cursor_type to the cursor we want to be displayed. In a
11505 mini-buffer window, we want the cursor only to appear if we are
11506 reading input from this window. For the selected window, we want
11507 the cursor type given by the frame parameter. If explicitly
11508 marked off, draw no cursor. In all other cases, we want a hollow
11509 box cursor. */
11510 cursor_non_selected
11511 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
11512 w->buffer));
11513 new_cursor_width = -1;
11514 if (cursor_in_echo_area
11515 && FRAME_HAS_MINIBUF_P (f)
11516 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11518 if (w == XWINDOW (echo_area_window))
11519 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11520 else if (cursor_non_selected)
11521 new_cursor_type = HOLLOW_BOX_CURSOR;
11522 else
11523 new_cursor_type = NO_CURSOR;
11525 else
11527 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11528 || w != XWINDOW (f->selected_window))
11530 if ((MINI_WINDOW_P (w) && minibuf_level == 0)
11531 || !cursor_non_selected
11532 || NILP (XBUFFER (w->buffer)->cursor_type))
11533 new_cursor_type = NO_CURSOR;
11534 else
11535 new_cursor_type = HOLLOW_BOX_CURSOR;
11537 else if (w->cursor_off_p)
11538 new_cursor_type = NO_CURSOR;
11539 else
11541 struct buffer *b = XBUFFER (w->buffer);
11543 if (EQ (b->cursor_type, Qt))
11544 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11545 else
11546 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11547 &new_cursor_width);
11551 /* If cursor is currently being shown and we don't want it to be or
11552 it is in the wrong place, or the cursor type is not what we want,
11553 erase it. */
11554 if (w->phys_cursor_on_p
11555 && (!on
11556 || w->phys_cursor.x != x
11557 || w->phys_cursor.y != y
11558 || new_cursor_type != w->phys_cursor_type))
11559 x_erase_phys_cursor (w);
11561 /* If the cursor is now invisible and we want it to be visible,
11562 display it. */
11563 if (on && !w->phys_cursor_on_p)
11565 w->phys_cursor_ascent = glyph_row->ascent;
11566 w->phys_cursor_height = glyph_row->height;
11568 /* Set phys_cursor_.* before x_draw_.* is called because some
11569 of them may need the information. */
11570 w->phys_cursor.x = x;
11571 w->phys_cursor.y = glyph_row->y;
11572 w->phys_cursor.hpos = hpos;
11573 w->phys_cursor.vpos = vpos;
11574 w->phys_cursor_type = new_cursor_type;
11575 w->phys_cursor_on_p = 1;
11577 switch (new_cursor_type)
11579 case HOLLOW_BOX_CURSOR:
11580 x_draw_hollow_cursor (w, glyph_row);
11581 break;
11583 case FILLED_BOX_CURSOR:
11584 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11585 break;
11587 case BAR_CURSOR:
11588 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11589 break;
11591 case NO_CURSOR:
11592 break;
11594 default:
11595 abort ();
11598 #ifdef HAVE_X_I18N
11599 if (w == XWINDOW (f->selected_window))
11600 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11601 xic_set_preeditarea (w, x, y);
11602 #endif
11605 #ifndef XFlush
11606 if (updating_frame != f)
11607 XFlush (FRAME_X_DISPLAY (f));
11608 #endif
11612 /* Display the cursor on window W, or clear it. X and Y are window
11613 relative pixel coordinates. HPOS and VPOS are glyph matrix
11614 positions. If W is not the selected window, display a hollow
11615 cursor. ON non-zero means display the cursor at X, Y which
11616 correspond to HPOS, VPOS, otherwise it is cleared. */
11618 void
11619 x_display_cursor (w, on, hpos, vpos, x, y)
11620 struct window *w;
11621 int on, hpos, vpos, x, y;
11623 BLOCK_INPUT;
11624 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11625 UNBLOCK_INPUT;
11629 /* Display the cursor on window W, or clear it, according to ON_P.
11630 Don't change the cursor's position. */
11632 void
11633 x_update_cursor (f, on_p)
11634 struct frame *f;
11636 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11640 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11641 in the window tree rooted at W. */
11643 static void
11644 x_update_cursor_in_window_tree (w, on_p)
11645 struct window *w;
11646 int on_p;
11648 while (w)
11650 if (!NILP (w->hchild))
11651 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11652 else if (!NILP (w->vchild))
11653 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11654 else
11655 x_update_window_cursor (w, on_p);
11657 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11662 /* Switch the display of W's cursor on or off, according to the value
11663 of ON. */
11665 static void
11666 x_update_window_cursor (w, on)
11667 struct window *w;
11668 int on;
11670 /* Don't update cursor in windows whose frame is in the process
11671 of being deleted. */
11672 if (w->current_matrix)
11674 BLOCK_INPUT;
11675 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11676 w->phys_cursor.x, w->phys_cursor.y);
11677 UNBLOCK_INPUT;
11684 /* Icons. */
11686 /* Make the x-window of frame F use the gnu icon bitmap. */
11689 x_bitmap_icon (f, file)
11690 struct frame *f;
11691 Lisp_Object file;
11693 int bitmap_id;
11695 if (FRAME_X_WINDOW (f) == 0)
11696 return 1;
11698 /* Free up our existing icon bitmap if any. */
11699 if (f->output_data.x->icon_bitmap > 0)
11700 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11701 f->output_data.x->icon_bitmap = 0;
11703 if (STRINGP (file))
11704 bitmap_id = x_create_bitmap_from_file (f, file);
11705 else
11707 /* Create the GNU bitmap if necessary. */
11708 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11709 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11710 = x_create_bitmap_from_data (f, gnu_bits,
11711 gnu_width, gnu_height);
11713 /* The first time we create the GNU bitmap,
11714 this increments the ref-count one extra time.
11715 As a result, the GNU bitmap is never freed.
11716 That way, we don't have to worry about allocating it again. */
11717 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11719 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11722 x_wm_set_icon_pixmap (f, bitmap_id);
11723 f->output_data.x->icon_bitmap = bitmap_id;
11725 return 0;
11729 /* Make the x-window of frame F use a rectangle with text.
11730 Use ICON_NAME as the text. */
11733 x_text_icon (f, icon_name)
11734 struct frame *f;
11735 char *icon_name;
11737 if (FRAME_X_WINDOW (f) == 0)
11738 return 1;
11740 #ifdef HAVE_X11R4
11742 XTextProperty text;
11743 text.value = (unsigned char *) icon_name;
11744 text.encoding = XA_STRING;
11745 text.format = 8;
11746 text.nitems = strlen (icon_name);
11747 #ifdef USE_X_TOOLKIT
11748 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11749 &text);
11750 #else /* not USE_X_TOOLKIT */
11751 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11752 #endif /* not USE_X_TOOLKIT */
11754 #else /* not HAVE_X11R4 */
11755 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11756 #endif /* not HAVE_X11R4 */
11758 if (f->output_data.x->icon_bitmap > 0)
11759 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11760 f->output_data.x->icon_bitmap = 0;
11761 x_wm_set_icon_pixmap (f, 0);
11763 return 0;
11766 #define X_ERROR_MESSAGE_SIZE 200
11768 /* If non-nil, this should be a string.
11769 It means catch X errors and store the error message in this string. */
11771 static Lisp_Object x_error_message_string;
11773 /* An X error handler which stores the error message in
11774 x_error_message_string. This is called from x_error_handler if
11775 x_catch_errors is in effect. */
11777 static void
11778 x_error_catcher (display, error)
11779 Display *display;
11780 XErrorEvent *error;
11782 XGetErrorText (display, error->error_code,
11783 XSTRING (x_error_message_string)->data,
11784 X_ERROR_MESSAGE_SIZE);
11787 /* Begin trapping X errors for display DPY. Actually we trap X errors
11788 for all displays, but DPY should be the display you are actually
11789 operating on.
11791 After calling this function, X protocol errors no longer cause
11792 Emacs to exit; instead, they are recorded in the string
11793 stored in x_error_message_string.
11795 Calling x_check_errors signals an Emacs error if an X error has
11796 occurred since the last call to x_catch_errors or x_check_errors.
11798 Calling x_uncatch_errors resumes the normal error handling. */
11800 void x_check_errors ();
11801 static Lisp_Object x_catch_errors_unwind ();
11804 x_catch_errors (dpy)
11805 Display *dpy;
11807 int count = specpdl_ptr - specpdl;
11809 /* Make sure any errors from previous requests have been dealt with. */
11810 XSync (dpy, False);
11812 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11814 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11815 XSTRING (x_error_message_string)->data[0] = 0;
11817 return count;
11820 /* Unbind the binding that we made to check for X errors. */
11822 static Lisp_Object
11823 x_catch_errors_unwind (old_val)
11824 Lisp_Object old_val;
11826 x_error_message_string = old_val;
11827 return Qnil;
11830 /* If any X protocol errors have arrived since the last call to
11831 x_catch_errors or x_check_errors, signal an Emacs error using
11832 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11834 void
11835 x_check_errors (dpy, format)
11836 Display *dpy;
11837 char *format;
11839 /* Make sure to catch any errors incurred so far. */
11840 XSync (dpy, False);
11842 if (XSTRING (x_error_message_string)->data[0])
11843 error (format, XSTRING (x_error_message_string)->data);
11846 /* Nonzero if we had any X protocol errors
11847 since we did x_catch_errors on DPY. */
11850 x_had_errors_p (dpy)
11851 Display *dpy;
11853 /* Make sure to catch any errors incurred so far. */
11854 XSync (dpy, False);
11856 return XSTRING (x_error_message_string)->data[0] != 0;
11859 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11861 void
11862 x_clear_errors (dpy)
11863 Display *dpy;
11865 XSTRING (x_error_message_string)->data[0] = 0;
11868 /* Stop catching X protocol errors and let them make Emacs die.
11869 DPY should be the display that was passed to x_catch_errors.
11870 COUNT should be the value that was returned by
11871 the corresponding call to x_catch_errors. */
11873 void
11874 x_uncatch_errors (dpy, count)
11875 Display *dpy;
11876 int count;
11878 unbind_to (count, Qnil);
11881 #if 0
11882 static unsigned int x_wire_count;
11883 x_trace_wire ()
11885 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11887 #endif /* ! 0 */
11890 /* Handle SIGPIPE, which can happen when the connection to a server
11891 simply goes away. SIGPIPE is handled by x_connection_signal.
11892 Don't need to do anything, because the write which caused the
11893 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11894 which will do the appropriate cleanup for us. */
11896 static SIGTYPE
11897 x_connection_signal (signalnum) /* If we don't have an argument, */
11898 int signalnum; /* some compilers complain in signal calls. */
11900 #ifdef USG
11901 /* USG systems forget handlers when they are used;
11902 must reestablish each time */
11903 signal (signalnum, x_connection_signal);
11904 #endif /* USG */
11908 /************************************************************************
11909 Handling X errors
11910 ************************************************************************/
11912 /* Error message passed to x_connection_closed. */
11914 static char *error_msg;
11916 /* Function installed as fatal_error_signal_hook in
11917 x_connection_closed. Print the X error message, and exit normally,
11918 instead of dumping core when XtCloseDisplay fails. */
11920 static void
11921 x_fatal_error_signal ()
11923 fprintf (stderr, "%s\n", error_msg);
11924 exit (70);
11927 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11928 the text of an error message that lead to the connection loss. */
11930 static SIGTYPE
11931 x_connection_closed (dpy, error_message)
11932 Display *dpy;
11933 char *error_message;
11935 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11936 Lisp_Object frame, tail;
11937 int count;
11939 error_msg = (char *) alloca (strlen (error_message) + 1);
11940 strcpy (error_msg, error_message);
11941 handling_signal = 0;
11943 /* Prevent being called recursively because of an error condition
11944 below. Otherwise, we might end up with printing ``can't find per
11945 display information'' in the recursive call instead of printing
11946 the original message here. */
11947 count = x_catch_errors (dpy);
11949 /* We have to close the display to inform Xt that it doesn't
11950 exist anymore. If we don't, Xt will continue to wait for
11951 events from the display. As a consequence, a sequence of
11953 M-x make-frame-on-display RET :1 RET
11954 ...kill the new frame, so that we get an IO error...
11955 M-x make-frame-on-display RET :1 RET
11957 will indefinitely wait in Xt for events for display `:1', opened
11958 in the first class to make-frame-on-display.
11960 Closing the display is reported to lead to a bus error on
11961 OpenWindows in certain situations. I suspect that is a bug
11962 in OpenWindows. I don't know how to cicumvent it here. */
11964 #ifdef USE_X_TOOLKIT
11965 /* If DPYINFO is null, this means we didn't open the display
11966 in the first place, so don't try to close it. */
11967 if (dpyinfo)
11969 extern void (*fatal_error_signal_hook) P_ ((void));
11970 fatal_error_signal_hook = x_fatal_error_signal;
11971 XtCloseDisplay (dpy);
11972 fatal_error_signal_hook = NULL;
11974 #endif
11976 /* Indicate that this display is dead. */
11977 if (dpyinfo)
11978 dpyinfo->display = 0;
11980 /* First delete frames whose mini-buffers are on frames
11981 that are on the dead display. */
11982 FOR_EACH_FRAME (tail, frame)
11984 Lisp_Object minibuf_frame;
11985 minibuf_frame
11986 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11987 if (FRAME_X_P (XFRAME (frame))
11988 && FRAME_X_P (XFRAME (minibuf_frame))
11989 && ! EQ (frame, minibuf_frame)
11990 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11991 Fdelete_frame (frame, Qt);
11994 /* Now delete all remaining frames on the dead display.
11995 We are now sure none of these is used as the mini-buffer
11996 for another frame that we need to delete. */
11997 FOR_EACH_FRAME (tail, frame)
11998 if (FRAME_X_P (XFRAME (frame))
11999 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12001 /* Set this to t so that Fdelete_frame won't get confused
12002 trying to find a replacement. */
12003 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12004 Fdelete_frame (frame, Qt);
12007 if (dpyinfo)
12008 x_delete_display (dpyinfo);
12010 x_uncatch_errors (dpy, count);
12012 if (x_display_list == 0)
12014 fprintf (stderr, "%s\n", error_msg);
12015 shut_down_emacs (0, 0, Qnil);
12016 exit (70);
12019 /* Ordinary stack unwind doesn't deal with these. */
12020 #ifdef SIGIO
12021 sigunblock (sigmask (SIGIO));
12022 #endif
12023 sigunblock (sigmask (SIGALRM));
12024 TOTALLY_UNBLOCK_INPUT;
12026 clear_waiting_for_input ();
12027 error ("%s", error_msg);
12031 /* This is the usual handler for X protocol errors.
12032 It kills all frames on the display that we got the error for.
12033 If that was the only one, it prints an error message and kills Emacs. */
12035 static void
12036 x_error_quitter (display, error)
12037 Display *display;
12038 XErrorEvent *error;
12040 char buf[256], buf1[356];
12042 /* Note that there is no real way portable across R3/R4 to get the
12043 original error handler. */
12045 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12046 sprintf (buf1, "X protocol error: %s on protocol request %d",
12047 buf, error->request_code);
12048 x_connection_closed (display, buf1);
12052 /* This is the first-level handler for X protocol errors.
12053 It calls x_error_quitter or x_error_catcher. */
12055 static int
12056 x_error_handler (display, error)
12057 Display *display;
12058 XErrorEvent *error;
12060 if (! NILP (x_error_message_string))
12061 x_error_catcher (display, error);
12062 else
12063 x_error_quitter (display, error);
12064 return 0;
12067 /* This is the handler for X IO errors, always.
12068 It kills all frames on the display that we lost touch with.
12069 If that was the only one, it prints an error message and kills Emacs. */
12071 static int
12072 x_io_error_quitter (display)
12073 Display *display;
12075 char buf[256];
12077 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12078 x_connection_closed (display, buf);
12079 return 0;
12082 /* Changing the font of the frame. */
12084 /* Give frame F the font named FONTNAME as its default font, and
12085 return the full name of that font. FONTNAME may be a wildcard
12086 pattern; in that case, we choose some font that fits the pattern.
12087 The return value shows which font we chose. */
12089 Lisp_Object
12090 x_new_font (f, fontname)
12091 struct frame *f;
12092 register char *fontname;
12094 struct font_info *fontp
12095 = FS_LOAD_FONT (f, 0, fontname, -1);
12097 if (!fontp)
12098 return Qnil;
12100 f->output_data.x->font = (XFontStruct *) (fontp->font);
12101 f->output_data.x->baseline_offset = fontp->baseline_offset;
12102 f->output_data.x->fontset = -1;
12104 x_compute_fringe_widths (f, 1);
12106 /* Compute the scroll bar width in character columns. */
12107 if (f->scroll_bar_pixel_width > 0)
12109 int wid = FONT_WIDTH (f->output_data.x->font);
12110 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12112 else
12114 int wid = FONT_WIDTH (f->output_data.x->font);
12115 f->scroll_bar_cols = (14 + wid - 1) / wid;
12118 /* Now make the frame display the given font. */
12119 if (FRAME_X_WINDOW (f) != 0)
12121 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12122 f->output_data.x->font->fid);
12123 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12124 f->output_data.x->font->fid);
12125 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12126 f->output_data.x->font->fid);
12128 frame_update_line_height (f);
12130 /* Don't change the size of a tip frame; there's no point in
12131 doing it because it's done in Fx_show_tip, and it leads to
12132 problems because the tip frame has no widget. */
12133 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12134 x_set_window_size (f, 0, f->width, f->height);
12136 else
12137 /* If we are setting a new frame's font for the first time,
12138 there are no faces yet, so this font's height is the line height. */
12139 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12141 return build_string (fontp->full_name);
12144 /* Give frame F the fontset named FONTSETNAME as its default font, and
12145 return the full name of that fontset. FONTSETNAME may be a wildcard
12146 pattern; in that case, we choose some fontset that fits the pattern.
12147 The return value shows which fontset we chose. */
12149 Lisp_Object
12150 x_new_fontset (f, fontsetname)
12151 struct frame *f;
12152 char *fontsetname;
12154 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12155 Lisp_Object result;
12157 if (fontset < 0)
12158 return Qnil;
12160 if (f->output_data.x->fontset == fontset)
12161 /* This fontset is already set in frame F. There's nothing more
12162 to do. */
12163 return fontset_name (fontset);
12165 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
12167 if (!STRINGP (result))
12168 /* Can't load ASCII font. */
12169 return Qnil;
12171 /* Since x_new_font doesn't update any fontset information, do it now. */
12172 f->output_data.x->fontset = fontset;
12174 #ifdef HAVE_X_I18N
12175 if (FRAME_XIC (f)
12176 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12177 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
12178 #endif
12180 return build_string (fontsetname);
12183 /* Compute actual fringe widths */
12185 void
12186 x_compute_fringe_widths (f, redraw)
12187 struct frame *f;
12188 int redraw;
12190 int o_left = f->output_data.x->left_fringe_width;
12191 int o_right = f->output_data.x->right_fringe_width;
12192 int o_cols = f->output_data.x->fringe_cols;
12194 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12195 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12196 int left_fringe_width, right_fringe_width;
12198 if (!NILP (left_fringe))
12199 left_fringe = Fcdr (left_fringe);
12200 if (!NILP (right_fringe))
12201 right_fringe = Fcdr (right_fringe);
12203 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12204 XINT (left_fringe));
12205 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12206 XINT (right_fringe));
12208 if (left_fringe_width || right_fringe_width)
12210 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12211 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12212 int conf_wid = left_wid + right_wid;
12213 int font_wid = FONT_WIDTH (f->output_data.x->font);
12214 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12215 int real_wid = cols * font_wid;
12216 if (left_wid && right_wid)
12218 if (left_fringe_width < 0)
12220 /* Left fringe width is fixed, adjust right fringe if necessary */
12221 f->output_data.x->left_fringe_width = left_wid;
12222 f->output_data.x->right_fringe_width = real_wid - left_wid;
12224 else if (right_fringe_width < 0)
12226 /* Right fringe width is fixed, adjust left fringe if necessary */
12227 f->output_data.x->left_fringe_width = real_wid - right_wid;
12228 f->output_data.x->right_fringe_width = right_wid;
12230 else
12232 /* Adjust both fringes with an equal amount.
12233 Note that we are doing integer arithmetic here, so don't
12234 lose a pixel if the total width is an odd number. */
12235 int fill = real_wid - conf_wid;
12236 f->output_data.x->left_fringe_width = left_wid + fill/2;
12237 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12240 else if (left_fringe_width)
12242 f->output_data.x->left_fringe_width = real_wid;
12243 f->output_data.x->right_fringe_width = 0;
12245 else
12247 f->output_data.x->left_fringe_width = 0;
12248 f->output_data.x->right_fringe_width = real_wid;
12250 f->output_data.x->fringe_cols = cols;
12251 f->output_data.x->fringes_extra = real_wid;
12253 else
12255 f->output_data.x->left_fringe_width = 0;
12256 f->output_data.x->right_fringe_width = 0;
12257 f->output_data.x->fringe_cols = 0;
12258 f->output_data.x->fringes_extra = 0;
12261 if (redraw && FRAME_VISIBLE_P (f))
12262 if (o_left != f->output_data.x->left_fringe_width ||
12263 o_right != f->output_data.x->right_fringe_width ||
12264 o_cols != f->output_data.x->fringe_cols)
12265 redraw_frame (f);
12268 /***********************************************************************
12269 X Input Methods
12270 ***********************************************************************/
12272 #ifdef HAVE_X_I18N
12274 #ifdef HAVE_X11R6
12276 /* XIM destroy callback function, which is called whenever the
12277 connection to input method XIM dies. CLIENT_DATA contains a
12278 pointer to the x_display_info structure corresponding to XIM. */
12280 static void
12281 xim_destroy_callback (xim, client_data, call_data)
12282 XIM xim;
12283 XPointer client_data;
12284 XPointer call_data;
12286 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12287 Lisp_Object frame, tail;
12289 BLOCK_INPUT;
12291 /* No need to call XDestroyIC.. */
12292 FOR_EACH_FRAME (tail, frame)
12294 struct frame *f = XFRAME (frame);
12295 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12297 FRAME_XIC (f) = NULL;
12298 if (FRAME_XIC_FONTSET (f))
12300 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12301 FRAME_XIC_FONTSET (f) = NULL;
12306 /* No need to call XCloseIM. */
12307 dpyinfo->xim = NULL;
12308 XFree (dpyinfo->xim_styles);
12309 UNBLOCK_INPUT;
12312 #endif /* HAVE_X11R6 */
12314 /* Open the connection to the XIM server on display DPYINFO.
12315 RESOURCE_NAME is the resource name Emacs uses. */
12317 static void
12318 xim_open_dpy (dpyinfo, resource_name)
12319 struct x_display_info *dpyinfo;
12320 char *resource_name;
12322 #ifdef USE_XIM
12323 XIM xim;
12325 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12326 dpyinfo->xim = xim;
12328 if (xim)
12330 #ifdef HAVE_X11R6
12331 XIMCallback destroy;
12332 #endif
12334 /* Get supported styles and XIM values. */
12335 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12337 #ifdef HAVE_X11R6
12338 destroy.callback = xim_destroy_callback;
12339 destroy.client_data = (XPointer)dpyinfo;
12340 /* This isn't prototyped in OSF 5.0. */
12341 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12342 #endif
12345 #else /* not USE_XIM */
12346 dpyinfo->xim = NULL;
12347 #endif /* not USE_XIM */
12351 #ifdef HAVE_X11R6_XIM
12353 struct xim_inst_t
12355 struct x_display_info *dpyinfo;
12356 char *resource_name;
12359 /* XIM instantiate callback function, which is called whenever an XIM
12360 server is available. DISPLAY is teh display of the XIM.
12361 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12362 when the callback was registered. */
12364 static void
12365 xim_instantiate_callback (display, client_data, call_data)
12366 Display *display;
12367 XPointer client_data;
12368 XPointer call_data;
12370 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12371 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12373 /* We don't support multiple XIM connections. */
12374 if (dpyinfo->xim)
12375 return;
12377 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12379 /* Create XIC for the existing frames on the same display, as long
12380 as they have no XIC. */
12381 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12383 Lisp_Object tail, frame;
12385 BLOCK_INPUT;
12386 FOR_EACH_FRAME (tail, frame)
12388 struct frame *f = XFRAME (frame);
12390 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12391 if (FRAME_XIC (f) == NULL)
12393 create_frame_xic (f);
12394 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12395 xic_set_statusarea (f);
12396 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12398 struct window *w = XWINDOW (f->selected_window);
12399 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12404 UNBLOCK_INPUT;
12408 #endif /* HAVE_X11R6_XIM */
12411 /* Open a connection to the XIM server on display DPYINFO.
12412 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12413 connection only at the first time. On X11R6, open the connection
12414 in the XIM instantiate callback function. */
12416 static void
12417 xim_initialize (dpyinfo, resource_name)
12418 struct x_display_info *dpyinfo;
12419 char *resource_name;
12421 #ifdef USE_XIM
12422 #ifdef HAVE_X11R6_XIM
12423 struct xim_inst_t *xim_inst;
12424 int len;
12426 dpyinfo->xim = NULL;
12427 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12428 xim_inst->dpyinfo = dpyinfo;
12429 len = strlen (resource_name);
12430 xim_inst->resource_name = (char *) xmalloc (len + 1);
12431 bcopy (resource_name, xim_inst->resource_name, len + 1);
12432 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12433 resource_name, EMACS_CLASS,
12434 xim_instantiate_callback,
12435 /* Fixme: This is XPointer in
12436 XFree86 but (XPointer *) on
12437 Tru64, at least. */
12438 (XPointer) xim_inst);
12439 #else /* not HAVE_X11R6_XIM */
12440 dpyinfo->xim = NULL;
12441 xim_open_dpy (dpyinfo, resource_name);
12442 #endif /* not HAVE_X11R6_XIM */
12444 #else /* not USE_XIM */
12445 dpyinfo->xim = NULL;
12446 #endif /* not USE_XIM */
12450 /* Close the connection to the XIM server on display DPYINFO. */
12452 static void
12453 xim_close_dpy (dpyinfo)
12454 struct x_display_info *dpyinfo;
12456 #ifdef USE_XIM
12457 #ifdef HAVE_X11R6_XIM
12458 if (dpyinfo->display)
12459 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12460 NULL, EMACS_CLASS,
12461 xim_instantiate_callback, NULL);
12462 #endif /* not HAVE_X11R6_XIM */
12463 if (dpyinfo->display)
12464 XCloseIM (dpyinfo->xim);
12465 dpyinfo->xim = NULL;
12466 XFree (dpyinfo->xim_styles);
12467 #endif /* USE_XIM */
12470 #endif /* not HAVE_X11R6_XIM */
12474 /* Calculate the absolute position in frame F
12475 from its current recorded position values and gravity. */
12477 void
12478 x_calc_absolute_position (f)
12479 struct frame *f;
12481 Window child;
12482 int win_x = 0, win_y = 0;
12483 int flags = f->output_data.x->size_hint_flags;
12484 int this_window;
12486 /* We have nothing to do if the current position
12487 is already for the top-left corner. */
12488 if (! ((flags & XNegative) || (flags & YNegative)))
12489 return;
12491 #ifdef USE_X_TOOLKIT
12492 this_window = XtWindow (f->output_data.x->widget);
12493 #else
12494 this_window = FRAME_X_WINDOW (f);
12495 #endif
12497 /* Find the position of the outside upper-left corner of
12498 the inner window, with respect to the outer window.
12499 But do this only if we will need the results. */
12500 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12502 int count;
12504 BLOCK_INPUT;
12505 count = x_catch_errors (FRAME_X_DISPLAY (f));
12506 while (1)
12508 x_clear_errors (FRAME_X_DISPLAY (f));
12509 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12511 /* From-window, to-window. */
12512 this_window,
12513 f->output_data.x->parent_desc,
12515 /* From-position, to-position. */
12516 0, 0, &win_x, &win_y,
12518 /* Child of win. */
12519 &child);
12520 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12522 Window newroot, newparent = 0xdeadbeef;
12523 Window *newchildren;
12524 unsigned int nchildren;
12526 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12527 &newparent, &newchildren, &nchildren))
12528 break;
12530 XFree ((char *) newchildren);
12532 f->output_data.x->parent_desc = newparent;
12534 else
12535 break;
12538 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12539 UNBLOCK_INPUT;
12542 /* Treat negative positions as relative to the leftmost bottommost
12543 position that fits on the screen. */
12544 if (flags & XNegative)
12545 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12546 - 2 * f->output_data.x->border_width - win_x
12547 - PIXEL_WIDTH (f)
12548 + f->output_data.x->left_pos);
12551 int height = PIXEL_HEIGHT (f);
12553 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12554 /* Something is fishy here. When using Motif, starting Emacs with
12555 `-g -0-0', the frame appears too low by a few pixels.
12557 This seems to be so because initially, while Emacs is starting,
12558 the column widget's height and the frame's pixel height are
12559 different. The column widget's height is the right one. In
12560 later invocations, when Emacs is up, the frame's pixel height
12561 is right, though.
12563 It's not obvious where the initial small difference comes from.
12564 2000-12-01, gerd. */
12566 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12567 #endif
12569 if (flags & YNegative)
12570 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12571 - 2 * f->output_data.x->border_width
12572 - win_y
12573 - height
12574 + f->output_data.x->top_pos);
12577 /* The left_pos and top_pos
12578 are now relative to the top and left screen edges,
12579 so the flags should correspond. */
12580 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12583 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12584 to really change the position, and 0 when calling from
12585 x_make_frame_visible (in that case, XOFF and YOFF are the current
12586 position values). It is -1 when calling from x_set_frame_parameters,
12587 which means, do adjust for borders but don't change the gravity. */
12589 void
12590 x_set_offset (f, xoff, yoff, change_gravity)
12591 struct frame *f;
12592 register int xoff, yoff;
12593 int change_gravity;
12595 int modified_top, modified_left;
12597 if (change_gravity > 0)
12599 f->output_data.x->top_pos = yoff;
12600 f->output_data.x->left_pos = xoff;
12601 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12602 if (xoff < 0)
12603 f->output_data.x->size_hint_flags |= XNegative;
12604 if (yoff < 0)
12605 f->output_data.x->size_hint_flags |= YNegative;
12606 f->output_data.x->win_gravity = NorthWestGravity;
12608 x_calc_absolute_position (f);
12610 BLOCK_INPUT;
12611 x_wm_set_size_hint (f, (long) 0, 0);
12613 modified_left = f->output_data.x->left_pos;
12614 modified_top = f->output_data.x->top_pos;
12615 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12616 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12617 /* It is a mystery why we need to add the border_width here
12618 when the frame is already visible, but experiment says we do. */
12619 if (change_gravity != 0)
12621 modified_left += f->output_data.x->border_width;
12622 modified_top += f->output_data.x->border_width;
12624 #endif
12626 #ifdef USE_X_TOOLKIT
12627 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12628 modified_left, modified_top);
12629 #else /* not USE_X_TOOLKIT */
12630 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12631 modified_left, modified_top);
12632 #endif /* not USE_X_TOOLKIT */
12633 UNBLOCK_INPUT;
12637 /* Change the size of frame F's X window to COLS/ROWS in the case F
12638 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12639 top-left-corner window gravity for this size change and subsequent
12640 size changes. Otherwise we leave the window gravity unchanged. */
12642 static void
12643 x_set_window_size_1 (f, change_gravity, cols, rows)
12644 struct frame *f;
12645 int change_gravity;
12646 int cols, rows;
12648 int pixelwidth, pixelheight;
12650 check_frame_size (f, &rows, &cols);
12651 f->output_data.x->vertical_scroll_bar_extra
12652 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12654 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12655 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12656 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12658 x_compute_fringe_widths (f, 0);
12660 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12661 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12663 f->output_data.x->win_gravity = NorthWestGravity;
12664 x_wm_set_size_hint (f, (long) 0, 0);
12666 XSync (FRAME_X_DISPLAY (f), False);
12667 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12668 pixelwidth, pixelheight);
12670 /* Now, strictly speaking, we can't be sure that this is accurate,
12671 but the window manager will get around to dealing with the size
12672 change request eventually, and we'll hear how it went when the
12673 ConfigureNotify event gets here.
12675 We could just not bother storing any of this information here,
12676 and let the ConfigureNotify event set everything up, but that
12677 might be kind of confusing to the Lisp code, since size changes
12678 wouldn't be reported in the frame parameters until some random
12679 point in the future when the ConfigureNotify event arrives.
12681 We pass 1 for DELAY since we can't run Lisp code inside of
12682 a BLOCK_INPUT. */
12683 change_frame_size (f, rows, cols, 0, 1, 0);
12684 PIXEL_WIDTH (f) = pixelwidth;
12685 PIXEL_HEIGHT (f) = pixelheight;
12687 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12688 receive in the ConfigureNotify event; if we get what we asked
12689 for, then the event won't cause the screen to become garbaged, so
12690 we have to make sure to do it here. */
12691 SET_FRAME_GARBAGED (f);
12693 XFlush (FRAME_X_DISPLAY (f));
12697 /* Call this to change the size of frame F's x-window.
12698 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12699 for this size change and subsequent size changes.
12700 Otherwise we leave the window gravity unchanged. */
12702 void
12703 x_set_window_size (f, change_gravity, cols, rows)
12704 struct frame *f;
12705 int change_gravity;
12706 int cols, rows;
12708 BLOCK_INPUT;
12710 #ifdef USE_X_TOOLKIT
12712 if (f->output_data.x->widget != NULL)
12714 /* The x and y position of the widget is clobbered by the
12715 call to XtSetValues within EmacsFrameSetCharSize.
12716 This is a real kludge, but I don't understand Xt so I can't
12717 figure out a correct fix. Can anyone else tell me? -- rms. */
12718 int xpos = f->output_data.x->widget->core.x;
12719 int ypos = f->output_data.x->widget->core.y;
12720 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12721 f->output_data.x->widget->core.x = xpos;
12722 f->output_data.x->widget->core.y = ypos;
12724 else
12725 x_set_window_size_1 (f, change_gravity, cols, rows);
12727 #else /* not USE_X_TOOLKIT */
12729 x_set_window_size_1 (f, change_gravity, cols, rows);
12731 #endif /* not USE_X_TOOLKIT */
12733 /* If cursor was outside the new size, mark it as off. */
12734 mark_window_cursors_off (XWINDOW (f->root_window));
12736 /* Clear out any recollection of where the mouse highlighting was,
12737 since it might be in a place that's outside the new frame size.
12738 Actually checking whether it is outside is a pain in the neck,
12739 so don't try--just let the highlighting be done afresh with new size. */
12740 cancel_mouse_face (f);
12742 UNBLOCK_INPUT;
12745 /* Mouse warping. */
12747 void
12748 x_set_mouse_position (f, x, y)
12749 struct frame *f;
12750 int x, y;
12752 int pix_x, pix_y;
12754 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12755 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12757 if (pix_x < 0) pix_x = 0;
12758 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12760 if (pix_y < 0) pix_y = 0;
12761 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12763 BLOCK_INPUT;
12765 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12766 0, 0, 0, 0, pix_x, pix_y);
12767 UNBLOCK_INPUT;
12770 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12772 void
12773 x_set_mouse_pixel_position (f, pix_x, pix_y)
12774 struct frame *f;
12775 int pix_x, pix_y;
12777 BLOCK_INPUT;
12779 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12780 0, 0, 0, 0, pix_x, pix_y);
12781 UNBLOCK_INPUT;
12784 /* focus shifting, raising and lowering. */
12786 void
12787 x_focus_on_frame (f)
12788 struct frame *f;
12790 #if 0 /* This proves to be unpleasant. */
12791 x_raise_frame (f);
12792 #endif
12793 #if 0
12794 /* I don't think that the ICCCM allows programs to do things like this
12795 without the interaction of the window manager. Whatever you end up
12796 doing with this code, do it to x_unfocus_frame too. */
12797 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12798 RevertToPointerRoot, CurrentTime);
12799 #endif /* ! 0 */
12802 void
12803 x_unfocus_frame (f)
12804 struct frame *f;
12806 #if 0
12807 /* Look at the remarks in x_focus_on_frame. */
12808 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12809 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12810 RevertToPointerRoot, CurrentTime);
12811 #endif /* ! 0 */
12814 /* Raise frame F. */
12816 void
12817 x_raise_frame (f)
12818 struct frame *f;
12820 if (f->async_visible)
12822 BLOCK_INPUT;
12823 #ifdef USE_X_TOOLKIT
12824 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12825 #else /* not USE_X_TOOLKIT */
12826 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12827 #endif /* not USE_X_TOOLKIT */
12828 XFlush (FRAME_X_DISPLAY (f));
12829 UNBLOCK_INPUT;
12833 /* Lower frame F. */
12835 void
12836 x_lower_frame (f)
12837 struct frame *f;
12839 if (f->async_visible)
12841 BLOCK_INPUT;
12842 #ifdef USE_X_TOOLKIT
12843 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12844 #else /* not USE_X_TOOLKIT */
12845 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12846 #endif /* not USE_X_TOOLKIT */
12847 XFlush (FRAME_X_DISPLAY (f));
12848 UNBLOCK_INPUT;
12852 static void
12853 XTframe_raise_lower (f, raise_flag)
12854 FRAME_PTR f;
12855 int raise_flag;
12857 if (raise_flag)
12858 x_raise_frame (f);
12859 else
12860 x_lower_frame (f);
12863 /* Change of visibility. */
12865 /* This tries to wait until the frame is really visible.
12866 However, if the window manager asks the user where to position
12867 the frame, this will return before the user finishes doing that.
12868 The frame will not actually be visible at that time,
12869 but it will become visible later when the window manager
12870 finishes with it. */
12872 void
12873 x_make_frame_visible (f)
12874 struct frame *f;
12876 Lisp_Object type;
12877 int original_top, original_left;
12878 int retry_count = 2;
12880 retry:
12882 BLOCK_INPUT;
12884 type = x_icon_type (f);
12885 if (!NILP (type))
12886 x_bitmap_icon (f, type);
12888 if (! FRAME_VISIBLE_P (f))
12890 /* We test FRAME_GARBAGED_P here to make sure we don't
12891 call x_set_offset a second time
12892 if we get to x_make_frame_visible a second time
12893 before the window gets really visible. */
12894 if (! FRAME_ICONIFIED_P (f)
12895 && ! f->output_data.x->asked_for_visible)
12896 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12898 f->output_data.x->asked_for_visible = 1;
12900 if (! EQ (Vx_no_window_manager, Qt))
12901 x_wm_set_window_state (f, NormalState);
12902 #ifdef USE_X_TOOLKIT
12903 /* This was XtPopup, but that did nothing for an iconified frame. */
12904 XtMapWidget (f->output_data.x->widget);
12905 #else /* not USE_X_TOOLKIT */
12906 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12907 #endif /* not USE_X_TOOLKIT */
12908 #if 0 /* This seems to bring back scroll bars in the wrong places
12909 if the window configuration has changed. They seem
12910 to come back ok without this. */
12911 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12912 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12913 #endif
12916 XFlush (FRAME_X_DISPLAY (f));
12918 /* Synchronize to ensure Emacs knows the frame is visible
12919 before we do anything else. We do this loop with input not blocked
12920 so that incoming events are handled. */
12922 Lisp_Object frame;
12923 int count;
12924 /* This must be before UNBLOCK_INPUT
12925 since events that arrive in response to the actions above
12926 will set it when they are handled. */
12927 int previously_visible = f->output_data.x->has_been_visible;
12929 original_left = f->output_data.x->left_pos;
12930 original_top = f->output_data.x->top_pos;
12932 /* This must come after we set COUNT. */
12933 UNBLOCK_INPUT;
12935 /* We unblock here so that arriving X events are processed. */
12937 /* Now move the window back to where it was "supposed to be".
12938 But don't do it if the gravity is negative.
12939 When the gravity is negative, this uses a position
12940 that is 3 pixels too low. Perhaps that's really the border width.
12942 Don't do this if the window has never been visible before,
12943 because the window manager may choose the position
12944 and we don't want to override it. */
12946 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12947 && f->output_data.x->win_gravity == NorthWestGravity
12948 && previously_visible)
12950 Drawable rootw;
12951 int x, y;
12952 unsigned int width, height, border, depth;
12954 BLOCK_INPUT;
12956 /* On some window managers (such as FVWM) moving an existing
12957 window, even to the same place, causes the window manager
12958 to introduce an offset. This can cause the window to move
12959 to an unexpected location. Check the geometry (a little
12960 slow here) and then verify that the window is in the right
12961 place. If the window is not in the right place, move it
12962 there, and take the potential window manager hit. */
12963 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12964 &rootw, &x, &y, &width, &height, &border, &depth);
12966 if (original_left != x || original_top != y)
12967 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12968 original_left, original_top);
12970 UNBLOCK_INPUT;
12973 XSETFRAME (frame, f);
12975 /* Wait until the frame is visible. Process X events until a
12976 MapNotify event has been seen, or until we think we won't get a
12977 MapNotify at all.. */
12978 for (count = input_signal_count + 10;
12979 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12981 /* Force processing of queued events. */
12982 x_sync (f);
12984 /* Machines that do polling rather than SIGIO have been
12985 observed to go into a busy-wait here. So we'll fake an
12986 alarm signal to let the handler know that there's something
12987 to be read. We used to raise a real alarm, but it seems
12988 that the handler isn't always enabled here. This is
12989 probably a bug. */
12990 if (input_polling_used ())
12992 /* It could be confusing if a real alarm arrives while
12993 processing the fake one. Turn it off and let the
12994 handler reset it. */
12995 extern void poll_for_input_1 P_ ((void));
12996 int old_poll_suppress_count = poll_suppress_count;
12997 poll_suppress_count = 1;
12998 poll_for_input_1 ();
12999 poll_suppress_count = old_poll_suppress_count;
13002 /* See if a MapNotify event has been processed. */
13003 FRAME_SAMPLE_VISIBILITY (f);
13006 /* 2000-09-28: In
13008 (let ((f (selected-frame)))
13009 (iconify-frame f)
13010 (raise-frame f))
13012 the frame is not raised with various window managers on
13013 FreeBSD, Linux and Solaris. It turns out that, for some
13014 unknown reason, the call to XtMapWidget is completely ignored.
13015 Mapping the widget a second time works. */
13017 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13018 goto retry;
13022 /* Change from mapped state to withdrawn state. */
13024 /* Make the frame visible (mapped and not iconified). */
13026 void
13027 x_make_frame_invisible (f)
13028 struct frame *f;
13030 Window window;
13032 #ifdef USE_X_TOOLKIT
13033 /* Use the frame's outermost window, not the one we normally draw on. */
13034 window = XtWindow (f->output_data.x->widget);
13035 #else /* not USE_X_TOOLKIT */
13036 window = FRAME_X_WINDOW (f);
13037 #endif /* not USE_X_TOOLKIT */
13039 /* Don't keep the highlight on an invisible frame. */
13040 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13041 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13043 #if 0/* This might add unreliability; I don't trust it -- rms. */
13044 if (! f->async_visible && ! f->async_iconified)
13045 return;
13046 #endif
13048 BLOCK_INPUT;
13050 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13051 that the current position of the window is user-specified, rather than
13052 program-specified, so that when the window is mapped again, it will be
13053 placed at the same location, without forcing the user to position it
13054 by hand again (they have already done that once for this window.) */
13055 x_wm_set_size_hint (f, (long) 0, 1);
13057 #ifdef HAVE_X11R4
13059 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13060 DefaultScreen (FRAME_X_DISPLAY (f))))
13062 UNBLOCK_INPUT_RESIGNAL;
13063 error ("Can't notify window manager of window withdrawal");
13065 #else /* ! defined (HAVE_X11R4) */
13067 /* Tell the window manager what we're going to do. */
13068 if (! EQ (Vx_no_window_manager, Qt))
13070 XEvent unmap;
13072 unmap.xunmap.type = UnmapNotify;
13073 unmap.xunmap.window = window;
13074 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13075 unmap.xunmap.from_configure = False;
13076 if (! XSendEvent (FRAME_X_DISPLAY (f),
13077 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13078 False,
13079 SubstructureRedirectMaskSubstructureNotifyMask,
13080 &unmap))
13082 UNBLOCK_INPUT_RESIGNAL;
13083 error ("Can't notify window manager of withdrawal");
13087 /* Unmap the window ourselves. Cheeky! */
13088 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13089 #endif /* ! defined (HAVE_X11R4) */
13091 /* We can't distinguish this from iconification
13092 just by the event that we get from the server.
13093 So we can't win using the usual strategy of letting
13094 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13095 and synchronize with the server to make sure we agree. */
13096 f->visible = 0;
13097 FRAME_ICONIFIED_P (f) = 0;
13098 f->async_visible = 0;
13099 f->async_iconified = 0;
13101 x_sync (f);
13103 UNBLOCK_INPUT;
13106 /* Change window state from mapped to iconified. */
13108 void
13109 x_iconify_frame (f)
13110 struct frame *f;
13112 int result;
13113 Lisp_Object type;
13115 /* Don't keep the highlight on an invisible frame. */
13116 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13117 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13119 if (f->async_iconified)
13120 return;
13122 BLOCK_INPUT;
13124 FRAME_SAMPLE_VISIBILITY (f);
13126 type = x_icon_type (f);
13127 if (!NILP (type))
13128 x_bitmap_icon (f, type);
13130 #ifdef USE_X_TOOLKIT
13132 if (! FRAME_VISIBLE_P (f))
13134 if (! EQ (Vx_no_window_manager, Qt))
13135 x_wm_set_window_state (f, IconicState);
13136 /* This was XtPopup, but that did nothing for an iconified frame. */
13137 XtMapWidget (f->output_data.x->widget);
13138 /* The server won't give us any event to indicate
13139 that an invisible frame was changed to an icon,
13140 so we have to record it here. */
13141 f->iconified = 1;
13142 f->visible = 1;
13143 f->async_iconified = 1;
13144 f->async_visible = 0;
13145 UNBLOCK_INPUT;
13146 return;
13149 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13150 XtWindow (f->output_data.x->widget),
13151 DefaultScreen (FRAME_X_DISPLAY (f)));
13152 UNBLOCK_INPUT;
13154 if (!result)
13155 error ("Can't notify window manager of iconification");
13157 f->async_iconified = 1;
13158 f->async_visible = 0;
13161 BLOCK_INPUT;
13162 XFlush (FRAME_X_DISPLAY (f));
13163 UNBLOCK_INPUT;
13164 #else /* not USE_X_TOOLKIT */
13166 /* Make sure the X server knows where the window should be positioned,
13167 in case the user deiconifies with the window manager. */
13168 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13169 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13171 /* Since we don't know which revision of X we're running, we'll use both
13172 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13174 /* X11R4: send a ClientMessage to the window manager using the
13175 WM_CHANGE_STATE type. */
13177 XEvent message;
13179 message.xclient.window = FRAME_X_WINDOW (f);
13180 message.xclient.type = ClientMessage;
13181 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13182 message.xclient.format = 32;
13183 message.xclient.data.l[0] = IconicState;
13185 if (! XSendEvent (FRAME_X_DISPLAY (f),
13186 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13187 False,
13188 SubstructureRedirectMask | SubstructureNotifyMask,
13189 &message))
13191 UNBLOCK_INPUT_RESIGNAL;
13192 error ("Can't notify window manager of iconification");
13196 /* X11R3: set the initial_state field of the window manager hints to
13197 IconicState. */
13198 x_wm_set_window_state (f, IconicState);
13200 if (!FRAME_VISIBLE_P (f))
13202 /* If the frame was withdrawn, before, we must map it. */
13203 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13206 f->async_iconified = 1;
13207 f->async_visible = 0;
13209 XFlush (FRAME_X_DISPLAY (f));
13210 UNBLOCK_INPUT;
13211 #endif /* not USE_X_TOOLKIT */
13215 /* Free X resources of frame F. */
13217 void
13218 x_free_frame_resources (f)
13219 struct frame *f;
13221 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13222 Lisp_Object bar;
13223 struct scroll_bar *b;
13225 BLOCK_INPUT;
13227 /* If a display connection is dead, don't try sending more
13228 commands to the X server. */
13229 if (dpyinfo->display)
13231 if (f->output_data.x->icon_desc)
13232 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13234 #ifdef USE_X_TOOLKIT
13235 /* Explicitly destroy the scroll bars of the frame. Without
13236 this, we get "BadDrawable" errors from the toolkit later on,
13237 presumably from expose events generated for the disappearing
13238 toolkit scroll bars. */
13239 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13241 b = XSCROLL_BAR (bar);
13242 x_scroll_bar_remove (b);
13244 #endif
13246 #ifdef HAVE_X_I18N
13247 if (FRAME_XIC (f))
13248 free_frame_xic (f);
13249 #endif
13251 #ifdef USE_X_TOOLKIT
13252 if (f->output_data.x->widget)
13254 XtDestroyWidget (f->output_data.x->widget);
13255 f->output_data.x->widget = NULL;
13257 /* Tooltips don't have widgets, only a simple X window, even if
13258 we are using a toolkit. */
13259 else if (FRAME_X_WINDOW (f))
13260 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13262 free_frame_menubar (f);
13263 #else /* !USE_X_TOOLKIT */
13264 if (FRAME_X_WINDOW (f))
13265 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13266 #endif /* !USE_X_TOOLKIT */
13268 unload_color (f, f->output_data.x->foreground_pixel);
13269 unload_color (f, f->output_data.x->background_pixel);
13270 unload_color (f, f->output_data.x->cursor_pixel);
13271 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13272 unload_color (f, f->output_data.x->border_pixel);
13273 unload_color (f, f->output_data.x->mouse_pixel);
13275 if (f->output_data.x->scroll_bar_background_pixel != -1)
13276 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13277 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13278 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13279 #ifdef USE_TOOLKIT_SCROLL_BARS
13280 /* Scrollbar shadow colors. */
13281 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13282 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13283 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13284 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13285 #endif /* USE_TOOLKIT_SCROLL_BARS */
13286 if (f->output_data.x->white_relief.allocated_p)
13287 unload_color (f, f->output_data.x->white_relief.pixel);
13288 if (f->output_data.x->black_relief.allocated_p)
13289 unload_color (f, f->output_data.x->black_relief.pixel);
13291 if (FRAME_FACE_CACHE (f))
13292 free_frame_faces (f);
13294 x_free_gcs (f);
13295 XFlush (FRAME_X_DISPLAY (f));
13298 if (f->output_data.x->saved_menu_event)
13299 xfree (f->output_data.x->saved_menu_event);
13301 xfree (f->output_data.x);
13302 f->output_data.x = NULL;
13304 if (f == dpyinfo->x_focus_frame)
13305 dpyinfo->x_focus_frame = 0;
13306 if (f == dpyinfo->x_focus_event_frame)
13307 dpyinfo->x_focus_event_frame = 0;
13308 if (f == dpyinfo->x_highlight_frame)
13309 dpyinfo->x_highlight_frame = 0;
13311 if (f == dpyinfo->mouse_face_mouse_frame)
13313 dpyinfo->mouse_face_beg_row
13314 = dpyinfo->mouse_face_beg_col = -1;
13315 dpyinfo->mouse_face_end_row
13316 = dpyinfo->mouse_face_end_col = -1;
13317 dpyinfo->mouse_face_window = Qnil;
13318 dpyinfo->mouse_face_deferred_gc = 0;
13319 dpyinfo->mouse_face_mouse_frame = 0;
13322 UNBLOCK_INPUT;
13326 /* Destroy the X window of frame F. */
13328 void
13329 x_destroy_window (f)
13330 struct frame *f;
13332 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13334 /* If a display connection is dead, don't try sending more
13335 commands to the X server. */
13336 if (dpyinfo->display != 0)
13337 x_free_frame_resources (f);
13339 dpyinfo->reference_count--;
13343 /* Setting window manager hints. */
13345 /* Set the normal size hints for the window manager, for frame F.
13346 FLAGS is the flags word to use--or 0 meaning preserve the flags
13347 that the window now has.
13348 If USER_POSITION is nonzero, we set the USPosition
13349 flag (this is useful when FLAGS is 0). */
13351 void
13352 x_wm_set_size_hint (f, flags, user_position)
13353 struct frame *f;
13354 long flags;
13355 int user_position;
13357 XSizeHints size_hints;
13359 #ifdef USE_X_TOOLKIT
13360 Arg al[2];
13361 int ac = 0;
13362 Dimension widget_width, widget_height;
13363 Window window = XtWindow (f->output_data.x->widget);
13364 #else /* not USE_X_TOOLKIT */
13365 Window window = FRAME_X_WINDOW (f);
13366 #endif /* not USE_X_TOOLKIT */
13368 /* Setting PMaxSize caused various problems. */
13369 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13371 size_hints.x = f->output_data.x->left_pos;
13372 size_hints.y = f->output_data.x->top_pos;
13374 #ifdef USE_X_TOOLKIT
13375 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13376 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13377 XtGetValues (f->output_data.x->widget, al, ac);
13378 size_hints.height = widget_height;
13379 size_hints.width = widget_width;
13380 #else /* not USE_X_TOOLKIT */
13381 size_hints.height = PIXEL_HEIGHT (f);
13382 size_hints.width = PIXEL_WIDTH (f);
13383 #endif /* not USE_X_TOOLKIT */
13385 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13386 size_hints.height_inc = f->output_data.x->line_height;
13387 size_hints.max_width
13388 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13389 size_hints.max_height
13390 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13392 /* Calculate the base and minimum sizes.
13394 (When we use the X toolkit, we don't do it here.
13395 Instead we copy the values that the widgets are using, below.) */
13396 #ifndef USE_X_TOOLKIT
13398 int base_width, base_height;
13399 int min_rows = 0, min_cols = 0;
13401 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13402 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13404 check_frame_size (f, &min_rows, &min_cols);
13406 /* The window manager uses the base width hints to calculate the
13407 current number of rows and columns in the frame while
13408 resizing; min_width and min_height aren't useful for this
13409 purpose, since they might not give the dimensions for a
13410 zero-row, zero-column frame.
13412 We use the base_width and base_height members if we have
13413 them; otherwise, we set the min_width and min_height members
13414 to the size for a zero x zero frame. */
13416 #ifdef HAVE_X11R4
13417 size_hints.flags |= PBaseSize;
13418 size_hints.base_width = base_width;
13419 size_hints.base_height = base_height;
13420 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13421 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13422 #else
13423 size_hints.min_width = base_width;
13424 size_hints.min_height = base_height;
13425 #endif
13428 /* If we don't need the old flags, we don't need the old hint at all. */
13429 if (flags)
13431 size_hints.flags |= flags;
13432 goto no_read;
13434 #endif /* not USE_X_TOOLKIT */
13437 XSizeHints hints; /* Sometimes I hate X Windows... */
13438 long supplied_return;
13439 int value;
13441 #ifdef HAVE_X11R4
13442 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13443 &supplied_return);
13444 #else
13445 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13446 #endif
13448 #ifdef USE_X_TOOLKIT
13449 size_hints.base_height = hints.base_height;
13450 size_hints.base_width = hints.base_width;
13451 size_hints.min_height = hints.min_height;
13452 size_hints.min_width = hints.min_width;
13453 #endif
13455 if (flags)
13456 size_hints.flags |= flags;
13457 else
13459 if (value == 0)
13460 hints.flags = 0;
13461 if (hints.flags & PSize)
13462 size_hints.flags |= PSize;
13463 if (hints.flags & PPosition)
13464 size_hints.flags |= PPosition;
13465 if (hints.flags & USPosition)
13466 size_hints.flags |= USPosition;
13467 if (hints.flags & USSize)
13468 size_hints.flags |= USSize;
13472 #ifndef USE_X_TOOLKIT
13473 no_read:
13474 #endif
13476 #ifdef PWinGravity
13477 size_hints.win_gravity = f->output_data.x->win_gravity;
13478 size_hints.flags |= PWinGravity;
13480 if (user_position)
13482 size_hints.flags &= ~ PPosition;
13483 size_hints.flags |= USPosition;
13485 #endif /* PWinGravity */
13487 #ifdef HAVE_X11R4
13488 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13489 #else
13490 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13491 #endif
13494 /* Used for IconicState or NormalState */
13496 void
13497 x_wm_set_window_state (f, state)
13498 struct frame *f;
13499 int state;
13501 #ifdef USE_X_TOOLKIT
13502 Arg al[1];
13504 XtSetArg (al[0], XtNinitialState, state);
13505 XtSetValues (f->output_data.x->widget, al, 1);
13506 #else /* not USE_X_TOOLKIT */
13507 Window window = FRAME_X_WINDOW (f);
13509 f->output_data.x->wm_hints.flags |= StateHint;
13510 f->output_data.x->wm_hints.initial_state = state;
13512 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13513 #endif /* not USE_X_TOOLKIT */
13516 void
13517 x_wm_set_icon_pixmap (f, pixmap_id)
13518 struct frame *f;
13519 int pixmap_id;
13521 Pixmap icon_pixmap;
13523 #ifndef USE_X_TOOLKIT
13524 Window window = FRAME_X_WINDOW (f);
13525 #endif
13527 if (pixmap_id > 0)
13529 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13530 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13532 else
13534 /* It seems there is no way to turn off use of an icon pixmap.
13535 The following line does it, only if no icon has yet been created,
13536 for some window managers. But with mwm it crashes.
13537 Some people say it should clear the IconPixmapHint bit in this case,
13538 but that doesn't work, and the X consortium said it isn't the
13539 right thing at all. Since there is no way to win,
13540 best to explicitly give up. */
13541 #if 0
13542 f->output_data.x->wm_hints.icon_pixmap = None;
13543 #else
13544 return;
13545 #endif
13548 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13551 Arg al[1];
13552 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13553 XtSetValues (f->output_data.x->widget, al, 1);
13556 #else /* not USE_X_TOOLKIT */
13558 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13559 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13561 #endif /* not USE_X_TOOLKIT */
13564 void
13565 x_wm_set_icon_position (f, icon_x, icon_y)
13566 struct frame *f;
13567 int icon_x, icon_y;
13569 #ifdef USE_X_TOOLKIT
13570 Window window = XtWindow (f->output_data.x->widget);
13571 #else
13572 Window window = FRAME_X_WINDOW (f);
13573 #endif
13575 f->output_data.x->wm_hints.flags |= IconPositionHint;
13576 f->output_data.x->wm_hints.icon_x = icon_x;
13577 f->output_data.x->wm_hints.icon_y = icon_y;
13579 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13583 /***********************************************************************
13584 Fonts
13585 ***********************************************************************/
13587 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13589 struct font_info *
13590 x_get_font_info (f, font_idx)
13591 FRAME_PTR f;
13592 int font_idx;
13594 return (FRAME_X_FONT_TABLE (f) + font_idx);
13598 /* Return a list of names of available fonts matching PATTERN on frame F.
13600 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13601 to be listed.
13603 SIZE < 0 means include scalable fonts.
13605 Frame F null means we have not yet created any frame on X, and
13606 consult the first display in x_display_list. MAXNAMES sets a limit
13607 on how many fonts to match. */
13609 Lisp_Object
13610 x_list_fonts (f, pattern, size, maxnames)
13611 struct frame *f;
13612 Lisp_Object pattern;
13613 int size;
13614 int maxnames;
13616 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13617 Lisp_Object tem, second_best;
13618 struct x_display_info *dpyinfo
13619 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13620 Display *dpy = dpyinfo->display;
13621 int try_XLoadQueryFont = 0;
13622 int count;
13623 int allow_scalable_fonts_p = 0;
13625 if (size < 0)
13627 allow_scalable_fonts_p = 1;
13628 size = 0;
13631 patterns = Fassoc (pattern, Valternate_fontname_alist);
13632 if (NILP (patterns))
13633 patterns = Fcons (pattern, Qnil);
13635 if (maxnames == 1 && !size)
13636 /* We can return any single font matching PATTERN. */
13637 try_XLoadQueryFont = 1;
13639 for (; CONSP (patterns); patterns = XCDR (patterns))
13641 int num_fonts;
13642 char **names = NULL;
13644 pattern = XCAR (patterns);
13645 /* See if we cached the result for this particular query.
13646 The cache is an alist of the form:
13647 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13648 tem = XCDR (dpyinfo->name_list_element);
13649 key = Fcons (Fcons (pattern, make_number (maxnames)),
13650 allow_scalable_fonts_p ? Qt : Qnil);
13651 list = Fassoc (key, tem);
13652 if (!NILP (list))
13654 list = Fcdr_safe (list);
13655 /* We have a cashed list. Don't have to get the list again. */
13656 goto label_cached;
13659 /* At first, put PATTERN in the cache. */
13661 BLOCK_INPUT;
13662 count = x_catch_errors (dpy);
13664 if (try_XLoadQueryFont)
13666 XFontStruct *font;
13667 unsigned long value;
13669 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13670 if (x_had_errors_p (dpy))
13672 /* This error is perhaps due to insufficient memory on X
13673 server. Let's just ignore it. */
13674 font = NULL;
13675 x_clear_errors (dpy);
13678 if (font
13679 && XGetFontProperty (font, XA_FONT, &value))
13681 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13682 int len = strlen (name);
13683 char *tmp;
13685 /* If DXPC (a Differential X Protocol Compressor)
13686 Ver.3.7 is running, XGetAtomName will return null
13687 string. We must avoid such a name. */
13688 if (len == 0)
13689 try_XLoadQueryFont = 0;
13690 else
13692 num_fonts = 1;
13693 names = (char **) alloca (sizeof (char *));
13694 /* Some systems only allow alloca assigned to a
13695 simple var. */
13696 tmp = (char *) alloca (len + 1); names[0] = tmp;
13697 bcopy (name, names[0], len + 1);
13698 XFree (name);
13701 else
13702 try_XLoadQueryFont = 0;
13704 if (font)
13705 XFreeFont (dpy, font);
13708 if (!try_XLoadQueryFont)
13710 /* We try at least 10 fonts because XListFonts will return
13711 auto-scaled fonts at the head. */
13712 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13713 &num_fonts);
13714 if (x_had_errors_p (dpy))
13716 /* This error is perhaps due to insufficient memory on X
13717 server. Let's just ignore it. */
13718 names = NULL;
13719 x_clear_errors (dpy);
13723 x_uncatch_errors (dpy, count);
13724 UNBLOCK_INPUT;
13726 if (names)
13728 int i;
13730 /* Make a list of all the fonts we got back.
13731 Store that in the font cache for the display. */
13732 for (i = 0; i < num_fonts; i++)
13734 int width = 0;
13735 char *p = names[i];
13736 int average_width = -1, dashes = 0;
13738 /* Count the number of dashes in NAMES[I]. If there are
13739 14 dashes, and the field value following 12th dash
13740 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13741 is usually too ugly to be used for editing. Let's
13742 ignore it. */
13743 while (*p)
13744 if (*p++ == '-')
13746 dashes++;
13747 if (dashes == 7) /* PIXEL_SIZE field */
13748 width = atoi (p);
13749 else if (dashes == 12) /* AVERAGE_WIDTH field */
13750 average_width = atoi (p);
13753 if (allow_scalable_fonts_p
13754 || dashes < 14 || average_width != 0)
13756 tem = build_string (names[i]);
13757 if (NILP (Fassoc (tem, list)))
13759 if (STRINGP (Vx_pixel_size_width_font_regexp)
13760 && ((fast_c_string_match_ignore_case
13761 (Vx_pixel_size_width_font_regexp, names[i]))
13762 >= 0))
13763 /* We can set the value of PIXEL_SIZE to the
13764 width of this font. */
13765 list = Fcons (Fcons (tem, make_number (width)), list);
13766 else
13767 /* For the moment, width is not known. */
13768 list = Fcons (Fcons (tem, Qnil), list);
13773 if (!try_XLoadQueryFont)
13775 BLOCK_INPUT;
13776 XFreeFontNames (names);
13777 UNBLOCK_INPUT;
13781 /* Now store the result in the cache. */
13782 XSETCDR (dpyinfo->name_list_element,
13783 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
13785 label_cached:
13786 if (NILP (list)) continue; /* Try the remaining alternatives. */
13788 newlist = second_best = Qnil;
13789 /* Make a list of the fonts that have the right width. */
13790 for (; CONSP (list); list = XCDR (list))
13792 int found_size;
13794 tem = XCAR (list);
13796 if (!CONSP (tem) || NILP (XCAR (tem)))
13797 continue;
13798 if (!size)
13800 newlist = Fcons (XCAR (tem), newlist);
13801 continue;
13804 if (!INTEGERP (XCDR (tem)))
13806 /* Since we have not yet known the size of this font, we
13807 must try slow function call XLoadQueryFont. */
13808 XFontStruct *thisinfo;
13810 BLOCK_INPUT;
13811 count = x_catch_errors (dpy);
13812 thisinfo = XLoadQueryFont (dpy,
13813 XSTRING (XCAR (tem))->data);
13814 if (x_had_errors_p (dpy))
13816 /* This error is perhaps due to insufficient memory on X
13817 server. Let's just ignore it. */
13818 thisinfo = NULL;
13819 x_clear_errors (dpy);
13821 x_uncatch_errors (dpy, count);
13822 UNBLOCK_INPUT;
13824 if (thisinfo)
13826 XSETCDR (tem,
13827 (thisinfo->min_bounds.width == 0
13828 ? make_number (0)
13829 : make_number (thisinfo->max_bounds.width)));
13830 BLOCK_INPUT;
13831 XFreeFont (dpy, thisinfo);
13832 UNBLOCK_INPUT;
13834 else
13835 /* For unknown reason, the previous call of XListFont had
13836 returned a font which can't be opened. Record the size
13837 as 0 not to try to open it again. */
13838 XSETCDR (tem, make_number (0));
13841 found_size = XINT (XCDR (tem));
13842 if (found_size == size)
13843 newlist = Fcons (XCAR (tem), newlist);
13844 else if (found_size > 0)
13846 if (NILP (second_best))
13847 second_best = tem;
13848 else if (found_size < size)
13850 if (XINT (XCDR (second_best)) > size
13851 || XINT (XCDR (second_best)) < found_size)
13852 second_best = tem;
13854 else
13856 if (XINT (XCDR (second_best)) > size
13857 && XINT (XCDR (second_best)) > found_size)
13858 second_best = tem;
13862 if (!NILP (newlist))
13863 break;
13864 else if (!NILP (second_best))
13866 newlist = Fcons (XCAR (second_best), Qnil);
13867 break;
13871 return newlist;
13875 #if GLYPH_DEBUG
13877 /* Check that FONT is valid on frame F. It is if it can be found in F's
13878 font table. */
13880 static void
13881 x_check_font (f, font)
13882 struct frame *f;
13883 XFontStruct *font;
13885 int i;
13886 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13888 xassert (font != NULL);
13890 for (i = 0; i < dpyinfo->n_fonts; i++)
13891 if (dpyinfo->font_table[i].name
13892 && font == dpyinfo->font_table[i].font)
13893 break;
13895 xassert (i < dpyinfo->n_fonts);
13898 #endif /* GLYPH_DEBUG != 0 */
13900 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13901 Note: There are (broken) X fonts out there with invalid XFontStruct
13902 min_bounds contents. For example, handa@etl.go.jp reports that
13903 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13904 have font->min_bounds.width == 0. */
13906 static INLINE void
13907 x_font_min_bounds (font, w, h)
13908 XFontStruct *font;
13909 int *w, *h;
13911 *h = FONT_HEIGHT (font);
13912 *w = font->min_bounds.width;
13914 /* Try to handle the case where FONT->min_bounds has invalid
13915 contents. Since the only font known to have invalid min_bounds
13916 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13917 if (*w <= 0)
13918 *w = font->max_bounds.width;
13922 /* Compute the smallest character width and smallest font height over
13923 all fonts available on frame F. Set the members smallest_char_width
13924 and smallest_font_height in F's x_display_info structure to
13925 the values computed. Value is non-zero if smallest_font_height or
13926 smallest_char_width become smaller than they were before. */
13928 static int
13929 x_compute_min_glyph_bounds (f)
13930 struct frame *f;
13932 int i;
13933 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13934 XFontStruct *font;
13935 int old_width = dpyinfo->smallest_char_width;
13936 int old_height = dpyinfo->smallest_font_height;
13938 dpyinfo->smallest_font_height = 100000;
13939 dpyinfo->smallest_char_width = 100000;
13941 for (i = 0; i < dpyinfo->n_fonts; ++i)
13942 if (dpyinfo->font_table[i].name)
13944 struct font_info *fontp = dpyinfo->font_table + i;
13945 int w, h;
13947 font = (XFontStruct *) fontp->font;
13948 xassert (font != (XFontStruct *) ~0);
13949 x_font_min_bounds (font, &w, &h);
13951 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13952 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13955 xassert (dpyinfo->smallest_char_width > 0
13956 && dpyinfo->smallest_font_height > 0);
13958 return (dpyinfo->n_fonts == 1
13959 || dpyinfo->smallest_char_width < old_width
13960 || dpyinfo->smallest_font_height < old_height);
13964 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13965 pointer to the structure font_info while allocating it dynamically.
13966 If SIZE is 0, load any size of font.
13967 If loading is failed, return NULL. */
13969 struct font_info *
13970 x_load_font (f, fontname, size)
13971 struct frame *f;
13972 register char *fontname;
13973 int size;
13975 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13976 Lisp_Object font_names;
13977 int count;
13979 /* Get a list of all the fonts that match this name. Once we
13980 have a list of matching fonts, we compare them against the fonts
13981 we already have by comparing names. */
13982 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13984 if (!NILP (font_names))
13986 Lisp_Object tail;
13987 int i;
13989 for (i = 0; i < dpyinfo->n_fonts; i++)
13990 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13991 if (dpyinfo->font_table[i].name
13992 && (!strcmp (dpyinfo->font_table[i].name,
13993 XSTRING (XCAR (tail))->data)
13994 || !strcmp (dpyinfo->font_table[i].full_name,
13995 XSTRING (XCAR (tail))->data)))
13996 return (dpyinfo->font_table + i);
13999 /* Load the font and add it to the table. */
14001 char *full_name;
14002 XFontStruct *font;
14003 struct font_info *fontp;
14004 unsigned long value;
14005 int i;
14007 /* If we have found fonts by x_list_font, load one of them. If
14008 not, we still try to load a font by the name given as FONTNAME
14009 because XListFonts (called in x_list_font) of some X server has
14010 a bug of not finding a font even if the font surely exists and
14011 is loadable by XLoadQueryFont. */
14012 if (size > 0 && !NILP (font_names))
14013 fontname = (char *) XSTRING (XCAR (font_names))->data;
14015 BLOCK_INPUT;
14016 count = x_catch_errors (FRAME_X_DISPLAY (f));
14017 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14018 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14020 /* This error is perhaps due to insufficient memory on X
14021 server. Let's just ignore it. */
14022 font = NULL;
14023 x_clear_errors (FRAME_X_DISPLAY (f));
14025 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14026 UNBLOCK_INPUT;
14027 if (!font)
14028 return NULL;
14030 /* Find a free slot in the font table. */
14031 for (i = 0; i < dpyinfo->n_fonts; ++i)
14032 if (dpyinfo->font_table[i].name == NULL)
14033 break;
14035 /* If no free slot found, maybe enlarge the font table. */
14036 if (i == dpyinfo->n_fonts
14037 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14039 int sz;
14040 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14041 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14042 dpyinfo->font_table
14043 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14046 fontp = dpyinfo->font_table + i;
14047 if (i == dpyinfo->n_fonts)
14048 ++dpyinfo->n_fonts;
14050 /* Now fill in the slots of *FONTP. */
14051 BLOCK_INPUT;
14052 fontp->font = font;
14053 fontp->font_idx = i;
14054 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14055 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14057 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14058 full_name = 0;
14059 if (XGetFontProperty (font, XA_FONT, &value))
14061 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14062 char *p = name;
14063 int dashes = 0;
14065 /* Count the number of dashes in the "full name".
14066 If it is too few, this isn't really the font's full name,
14067 so don't use it.
14068 In X11R4, the fonts did not come with their canonical names
14069 stored in them. */
14070 while (*p)
14072 if (*p == '-')
14073 dashes++;
14074 p++;
14077 if (dashes >= 13)
14079 full_name = (char *) xmalloc (p - name + 1);
14080 bcopy (name, full_name, p - name + 1);
14083 XFree (name);
14086 if (full_name != 0)
14087 fontp->full_name = full_name;
14088 else
14089 fontp->full_name = fontp->name;
14091 fontp->size = font->max_bounds.width;
14092 fontp->height = FONT_HEIGHT (font);
14094 if (NILP (font_names))
14096 /* We come here because of a bug of XListFonts mentioned at
14097 the head of this block. Let's store this information in
14098 the cache for x_list_fonts. */
14099 Lisp_Object lispy_name = build_string (fontname);
14100 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14101 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14102 Qnil);
14104 XSETCDR (dpyinfo->name_list_element,
14105 Fcons (Fcons (key,
14106 Fcons (Fcons (lispy_full_name,
14107 make_number (fontp->size)),
14108 Qnil)),
14109 XCDR (dpyinfo->name_list_element)));
14110 if (full_name)
14112 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14113 Qnil);
14114 XSETCDR (dpyinfo->name_list_element,
14115 Fcons (Fcons (key,
14116 Fcons (Fcons (lispy_full_name,
14117 make_number (fontp->size)),
14118 Qnil)),
14119 XCDR (dpyinfo->name_list_element)));
14123 /* The slot `encoding' specifies how to map a character
14124 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14125 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14126 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14127 2:0xA020..0xFF7F). For the moment, we don't know which charset
14128 uses this font. So, we set information in fontp->encoding[1]
14129 which is never used by any charset. If mapping can't be
14130 decided, set FONT_ENCODING_NOT_DECIDED. */
14131 fontp->encoding[1]
14132 = (font->max_byte1 == 0
14133 /* 1-byte font */
14134 ? (font->min_char_or_byte2 < 0x80
14135 ? (font->max_char_or_byte2 < 0x80
14136 ? 0 /* 0x20..0x7F */
14137 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14138 : 1) /* 0xA0..0xFF */
14139 /* 2-byte font */
14140 : (font->min_byte1 < 0x80
14141 ? (font->max_byte1 < 0x80
14142 ? (font->min_char_or_byte2 < 0x80
14143 ? (font->max_char_or_byte2 < 0x80
14144 ? 0 /* 0x2020..0x7F7F */
14145 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14146 : 3) /* 0x20A0..0x7FFF */
14147 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14148 : (font->min_char_or_byte2 < 0x80
14149 ? (font->max_char_or_byte2 < 0x80
14150 ? 2 /* 0xA020..0xFF7F */
14151 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14152 : 1))); /* 0xA0A0..0xFFFF */
14154 fontp->baseline_offset
14155 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14156 ? (long) value : 0);
14157 fontp->relative_compose
14158 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14159 ? (long) value : 0);
14160 fontp->default_ascent
14161 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14162 ? (long) value : 0);
14164 /* Set global flag fonts_changed_p to non-zero if the font loaded
14165 has a character with a smaller width than any other character
14166 before, or if the font loaded has a smalle>r height than any
14167 other font loaded before. If this happens, it will make a
14168 glyph matrix reallocation necessary. */
14169 fonts_changed_p = x_compute_min_glyph_bounds (f);
14170 UNBLOCK_INPUT;
14171 return fontp;
14176 /* Return a pointer to struct font_info of a font named FONTNAME for
14177 frame F. If no such font is loaded, return NULL. */
14179 struct font_info *
14180 x_query_font (f, fontname)
14181 struct frame *f;
14182 register char *fontname;
14184 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14185 int i;
14187 for (i = 0; i < dpyinfo->n_fonts; i++)
14188 if (dpyinfo->font_table[i].name
14189 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14190 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14191 return (dpyinfo->font_table + i);
14192 return NULL;
14196 /* Find a CCL program for a font specified by FONTP, and set the member
14197 `encoder' of the structure. */
14199 void
14200 x_find_ccl_program (fontp)
14201 struct font_info *fontp;
14203 Lisp_Object list, elt;
14205 elt = Qnil;
14206 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14208 elt = XCAR (list);
14209 if (CONSP (elt)
14210 && STRINGP (XCAR (elt))
14211 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14212 >= 0)
14213 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14214 >= 0)))
14215 break;
14218 if (! NILP (list))
14220 struct ccl_program *ccl
14221 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14223 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14224 xfree (ccl);
14225 else
14226 fontp->font_encoder = ccl;
14232 /***********************************************************************
14233 Initialization
14234 ***********************************************************************/
14236 #ifdef USE_X_TOOLKIT
14237 static XrmOptionDescRec emacs_options[] = {
14238 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14239 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14241 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14242 XrmoptionSepArg, NULL},
14243 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14245 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14246 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14247 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14248 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14249 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14250 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14251 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14253 #endif /* USE_X_TOOLKIT */
14255 static int x_initialized;
14257 #ifdef MULTI_KBOARD
14258 /* Test whether two display-name strings agree up to the dot that separates
14259 the screen number from the server number. */
14260 static int
14261 same_x_server (name1, name2)
14262 char *name1, *name2;
14264 int seen_colon = 0;
14265 unsigned char *system_name = XSTRING (Vsystem_name)->data;
14266 int system_name_length = strlen (system_name);
14267 int length_until_period = 0;
14269 while (system_name[length_until_period] != 0
14270 && system_name[length_until_period] != '.')
14271 length_until_period++;
14273 /* Treat `unix' like an empty host name. */
14274 if (! strncmp (name1, "unix:", 5))
14275 name1 += 4;
14276 if (! strncmp (name2, "unix:", 5))
14277 name2 += 4;
14278 /* Treat this host's name like an empty host name. */
14279 if (! strncmp (name1, system_name, system_name_length)
14280 && name1[system_name_length] == ':')
14281 name1 += system_name_length;
14282 if (! strncmp (name2, system_name, system_name_length)
14283 && name2[system_name_length] == ':')
14284 name2 += system_name_length;
14285 /* Treat this host's domainless name like an empty host name. */
14286 if (! strncmp (name1, system_name, length_until_period)
14287 && name1[length_until_period] == ':')
14288 name1 += length_until_period;
14289 if (! strncmp (name2, system_name, length_until_period)
14290 && name2[length_until_period] == ':')
14291 name2 += length_until_period;
14293 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14295 if (*name1 == ':')
14296 seen_colon++;
14297 if (seen_colon && *name1 == '.')
14298 return 1;
14300 return (seen_colon
14301 && (*name1 == '.' || *name1 == '\0')
14302 && (*name2 == '.' || *name2 == '\0'));
14304 #endif
14306 struct x_display_info *
14307 x_term_init (display_name, xrm_option, resource_name)
14308 Lisp_Object display_name;
14309 char *xrm_option;
14310 char *resource_name;
14312 int connection;
14313 Display *dpy;
14314 struct x_display_info *dpyinfo;
14315 XrmDatabase xrdb;
14317 BLOCK_INPUT;
14319 if (!x_initialized)
14321 x_initialize ();
14322 x_initialized = 1;
14325 #ifdef USE_X_TOOLKIT
14326 /* weiner@footloose.sps.mot.com reports that this causes
14327 errors with X11R5:
14328 X protocol error: BadAtom (invalid Atom parameter)
14329 on protocol request 18skiloaf.
14330 So let's not use it until R6. */
14331 #ifdef HAVE_X11XTR6
14332 XtSetLanguageProc (NULL, NULL, NULL);
14333 #endif
14336 int argc = 0;
14337 char *argv[3];
14339 argv[0] = "";
14340 argc = 1;
14341 if (xrm_option)
14343 argv[argc++] = "-xrm";
14344 argv[argc++] = xrm_option;
14346 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
14347 resource_name, EMACS_CLASS,
14348 emacs_options, XtNumber (emacs_options),
14349 &argc, argv);
14351 #ifdef HAVE_X11XTR6
14352 /* I think this is to compensate for XtSetLanguageProc. */
14353 fixup_locale ();
14354 #endif
14357 #else /* not USE_X_TOOLKIT */
14358 #ifdef HAVE_X11R5
14359 XSetLocaleModifiers ("");
14360 #endif
14361 dpy = XOpenDisplay (XSTRING (display_name)->data);
14362 #endif /* not USE_X_TOOLKIT */
14364 /* Detect failure. */
14365 if (dpy == 0)
14367 UNBLOCK_INPUT;
14368 return 0;
14371 /* We have definitely succeeded. Record the new connection. */
14373 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14374 bzero (dpyinfo, sizeof *dpyinfo);
14376 #ifdef MULTI_KBOARD
14378 struct x_display_info *share;
14379 Lisp_Object tail;
14381 for (share = x_display_list, tail = x_display_name_list; share;
14382 share = share->next, tail = XCDR (tail))
14383 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
14384 XSTRING (display_name)->data))
14385 break;
14386 if (share)
14387 dpyinfo->kboard = share->kboard;
14388 else
14390 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14391 init_kboard (dpyinfo->kboard);
14392 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14394 char *vendor = ServerVendor (dpy);
14395 UNBLOCK_INPUT;
14396 dpyinfo->kboard->Vsystem_key_alist
14397 = call1 (Qvendor_specific_keysyms,
14398 build_string (vendor ? vendor : ""));
14399 BLOCK_INPUT;
14402 dpyinfo->kboard->next_kboard = all_kboards;
14403 all_kboards = dpyinfo->kboard;
14404 /* Don't let the initial kboard remain current longer than necessary.
14405 That would cause problems if a file loaded on startup tries to
14406 prompt in the mini-buffer. */
14407 if (current_kboard == initial_kboard)
14408 current_kboard = dpyinfo->kboard;
14410 dpyinfo->kboard->reference_count++;
14412 #endif
14414 /* Put this display on the chain. */
14415 dpyinfo->next = x_display_list;
14416 x_display_list = dpyinfo;
14418 /* Put it on x_display_name_list as well, to keep them parallel. */
14419 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14420 x_display_name_list);
14421 dpyinfo->name_list_element = XCAR (x_display_name_list);
14423 dpyinfo->display = dpy;
14425 #if 0
14426 XSetAfterFunction (x_current_display, x_trace_wire);
14427 #endif /* ! 0 */
14429 dpyinfo->x_id_name
14430 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14431 + STRING_BYTES (XSTRING (Vsystem_name))
14432 + 2);
14433 sprintf (dpyinfo->x_id_name, "%s@%s",
14434 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
14436 /* Figure out which modifier bits mean what. */
14437 x_find_modifier_meanings (dpyinfo);
14439 /* Get the scroll bar cursor. */
14440 dpyinfo->vertical_scroll_bar_cursor
14441 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14443 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14444 resource_name, EMACS_CLASS);
14445 #ifdef HAVE_XRMSETDATABASE
14446 XrmSetDatabase (dpyinfo->display, xrdb);
14447 #else
14448 dpyinfo->display->db = xrdb;
14449 #endif
14450 /* Put the rdb where we can find it in a way that works on
14451 all versions. */
14452 dpyinfo->xrdb = xrdb;
14454 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14455 DefaultScreen (dpyinfo->display));
14456 select_visual (dpyinfo);
14457 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14458 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14459 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14460 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14461 dpyinfo->grabbed = 0;
14462 dpyinfo->reference_count = 0;
14463 dpyinfo->icon_bitmap_id = -1;
14464 dpyinfo->font_table = NULL;
14465 dpyinfo->n_fonts = 0;
14466 dpyinfo->font_table_size = 0;
14467 dpyinfo->bitmaps = 0;
14468 dpyinfo->bitmaps_size = 0;
14469 dpyinfo->bitmaps_last = 0;
14470 dpyinfo->scratch_cursor_gc = 0;
14471 dpyinfo->mouse_face_mouse_frame = 0;
14472 dpyinfo->mouse_face_deferred_gc = 0;
14473 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14474 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14475 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14476 dpyinfo->mouse_face_window = Qnil;
14477 dpyinfo->mouse_face_overlay = Qnil;
14478 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14479 dpyinfo->mouse_face_defer = 0;
14480 dpyinfo->x_focus_frame = 0;
14481 dpyinfo->x_focus_event_frame = 0;
14482 dpyinfo->x_highlight_frame = 0;
14483 dpyinfo->image_cache = make_image_cache ();
14485 /* See if a private colormap is requested. */
14486 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14488 if (dpyinfo->visual->class == PseudoColor)
14490 Lisp_Object value;
14491 value = display_x_get_resource (dpyinfo,
14492 build_string ("privateColormap"),
14493 build_string ("PrivateColormap"),
14494 Qnil, Qnil);
14495 if (STRINGP (value)
14496 && (!strcmp (XSTRING (value)->data, "true")
14497 || !strcmp (XSTRING (value)->data, "on")))
14498 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14501 else
14502 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14503 dpyinfo->visual, AllocNone);
14506 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14507 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14508 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14509 dpyinfo->resy = pixels * 25.4 / mm;
14510 pixels = DisplayWidth (dpyinfo->display, screen_number);
14511 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14512 dpyinfo->resx = pixels * 25.4 / mm;
14515 dpyinfo->Xatom_wm_protocols
14516 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14517 dpyinfo->Xatom_wm_take_focus
14518 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14519 dpyinfo->Xatom_wm_save_yourself
14520 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14521 dpyinfo->Xatom_wm_delete_window
14522 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14523 dpyinfo->Xatom_wm_change_state
14524 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14525 dpyinfo->Xatom_wm_configure_denied
14526 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14527 dpyinfo->Xatom_wm_window_moved
14528 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14529 dpyinfo->Xatom_editres
14530 = XInternAtom (dpyinfo->display, "Editres", False);
14531 dpyinfo->Xatom_CLIPBOARD
14532 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14533 dpyinfo->Xatom_TIMESTAMP
14534 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14535 dpyinfo->Xatom_TEXT
14536 = XInternAtom (dpyinfo->display, "TEXT", False);
14537 dpyinfo->Xatom_COMPOUND_TEXT
14538 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14539 dpyinfo->Xatom_DELETE
14540 = XInternAtom (dpyinfo->display, "DELETE", False);
14541 dpyinfo->Xatom_MULTIPLE
14542 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14543 dpyinfo->Xatom_INCR
14544 = XInternAtom (dpyinfo->display, "INCR", False);
14545 dpyinfo->Xatom_EMACS_TMP
14546 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14547 dpyinfo->Xatom_TARGETS
14548 = XInternAtom (dpyinfo->display, "TARGETS", False);
14549 dpyinfo->Xatom_NULL
14550 = XInternAtom (dpyinfo->display, "NULL", False);
14551 dpyinfo->Xatom_ATOM_PAIR
14552 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14553 /* For properties of font. */
14554 dpyinfo->Xatom_PIXEL_SIZE
14555 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14556 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14557 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14558 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14559 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14560 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14561 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14563 /* Ghostscript support. */
14564 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14565 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14567 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14568 False);
14570 dpyinfo->cut_buffers_initialized = 0;
14572 connection = ConnectionNumber (dpyinfo->display);
14573 dpyinfo->connection = connection;
14576 char null_bits[1];
14578 null_bits[0] = 0x00;
14580 dpyinfo->null_pixel
14581 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14582 null_bits, 1, 1, (long) 0, (long) 0,
14587 extern int gray_bitmap_width, gray_bitmap_height;
14588 extern char *gray_bitmap_bits;
14589 dpyinfo->gray
14590 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14591 gray_bitmap_bits,
14592 gray_bitmap_width, gray_bitmap_height,
14593 (unsigned long) 1, (unsigned long) 0, 1);
14596 #ifdef HAVE_X_I18N
14597 xim_initialize (dpyinfo, resource_name);
14598 #endif
14600 #ifdef subprocesses
14601 /* This is only needed for distinguishing keyboard and process input. */
14602 if (connection != 0)
14603 add_keyboard_wait_descriptor (connection);
14604 #endif
14606 #ifndef F_SETOWN_BUG
14607 #ifdef F_SETOWN
14608 #ifdef F_SETOWN_SOCK_NEG
14609 /* stdin is a socket here */
14610 fcntl (connection, F_SETOWN, -getpid ());
14611 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14612 fcntl (connection, F_SETOWN, getpid ());
14613 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14614 #endif /* ! defined (F_SETOWN) */
14615 #endif /* F_SETOWN_BUG */
14617 #ifdef SIGIO
14618 if (interrupt_input)
14619 init_sigio (connection);
14620 #endif /* ! defined (SIGIO) */
14622 #ifdef USE_LUCID
14623 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14624 /* Make sure that we have a valid font for dialog boxes
14625 so that Xt does not crash. */
14627 Display *dpy = dpyinfo->display;
14628 XrmValue d, fr, to;
14629 Font font;
14630 int count;
14632 d.addr = (XPointer)&dpy;
14633 d.size = sizeof (Display *);
14634 fr.addr = XtDefaultFont;
14635 fr.size = sizeof (XtDefaultFont);
14636 to.size = sizeof (Font *);
14637 to.addr = (XPointer)&font;
14638 count = x_catch_errors (dpy);
14639 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14640 abort ();
14641 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14642 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14643 x_uncatch_errors (dpy, count);
14645 #endif
14646 #endif
14648 /* See if we should run in synchronous mode. This is useful
14649 for debugging X code. */
14651 Lisp_Object value;
14652 value = display_x_get_resource (dpyinfo,
14653 build_string ("synchronous"),
14654 build_string ("Synchronous"),
14655 Qnil, Qnil);
14656 if (STRINGP (value)
14657 && (!strcmp (XSTRING (value)->data, "true")
14658 || !strcmp (XSTRING (value)->data, "on")))
14659 XSynchronize (dpyinfo->display, True);
14662 UNBLOCK_INPUT;
14664 return dpyinfo;
14667 /* Get rid of display DPYINFO, assuming all frames are already gone,
14668 and without sending any more commands to the X server. */
14670 void
14671 x_delete_display (dpyinfo)
14672 struct x_display_info *dpyinfo;
14674 delete_keyboard_wait_descriptor (dpyinfo->connection);
14676 /* Discard this display from x_display_name_list and x_display_list.
14677 We can't use Fdelq because that can quit. */
14678 if (! NILP (x_display_name_list)
14679 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14680 x_display_name_list = XCDR (x_display_name_list);
14681 else
14683 Lisp_Object tail;
14685 tail = x_display_name_list;
14686 while (CONSP (tail) && CONSP (XCDR (tail)))
14688 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14690 XSETCDR (tail, XCDR (XCDR (tail)));
14691 break;
14693 tail = XCDR (tail);
14697 if (next_noop_dpyinfo == dpyinfo)
14698 next_noop_dpyinfo = dpyinfo->next;
14700 if (x_display_list == dpyinfo)
14701 x_display_list = dpyinfo->next;
14702 else
14704 struct x_display_info *tail;
14706 for (tail = x_display_list; tail; tail = tail->next)
14707 if (tail->next == dpyinfo)
14708 tail->next = tail->next->next;
14711 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14712 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14713 XrmDestroyDatabase (dpyinfo->xrdb);
14714 #endif
14715 #endif
14716 #ifdef MULTI_KBOARD
14717 if (--dpyinfo->kboard->reference_count == 0)
14718 delete_kboard (dpyinfo->kboard);
14719 #endif
14720 #ifdef HAVE_X_I18N
14721 if (dpyinfo->xim)
14722 xim_close_dpy (dpyinfo);
14723 #endif
14725 xfree (dpyinfo->font_table);
14726 xfree (dpyinfo->x_id_name);
14727 xfree (dpyinfo->color_cells);
14728 xfree (dpyinfo);
14732 /* Set up use of X before we make the first connection. */
14734 static struct redisplay_interface x_redisplay_interface =
14736 x_produce_glyphs,
14737 x_write_glyphs,
14738 x_insert_glyphs,
14739 x_clear_end_of_line,
14740 x_scroll_run,
14741 x_after_update_window_line,
14742 x_update_window_begin,
14743 x_update_window_end,
14744 XTcursor_to,
14745 x_flush,
14746 x_clear_mouse_face,
14747 x_get_glyph_overhangs,
14748 x_fix_overlapping_area
14751 void
14752 x_initialize ()
14754 rif = &x_redisplay_interface;
14756 clear_frame_hook = x_clear_frame;
14757 ins_del_lines_hook = x_ins_del_lines;
14758 delete_glyphs_hook = x_delete_glyphs;
14759 ring_bell_hook = XTring_bell;
14760 reset_terminal_modes_hook = XTreset_terminal_modes;
14761 set_terminal_modes_hook = XTset_terminal_modes;
14762 update_begin_hook = x_update_begin;
14763 update_end_hook = x_update_end;
14764 set_terminal_window_hook = XTset_terminal_window;
14765 read_socket_hook = XTread_socket;
14766 frame_up_to_date_hook = XTframe_up_to_date;
14767 mouse_position_hook = XTmouse_position;
14768 frame_rehighlight_hook = XTframe_rehighlight;
14769 frame_raise_lower_hook = XTframe_raise_lower;
14770 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14771 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14772 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14773 judge_scroll_bars_hook = XTjudge_scroll_bars;
14774 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14776 scroll_region_ok = 1; /* we'll scroll partial frames */
14777 char_ins_del_ok = 1;
14778 line_ins_del_ok = 1; /* we'll just blt 'em */
14779 fast_clear_end_of_line = 1; /* X does this well */
14780 memory_below_frame = 0; /* we don't remember what scrolls
14781 off the bottom */
14782 baud_rate = 19200;
14784 x_noop_count = 0;
14785 last_tool_bar_item = -1;
14786 any_help_event_p = 0;
14788 /* Try to use interrupt input; if we can't, then start polling. */
14789 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14791 #ifdef USE_X_TOOLKIT
14792 XtToolkitInitialize ();
14794 Xt_app_con = XtCreateApplicationContext ();
14796 /* Register a converter from strings to pixels, which uses
14797 Emacs' color allocation infrastructure. */
14798 XtAppSetTypeConverter (Xt_app_con,
14799 XtRString, XtRPixel, cvt_string_to_pixel,
14800 cvt_string_to_pixel_args,
14801 XtNumber (cvt_string_to_pixel_args),
14802 XtCacheByDisplay, cvt_pixel_dtor);
14804 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14806 /* Install an asynchronous timer that processes Xt timeout events
14807 every 0.1s. This is necessary because some widget sets use
14808 timeouts internally, for example the LessTif menu bar, or the
14809 Xaw3d scroll bar. When Xt timouts aren't processed, these
14810 widgets don't behave normally. */
14812 EMACS_TIME interval;
14813 EMACS_SET_SECS_USECS (interval, 0, 100000);
14814 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14816 #endif
14818 #ifdef USE_TOOLKIT_SCROLL_BARS
14819 xaw3d_arrow_scroll = False;
14820 xaw3d_pick_top = True;
14821 #endif
14823 /* Note that there is no real way portable across R3/R4 to get the
14824 original error handler. */
14825 XSetErrorHandler (x_error_handler);
14826 XSetIOErrorHandler (x_io_error_quitter);
14828 /* Disable Window Change signals; they are handled by X events. */
14829 #ifdef SIGWINCH
14830 signal (SIGWINCH, SIG_DFL);
14831 #endif /* ! defined (SIGWINCH) */
14833 signal (SIGPIPE, x_connection_signal);
14837 void
14838 syms_of_xterm ()
14840 staticpro (&x_error_message_string);
14841 x_error_message_string = Qnil;
14843 staticpro (&x_display_name_list);
14844 x_display_name_list = Qnil;
14846 staticpro (&last_mouse_scroll_bar);
14847 last_mouse_scroll_bar = Qnil;
14849 staticpro (&Qvendor_specific_keysyms);
14850 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14852 staticpro (&last_mouse_press_frame);
14853 last_mouse_press_frame = Qnil;
14855 help_echo = Qnil;
14856 staticpro (&help_echo);
14857 help_echo_object = Qnil;
14858 staticpro (&help_echo_object);
14859 help_echo_window = Qnil;
14860 staticpro (&help_echo_window);
14861 previous_help_echo = Qnil;
14862 staticpro (&previous_help_echo);
14863 help_echo_pos = -1;
14865 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14866 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
14867 For example, if a block cursor is over a tab, it will be drawn as
14868 wide as that tab on the display. */);
14869 x_stretch_cursor_p = 0;
14871 DEFVAR_BOOL ("x-use-underline-position-properties",
14872 &x_use_underline_position_properties,
14873 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
14874 Nil means ignore them. If you encounter fonts with bogus
14875 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
14876 to 4.1, set this to nil. */);
14877 x_use_underline_position_properties = 1;
14879 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14880 doc: /* What X toolkit scroll bars Emacs uses.
14881 A value of nil means Emacs doesn't use X toolkit scroll bars.
14882 Otherwise, value is a symbol describing the X toolkit. */);
14883 #ifdef USE_TOOLKIT_SCROLL_BARS
14884 #ifdef USE_MOTIF
14885 Vx_toolkit_scroll_bars = intern ("motif");
14886 #elif defined HAVE_XAW3D
14887 Vx_toolkit_scroll_bars = intern ("xaw3d");
14888 #else
14889 Vx_toolkit_scroll_bars = intern ("xaw");
14890 #endif
14891 #else
14892 Vx_toolkit_scroll_bars = Qnil;
14893 #endif
14895 staticpro (&last_mouse_motion_frame);
14896 last_mouse_motion_frame = Qnil;
14899 #endif /* HAVE_X_WINDOWS */