(read-passwd): Clear command history after each
[emacs.git] / src / xterm.c
blob4996f6e4dfecdd0eef67e7bb169d9b37d3f89efe
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 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "disptab.h"
85 #include "buffer.h"
86 #include "window.h"
87 #include "keyboard.h"
88 #include "intervals.h"
89 #include "process.h"
90 #include "atimer.h"
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
96 #ifdef HAVE_SYS_TIME_H
97 #include <sys/time.h>
98 #endif
99 #ifdef HAVE_UNISTD_H
100 #include <unistd.h>
101 #endif
103 #ifdef USE_X_TOOLKIT
105 extern void free_frame_menubar P_ ((struct frame *));
106 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110 #define HACK_EDITRES
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
114 /* Include toolkit specific headers for the scroll bar widget. */
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #else /* !USE_MOTIF i.e. use Xaw */
122 #ifdef HAVE_XAW3D
123 #include <X11/Xaw3d/Simple.h>
124 #include <X11/Xaw3d/Scrollbar.h>
125 #define ARROW_SCROLLBAR
126 #include <X11/Xaw3d/ScrollbarP.h>
127 #else /* !HAVE_XAW3D */
128 #include <X11/Xaw/Simple.h>
129 #include <X11/Xaw/Scrollbar.h>
130 #endif /* !HAVE_XAW3D */
131 #ifndef XtNpickTop
132 #define XtNpickTop "pickTop"
133 #endif /* !XtNpickTop */
134 #endif /* !USE_MOTIF */
135 #endif /* USE_TOOLKIT_SCROLL_BARS */
137 #endif /* USE_X_TOOLKIT */
139 #ifndef USE_X_TOOLKIT
140 #define x_any_window_to_frame x_window_to_frame
141 #define x_top_window_to_frame x_window_to_frame
142 #endif
144 #ifdef USE_X_TOOLKIT
145 #include "widget.h"
146 #ifndef XtNinitialState
147 #define XtNinitialState "initialState"
148 #endif
149 #endif
151 #ifndef min
152 #define min(a,b) ((a) < (b) ? (a) : (b))
153 #endif
154 #ifndef max
155 #define max(a,b) ((a) > (b) ? (a) : (b))
156 #endif
158 #define abs(x) ((x) < 0 ? -(x) : (x))
160 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
163 /* Bitmaps for truncated lines. */
165 enum bitmap_type
167 NO_BITMAP,
168 LEFT_TRUNCATION_BITMAP,
169 RIGHT_TRUNCATION_BITMAP,
170 OVERLAY_ARROW_BITMAP,
171 CONTINUED_LINE_BITMAP,
172 CONTINUATION_LINE_BITMAP,
173 ZV_LINE_BITMAP
176 /* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
179 #define zv_width 8
180 #define zv_height 8
181 static unsigned char zv_bits[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184 /* An arrow like this: `<-'. */
186 #define left_width 8
187 #define left_height 8
188 static unsigned char left_bits[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191 /* Right truncation arrow bitmap `->'. */
193 #define right_width 8
194 #define right_height 8
195 static unsigned char right_bits[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198 /* Marker for continued lines. */
200 #define continued_width 8
201 #define continued_height 8
202 static unsigned char continued_bits[] = {
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205 /* Marker for continuation lines. */
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits[] = {
210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
212 /* Overlay arrow bitmap. */
214 #if 0
215 /* A bomb. */
216 #define ov_width 8
217 #define ov_height 8
218 static unsigned char ov_bits[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
220 #else
221 /* A triangular arrow. */
222 #define ov_width 8
223 #define ov_height 8
224 static unsigned char ov_bits[] = {
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
227 #endif
229 extern Lisp_Object Qhelp_echo;
232 /* Non-nil means Emacs uses toolkit scroll bars. */
234 Lisp_Object Vx_toolkit_scroll_bars;
236 /* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
239 static Lisp_Object help_echo;
240 static Lisp_Object help_echo_window;
241 static Lisp_Object help_echo_object;
242 static int help_echo_pos;
244 /* Temporary variable for XTread_socket. */
246 static Lisp_Object previous_help_echo;
248 /* Non-zero means that a HELP_EVENT has been generated since Emacs
249 start. */
251 static int any_help_event_p;
253 /* Non-zero means draw block and hollow cursor as wide as the glyph
254 under it. For example, if a block cursor is over a tab, it will be
255 drawn as wide as that tab on the display. */
257 int x_stretch_cursor_p;
259 /* This is a chain of structures for all the X displays currently in
260 use. */
262 struct x_display_info *x_display_list;
264 /* This is a list of cons cells, each of the form (NAME
265 . FONT-LIST-CACHE), one for each element of x_display_list and in
266 the same order. NAME is the name of the frame. FONT-LIST-CACHE
267 records previous values returned by x-list-fonts. */
269 Lisp_Object x_display_name_list;
271 /* Frame being updated by update_frame. This is declared in term.c.
272 This is set by update_begin and looked at by all the XT functions.
273 It is zero while not inside an update. In that case, the XT
274 functions assume that `selected_frame' is the frame to apply to. */
276 extern struct frame *updating_frame;
278 extern int waiting_for_input;
280 /* This is a frame waiting to be auto-raised, within XTread_socket. */
282 struct frame *pending_autoraise_frame;
284 #ifdef USE_X_TOOLKIT
285 /* The application context for Xt use. */
286 XtAppContext Xt_app_con;
287 static String Xt_default_resources[] = {0};
288 #endif /* USE_X_TOOLKIT */
290 /* Nominal cursor position -- where to draw output.
291 HPOS and VPOS are window relative glyph matrix coordinates.
292 X and Y are window relative pixel coordinates. */
294 struct cursor_pos output_cursor;
296 /* Non-zero means user is interacting with a toolkit scroll bar. */
298 static int toolkit_scroll_bar_interaction;
300 /* Mouse movement.
302 Formerly, we used PointerMotionHintMask (in standard_event_mask)
303 so that we would have to call XQueryPointer after each MotionNotify
304 event to ask for another such event. However, this made mouse tracking
305 slow, and there was a bug that made it eventually stop.
307 Simply asking for MotionNotify all the time seems to work better.
309 In order to avoid asking for motion events and then throwing most
310 of them away or busy-polling the server for mouse positions, we ask
311 the server for pointer motion hints. This means that we get only
312 one event per group of mouse movements. "Groups" are delimited by
313 other kinds of events (focus changes and button clicks, for
314 example), or by XQueryPointer calls; when one of these happens, we
315 get another MotionNotify event the next time the mouse moves. This
316 is at least as efficient as getting motion events when mouse
317 tracking is on, and I suspect only negligibly worse when tracking
318 is off. */
320 /* Where the mouse was last time we reported a mouse event. */
322 FRAME_PTR last_mouse_frame;
323 static XRectangle last_mouse_glyph;
324 static Lisp_Object last_mouse_press_frame;
326 /* The scroll bar in which the last X motion event occurred.
328 If the last X motion event occurred in a scroll bar, we set this so
329 XTmouse_position can know whether to report a scroll bar motion or
330 an ordinary motion.
332 If the last X motion event didn't occur in a scroll bar, we set
333 this to Qnil, to tell XTmouse_position to return an ordinary motion
334 event. */
336 static Lisp_Object last_mouse_scroll_bar;
338 /* This is a hack. We would really prefer that XTmouse_position would
339 return the time associated with the position it returns, but there
340 doesn't seem to be any way to wrest the time-stamp from the server
341 along with the position query. So, we just keep track of the time
342 of the last movement we received, and return that in hopes that
343 it's somewhat accurate. */
345 static Time last_mouse_movement_time;
347 /* Incremented by XTread_socket whenever it really tries to read
348 events. */
350 #ifdef __STDC__
351 static int volatile input_signal_count;
352 #else
353 static int input_signal_count;
354 #endif
356 /* Used locally within XTread_socket. */
358 static int x_noop_count;
360 /* Initial values of argv and argc. */
362 extern char **initial_argv;
363 extern int initial_argc;
365 extern Lisp_Object Vcommand_line_args, Vsystem_name;
367 /* Tells if a window manager is present or not. */
369 extern Lisp_Object Vx_no_window_manager;
371 extern Lisp_Object Qface, Qmouse_face;
373 extern int errno;
375 /* A mask of extra modifier bits to put into every keyboard char. */
377 extern int extra_keyboard_modifiers;
379 static Lisp_Object Qvendor_specific_keysyms;
381 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
382 extern Lisp_Object x_icon_type P_ ((struct frame *));
385 /* Enumeration for overriding/changing the face to use for drawing
386 glyphs in x_draw_glyphs. */
388 enum draw_glyphs_face
390 DRAW_NORMAL_TEXT,
391 DRAW_INVERSE_VIDEO,
392 DRAW_CURSOR,
393 DRAW_MOUSE_FACE,
394 DRAW_IMAGE_RAISED,
395 DRAW_IMAGE_SUNKEN
398 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
399 static const XColor *x_color_cells P_ ((struct frame *, int *));
400 static void x_update_window_end P_ ((struct window *, int, int));
401 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
402 void x_delete_display P_ ((struct x_display_info *));
403 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
404 unsigned));
405 static int fast_find_position P_ ((struct window *, int, int *, int *,
406 int *, int *));
407 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
408 int *, int *, int *, int *, int));
409 static void set_output_cursor P_ ((struct cursor_pos *));
410 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
411 int *, int *, int *, int));
412 static void note_mode_line_highlight P_ ((struct window *, int, int));
413 static void note_mouse_highlight P_ ((struct frame *, int, int));
414 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
415 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
416 static void show_mouse_face P_ ((struct x_display_info *,
417 enum draw_glyphs_face));
418 static int x_io_error_quitter P_ ((Display *));
419 int x_catch_errors P_ ((Display *));
420 void x_uncatch_errors P_ ((Display *, int));
421 void x_lower_frame P_ ((struct frame *));
422 void x_scroll_bar_clear P_ ((struct frame *));
423 int x_had_errors_p P_ ((Display *));
424 void x_wm_set_size_hint P_ ((struct frame *, long, int));
425 void x_raise_frame P_ ((struct frame *));
426 void x_set_window_size P_ ((struct frame *, int, int, int));
427 void x_wm_set_window_state P_ ((struct frame *, int));
428 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
429 void x_initialize P_ ((void));
430 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
431 static int x_compute_min_glyph_bounds P_ ((struct frame *));
432 static void x_draw_phys_cursor_glyph P_ ((struct window *,
433 struct glyph_row *,
434 enum draw_glyphs_face));
435 static void x_update_end P_ ((struct frame *));
436 static void XTframe_up_to_date P_ ((struct frame *));
437 static void XTreassert_line_highlight P_ ((int, int));
438 static void x_change_line_highlight P_ ((int, int, int, int));
439 static void XTset_terminal_modes P_ ((void));
440 static void XTreset_terminal_modes P_ ((void));
441 static void XTcursor_to P_ ((int, int, int, int));
442 static void x_write_glyphs P_ ((struct glyph *, int));
443 static void x_clear_end_of_line P_ ((int));
444 static void x_clear_frame P_ ((void));
445 static void x_clear_cursor P_ ((struct window *));
446 static void frame_highlight P_ ((struct frame *));
447 static void frame_unhighlight P_ ((struct frame *));
448 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
449 static void XTframe_rehighlight P_ ((struct frame *));
450 static void x_frame_rehighlight P_ ((struct x_display_info *));
451 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
452 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
453 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
454 XRectangle *));
455 static void expose_frame P_ ((struct frame *, int, int, int, int));
456 static void expose_window_tree P_ ((struct window *, XRectangle *));
457 static void expose_window P_ ((struct window *, XRectangle *));
458 static void expose_area P_ ((struct window *, struct glyph_row *,
459 XRectangle *, enum glyph_row_area));
460 static void expose_line P_ ((struct window *, struct glyph_row *,
461 XRectangle *));
462 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
463 static void x_update_window_cursor P_ ((struct window *, int));
464 static void x_erase_phys_cursor P_ ((struct window *));
465 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
466 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
467 enum bitmap_type));
469 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
470 GC, int));
471 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
472 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
473 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
474 static void x_flush P_ ((struct frame *f));
475 static void x_update_begin P_ ((struct frame *));
476 static void x_update_window_begin P_ ((struct window *));
477 static void x_draw_vertical_border P_ ((struct window *));
478 static void x_after_update_window_line P_ ((struct glyph_row *));
479 static INLINE void take_vertical_position_into_account P_ ((struct it *));
480 static void x_produce_stretch_glyph P_ ((struct it *));
481 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
482 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
483 enum scroll_bar_part *,
484 Lisp_Object *, Lisp_Object *,
485 unsigned long *));
487 /* Flush display of frame F, or of all frames if F is null. */
489 static void
490 x_flush (f)
491 struct frame *f;
493 BLOCK_INPUT;
494 if (f == NULL)
496 Lisp_Object rest, frame;
497 FOR_EACH_FRAME (rest, frame)
498 x_flush (XFRAME (frame));
500 else if (FRAME_X_P (f))
501 XFlush (FRAME_X_DISPLAY (f));
502 UNBLOCK_INPUT;
506 /* Remove calls to XFlush by defining XFlush to an empty replacement.
507 Calls to XFlush should be unnecessary because the X output buffer
508 is flushed automatically as needed by calls to XPending,
509 XNextEvent, or XWindowEvent according to the XFlush man page.
510 XTread_socket calls XPending. Removing XFlush improves
511 performance. */
513 #define XFlush(DISPLAY) (void) 0
516 /***********************************************************************
517 Debugging
518 ***********************************************************************/
520 #if 0
522 /* This is a function useful for recording debugging information about
523 the sequence of occurrences in this file. */
525 struct record
527 char *locus;
528 int type;
531 struct record event_record[100];
533 int event_record_index;
535 record_event (locus, type)
536 char *locus;
537 int type;
539 if (event_record_index == sizeof (event_record) / sizeof (struct record))
540 event_record_index = 0;
542 event_record[event_record_index].locus = locus;
543 event_record[event_record_index].type = type;
544 event_record_index++;
547 #endif /* 0 */
551 /* Return the struct x_display_info corresponding to DPY. */
553 struct x_display_info *
554 x_display_info_for_display (dpy)
555 Display *dpy;
557 struct x_display_info *dpyinfo;
559 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
560 if (dpyinfo->display == dpy)
561 return dpyinfo;
563 return 0;
568 /***********************************************************************
569 Starting and ending an update
570 ***********************************************************************/
572 /* Start an update of frame F. This function is installed as a hook
573 for update_begin, i.e. it is called when update_begin is called.
574 This function is called prior to calls to x_update_window_begin for
575 each window being updated. Currently, there is nothing to do here
576 because all interesting stuff is done on a window basis. */
578 static void
579 x_update_begin (f)
580 struct frame *f;
582 /* Nothing to do. */
586 /* Start update of window W. Set the global variable updated_window
587 to the window being updated and set output_cursor to the cursor
588 position of W. */
590 static void
591 x_update_window_begin (w)
592 struct window *w;
594 struct frame *f = XFRAME (WINDOW_FRAME (w));
595 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
597 updated_window = w;
598 set_output_cursor (&w->cursor);
600 BLOCK_INPUT;
602 if (f == display_info->mouse_face_mouse_frame)
604 /* Don't do highlighting for mouse motion during the update. */
605 display_info->mouse_face_defer = 1;
607 /* If F needs to be redrawn, simply forget about any prior mouse
608 highlighting. */
609 if (FRAME_GARBAGED_P (f))
610 display_info->mouse_face_window = Qnil;
612 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
613 their mouse_face_p flag set, which means that they are always
614 unequal to rows in a desired matrix which never have that
615 flag set. So, rows containing mouse-face glyphs are never
616 scrolled, and we don't have to switch the mouse highlight off
617 here to prevent it from being scrolled. */
619 /* Can we tell that this update does not affect the window
620 where the mouse highlight is? If so, no need to turn off.
621 Likewise, don't do anything if the frame is garbaged;
622 in that case, the frame's current matrix that we would use
623 is all wrong, and we will redisplay that line anyway. */
624 if (!NILP (display_info->mouse_face_window)
625 && w == XWINDOW (display_info->mouse_face_window))
627 int i;
629 for (i = 0; i < w->desired_matrix->nrows; ++i)
630 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
631 break;
633 if (i < w->desired_matrix->nrows)
634 clear_mouse_face (display_info);
636 #endif /* 0 */
639 UNBLOCK_INPUT;
643 /* Draw a vertical window border to the right of window W if W doesn't
644 have vertical scroll bars. */
646 static void
647 x_draw_vertical_border (w)
648 struct window *w;
650 struct frame *f = XFRAME (WINDOW_FRAME (w));
652 /* Redraw borders between horizontally adjacent windows. Don't
653 do it for frames with vertical scroll bars because either the
654 right scroll bar of a window, or the left scroll bar of its
655 neighbor will suffice as a border. */
656 if (!WINDOW_RIGHTMOST_P (w)
657 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
659 int x0, x1, y0, y1;
661 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
662 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
663 y1 -= 1;
665 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
666 f->output_data.x->normal_gc, x1, y0, x1, y1);
671 /* End update of window W (which is equal to updated_window).
673 Draw vertical borders between horizontally adjacent windows, and
674 display W's cursor if CURSOR_ON_P is non-zero.
676 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
677 glyphs in mouse-face were overwritten. In that case we have to
678 make sure that the mouse-highlight is properly redrawn.
680 W may be a menu bar pseudo-window in case we don't have X toolkit
681 support. Such windows don't have a cursor, so don't display it
682 here. */
684 static void
685 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
686 struct window *w;
687 int cursor_on_p, mouse_face_overwritten_p;
689 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
691 if (!w->pseudo_window_p)
693 BLOCK_INPUT;
695 if (cursor_on_p)
696 x_display_and_set_cursor (w, 1, output_cursor.hpos,
697 output_cursor.vpos,
698 output_cursor.x, output_cursor.y);
700 x_draw_vertical_border (w);
701 UNBLOCK_INPUT;
704 /* If a row with mouse-face was overwritten, arrange for
705 XTframe_up_to_date to redisplay the mouse highlight. */
706 if (mouse_face_overwritten_p)
708 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
709 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
710 dpyinfo->mouse_face_window = Qnil;
713 updated_window = NULL;
717 /* End update of frame F. This function is installed as a hook in
718 update_end. */
720 static void
721 x_update_end (f)
722 struct frame *f;
724 /* Mouse highlight may be displayed again. */
725 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
727 BLOCK_INPUT;
728 XFlush (FRAME_X_DISPLAY (f));
729 UNBLOCK_INPUT;
733 /* This function is called from various places in xdisp.c whenever a
734 complete update has been performed. The global variable
735 updated_window is not available here. */
737 static void
738 XTframe_up_to_date (f)
739 struct frame *f;
741 if (FRAME_X_P (f))
743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
745 if (dpyinfo->mouse_face_deferred_gc
746 || f == dpyinfo->mouse_face_mouse_frame)
748 BLOCK_INPUT;
749 if (dpyinfo->mouse_face_mouse_frame)
750 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
751 dpyinfo->mouse_face_mouse_x,
752 dpyinfo->mouse_face_mouse_y);
753 dpyinfo->mouse_face_deferred_gc = 0;
754 UNBLOCK_INPUT;
760 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
761 arrow bitmaps, or clear the areas where they would be displayed
762 before DESIRED_ROW is made current. The window being updated is
763 found in updated_window. This function It is called from
764 update_window_line only if it is known that there are differences
765 between bitmaps to be drawn between current row and DESIRED_ROW. */
767 static void
768 x_after_update_window_line (desired_row)
769 struct glyph_row *desired_row;
771 struct window *w = updated_window;
773 xassert (w);
775 if (!desired_row->mode_line_p && !w->pseudo_window_p)
777 struct frame *f;
778 int width;
780 BLOCK_INPUT;
781 x_draw_row_bitmaps (w, desired_row);
783 /* When a window has disappeared, make sure that no rest of
784 full-width rows stays visible in the internal border. */
785 if (windows_or_buffers_changed
786 && (f = XFRAME (w->frame),
787 width = FRAME_INTERNAL_BORDER_WIDTH (f),
788 width != 0))
790 int height = desired_row->visible_height;
791 int x = (window_box_right (w, -1)
792 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
793 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
795 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
796 x, y, width, height, False);
799 UNBLOCK_INPUT;
804 /* Draw the bitmap WHICH in one of the areas to the left or right of
805 window W. ROW is the glyph row for which to display the bitmap; it
806 determines the vertical position at which the bitmap has to be
807 drawn. */
809 static void
810 x_draw_bitmap (w, row, which)
811 struct window *w;
812 struct glyph_row *row;
813 enum bitmap_type which;
815 struct frame *f = XFRAME (WINDOW_FRAME (w));
816 Display *display = FRAME_X_DISPLAY (f);
817 Window window = FRAME_X_WINDOW (f);
818 int x, y, wd, h, dy;
819 unsigned char *bits;
820 Pixmap pixmap;
821 GC gc = f->output_data.x->normal_gc;
822 struct face *face;
823 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
825 /* Must clip because of partially visible lines. */
826 x_clip_to_row (w, row, gc, 1);
828 switch (which)
830 case LEFT_TRUNCATION_BITMAP:
831 wd = left_width;
832 h = left_height;
833 bits = left_bits;
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
835 - wd
836 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
837 break;
839 case OVERLAY_ARROW_BITMAP:
840 wd = left_width;
841 h = left_height;
842 bits = ov_bits;
843 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
844 - wd
845 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
846 break;
848 case RIGHT_TRUNCATION_BITMAP:
849 wd = right_width;
850 h = right_height;
851 bits = right_bits;
852 x = window_box_right (w, -1);
853 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
854 break;
856 case CONTINUED_LINE_BITMAP:
857 wd = right_width;
858 h = right_height;
859 bits = continued_bits;
860 x = window_box_right (w, -1);
861 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
862 break;
864 case CONTINUATION_LINE_BITMAP:
865 wd = continuation_width;
866 h = continuation_height;
867 bits = continuation_bits;
868 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
869 - wd
870 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
871 break;
873 case ZV_LINE_BITMAP:
874 wd = zv_width;
875 h = zv_height;
876 bits = zv_bits;
877 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
878 - wd
879 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
880 break;
882 default:
883 abort ();
886 /* Convert to frame coordinates. Set dy to the offset in the row to
887 start drawing the bitmap. */
888 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
889 dy = (row->height - h) / 2;
891 /* Draw the bitmap. I believe these small pixmaps can be cached
892 by the server. */
893 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
894 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
895 face->foreground,
896 face->background, depth);
897 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
898 XFreePixmap (display, pixmap);
899 XSetClipMask (display, gc, None);
903 /* Draw flags bitmaps for glyph row ROW on window W. Call this
904 function with input blocked. */
906 static void
907 x_draw_row_bitmaps (w, row)
908 struct window *w;
909 struct glyph_row *row;
911 struct frame *f = XFRAME (w->frame);
912 enum bitmap_type bitmap;
913 struct face *face;
914 int header_line_height = -1;
916 xassert (interrupt_input_blocked);
918 /* If row is completely invisible, because of vscrolling, we
919 don't have to draw anything. */
920 if (row->visible_height <= 0)
921 return;
923 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
924 PREPARE_FACE_FOR_DISPLAY (f, face);
926 /* Decide which bitmap to draw at the left side. */
927 if (row->overlay_arrow_p)
928 bitmap = OVERLAY_ARROW_BITMAP;
929 else if (row->truncated_on_left_p)
930 bitmap = LEFT_TRUNCATION_BITMAP;
931 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
932 bitmap = CONTINUATION_LINE_BITMAP;
933 else if (row->indicate_empty_line_p)
934 bitmap = ZV_LINE_BITMAP;
935 else
936 bitmap = NO_BITMAP;
938 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
939 the flags area. */
940 if (bitmap == NO_BITMAP
941 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
942 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
944 /* If W has a vertical border to its left, don't draw over it. */
945 int border = ((XFASTINT (w->left) > 0
946 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
947 ? 1 : 0);
948 int left = window_box_left (w, -1);
950 if (header_line_height < 0)
951 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
953 /* In case the same realized face is used for bitmap areas and
954 for something displayed in the text (e.g. face `region' on
955 mono-displays, the fill style may have been changed to
956 FillSolid in x_draw_glyph_string_background. */
957 if (face->stipple)
958 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
959 else
960 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
962 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
963 face->gc,
964 (left
965 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
966 + border),
967 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
968 row->y)),
969 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
970 row->visible_height);
971 if (!face->stipple)
972 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
975 /* Draw the left bitmap. */
976 if (bitmap != NO_BITMAP)
977 x_draw_bitmap (w, row, bitmap);
979 /* Decide which bitmap to draw at the right side. */
980 if (row->truncated_on_right_p)
981 bitmap = RIGHT_TRUNCATION_BITMAP;
982 else if (row->continued_p)
983 bitmap = CONTINUED_LINE_BITMAP;
984 else
985 bitmap = NO_BITMAP;
987 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
988 the flags area. */
989 if (bitmap == NO_BITMAP
990 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
991 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
993 int right = window_box_right (w, -1);
995 if (header_line_height < 0)
996 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
998 /* In case the same realized face is used for bitmap areas and
999 for something displayed in the text (e.g. face `region' on
1000 mono-displays, the fill style may have been changed to
1001 FillSolid in x_draw_glyph_string_background. */
1002 if (face->stipple)
1003 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1004 else
1005 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1006 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1007 face->gc,
1008 right,
1009 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1010 row->y)),
1011 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1012 row->visible_height);
1013 if (!face->stipple)
1014 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1017 /* Draw the right bitmap. */
1018 if (bitmap != NO_BITMAP)
1019 x_draw_bitmap (w, row, bitmap);
1023 /***********************************************************************
1024 Line Highlighting
1025 ***********************************************************************/
1027 /* External interface to control of standout mode. Not used for X
1028 frames. Aborts when called. */
1030 static void
1031 XTreassert_line_highlight (new, vpos)
1032 int new, vpos;
1034 abort ();
1038 /* Call this when about to modify line at position VPOS and change
1039 whether it is highlighted. Not used for X frames. Aborts when
1040 called. */
1042 static void
1043 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1044 int new_highlight, vpos, y, first_unused_hpos;
1046 abort ();
1050 /* This is called when starting Emacs and when restarting after
1051 suspend. When starting Emacs, no X window is mapped. And nothing
1052 must be done to Emacs's own window if it is suspended (though that
1053 rarely happens). */
1055 static void
1056 XTset_terminal_modes ()
1060 /* This is called when exiting or suspending Emacs. Exiting will make
1061 the X-windows go away, and suspending requires no action. */
1063 static void
1064 XTreset_terminal_modes ()
1070 /***********************************************************************
1071 Output Cursor
1072 ***********************************************************************/
1074 /* Set the global variable output_cursor to CURSOR. All cursor
1075 positions are relative to updated_window. */
1077 static void
1078 set_output_cursor (cursor)
1079 struct cursor_pos *cursor;
1081 output_cursor.hpos = cursor->hpos;
1082 output_cursor.vpos = cursor->vpos;
1083 output_cursor.x = cursor->x;
1084 output_cursor.y = cursor->y;
1088 /* Set a nominal cursor position.
1090 HPOS and VPOS are column/row positions in a window glyph matrix. X
1091 and Y are window text area relative pixel positions.
1093 If this is done during an update, updated_window will contain the
1094 window that is being updated and the position is the future output
1095 cursor position for that window. If updated_window is null, use
1096 selected_window and display the cursor at the given position. */
1098 static void
1099 XTcursor_to (vpos, hpos, y, x)
1100 int vpos, hpos, y, x;
1102 struct window *w;
1104 /* If updated_window is not set, work on selected_window. */
1105 if (updated_window)
1106 w = updated_window;
1107 else
1108 w = XWINDOW (selected_window);
1110 /* Set the output cursor. */
1111 output_cursor.hpos = hpos;
1112 output_cursor.vpos = vpos;
1113 output_cursor.x = x;
1114 output_cursor.y = y;
1116 /* If not called as part of an update, really display the cursor.
1117 This will also set the cursor position of W. */
1118 if (updated_window == NULL)
1120 BLOCK_INPUT;
1121 x_display_cursor (w, 1, hpos, vpos, x, y);
1122 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1123 UNBLOCK_INPUT;
1129 /***********************************************************************
1130 Display Iterator
1131 ***********************************************************************/
1133 /* Function prototypes of this page. */
1135 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1136 struct glyph *,
1137 XChar2b *,
1138 int *));
1139 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1140 int, XChar2b *, int));
1141 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1142 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1143 static void x_append_glyph P_ ((struct it *));
1144 static void x_append_composite_glyph P_ ((struct it *));
1145 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1146 int, int, double));
1147 static void x_produce_glyphs P_ ((struct it *));
1148 static void x_produce_image_glyph P_ ((struct it *it));
1151 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1152 is not contained in the font. */
1154 static INLINE XCharStruct *
1155 x_per_char_metric (font, char2b)
1156 XFontStruct *font;
1157 XChar2b *char2b;
1159 /* The result metric information. */
1160 XCharStruct *pcm = NULL;
1162 xassert (font && char2b);
1164 if (font->per_char != NULL)
1166 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1168 /* min_char_or_byte2 specifies the linear character index
1169 corresponding to the first element of the per_char array,
1170 max_char_or_byte2 is the index of the last character. A
1171 character with non-zero CHAR2B->byte1 is not in the font.
1172 A character with byte2 less than min_char_or_byte2 or
1173 greater max_char_or_byte2 is not in the font. */
1174 if (char2b->byte1 == 0
1175 && char2b->byte2 >= font->min_char_or_byte2
1176 && char2b->byte2 <= font->max_char_or_byte2)
1177 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1179 else
1181 /* If either min_byte1 or max_byte1 are nonzero, both
1182 min_char_or_byte2 and max_char_or_byte2 are less than
1183 256, and the 2-byte character index values corresponding
1184 to the per_char array element N (counting from 0) are:
1186 byte1 = N/D + min_byte1
1187 byte2 = N\D + min_char_or_byte2
1189 where:
1191 D = max_char_or_byte2 - min_char_or_byte2 + 1
1192 / = integer division
1193 \ = integer modulus */
1194 if (char2b->byte1 >= font->min_byte1
1195 && char2b->byte1 <= font->max_byte1
1196 && char2b->byte2 >= font->min_char_or_byte2
1197 && char2b->byte2 <= font->max_char_or_byte2)
1199 pcm = (font->per_char
1200 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1201 * (char2b->byte1 - font->min_byte1))
1202 + (char2b->byte2 - font->min_char_or_byte2));
1206 else
1208 /* If the per_char pointer is null, all glyphs between the first
1209 and last character indexes inclusive have the same
1210 information, as given by both min_bounds and max_bounds. */
1211 if (char2b->byte2 >= font->min_char_or_byte2
1212 && char2b->byte2 <= font->max_char_or_byte2)
1213 pcm = &font->max_bounds;
1216 return ((pcm == NULL
1217 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1218 ? NULL : pcm);
1222 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1223 the two-byte form of C. Encoding is returned in *CHAR2B. */
1225 static INLINE void
1226 x_encode_char (c, char2b, font_info)
1227 int c;
1228 XChar2b *char2b;
1229 struct font_info *font_info;
1231 int charset = CHAR_CHARSET (c);
1232 XFontStruct *font = font_info->font;
1234 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1235 This may be either a program in a special encoder language or a
1236 fixed encoding. */
1237 if (font_info->font_encoder)
1239 /* It's a program. */
1240 struct ccl_program *ccl = font_info->font_encoder;
1242 if (CHARSET_DIMENSION (charset) == 1)
1244 ccl->reg[0] = charset;
1245 ccl->reg[1] = char2b->byte2;
1247 else
1249 ccl->reg[0] = charset;
1250 ccl->reg[1] = char2b->byte1;
1251 ccl->reg[2] = char2b->byte2;
1254 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1256 /* We assume that MSBs are appropriately set/reset by CCL
1257 program. */
1258 if (font->max_byte1 == 0) /* 1-byte font */
1259 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1260 else
1261 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1263 else if (font_info->encoding[charset])
1265 /* Fixed encoding scheme. See fontset.h for the meaning of the
1266 encoding numbers. */
1267 int enc = font_info->encoding[charset];
1269 if ((enc == 1 || enc == 2)
1270 && CHARSET_DIMENSION (charset) == 2)
1271 char2b->byte1 |= 0x80;
1273 if (enc == 1 || enc == 3)
1274 char2b->byte2 |= 0x80;
1279 /* Get face and two-byte form of character C in face FACE_ID on frame
1280 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1281 means we want to display multibyte text. Value is a pointer to a
1282 realized face that is ready for display. */
1284 static INLINE struct face *
1285 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1286 struct frame *f;
1287 int c, face_id;
1288 XChar2b *char2b;
1289 int multibyte_p;
1291 struct face *face = FACE_FROM_ID (f, face_id);
1293 if (!multibyte_p)
1295 /* Unibyte case. We don't have to encode, but we have to make
1296 sure to use a face suitable for unibyte. */
1297 char2b->byte1 = 0;
1298 char2b->byte2 = c;
1299 face_id = FACE_FOR_CHAR (f, face, c);
1300 face = FACE_FROM_ID (f, face_id);
1302 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1304 /* Case of ASCII in a face known to fit ASCII. */
1305 char2b->byte1 = 0;
1306 char2b->byte2 = c;
1308 else
1310 int c1, c2, charset;
1312 /* Split characters into bytes. If c2 is -1 afterwards, C is
1313 really a one-byte character so that byte1 is zero. */
1314 SPLIT_CHAR (c, charset, c1, c2);
1315 if (c2 > 0)
1316 char2b->byte1 = c1, char2b->byte2 = c2;
1317 else
1318 char2b->byte1 = 0, char2b->byte2 = c1;
1320 /* Maybe encode the character in *CHAR2B. */
1321 if (face->font != NULL)
1323 struct font_info *font_info
1324 = FONT_INFO_FROM_ID (f, face->font_info_id);
1325 if (font_info)
1326 x_encode_char (c, char2b, font_info);
1330 /* Make sure X resources of the face are allocated. */
1331 xassert (face != NULL);
1332 PREPARE_FACE_FOR_DISPLAY (f, face);
1334 return face;
1338 /* Get face and two-byte form of character glyph GLYPH on frame F.
1339 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1340 a pointer to a realized face that is ready for display. */
1342 static INLINE struct face *
1343 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1344 struct frame *f;
1345 struct glyph *glyph;
1346 XChar2b *char2b;
1347 int *two_byte_p;
1349 struct face *face;
1351 xassert (glyph->type == CHAR_GLYPH);
1352 face = FACE_FROM_ID (f, glyph->face_id);
1354 if (two_byte_p)
1355 *two_byte_p = 0;
1357 if (!glyph->multibyte_p)
1359 /* Unibyte case. We don't have to encode, but we have to make
1360 sure to use a face suitable for unibyte. */
1361 char2b->byte1 = 0;
1362 char2b->byte2 = glyph->u.ch;
1364 else if (glyph->u.ch < 128
1365 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1367 /* Case of ASCII in a face known to fit ASCII. */
1368 char2b->byte1 = 0;
1369 char2b->byte2 = glyph->u.ch;
1371 else
1373 int c1, c2, charset;
1375 /* Split characters into bytes. If c2 is -1 afterwards, C is
1376 really a one-byte character so that byte1 is zero. */
1377 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1378 if (c2 > 0)
1379 char2b->byte1 = c1, char2b->byte2 = c2;
1380 else
1381 char2b->byte1 = 0, char2b->byte2 = c1;
1383 /* Maybe encode the character in *CHAR2B. */
1384 if (charset != CHARSET_ASCII)
1386 struct font_info *font_info
1387 = FONT_INFO_FROM_ID (f, face->font_info_id);
1388 if (font_info)
1390 x_encode_char (glyph->u.ch, char2b, font_info);
1391 if (two_byte_p)
1392 *two_byte_p
1393 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1398 /* Make sure X resources of the face are allocated. */
1399 xassert (face != NULL);
1400 PREPARE_FACE_FOR_DISPLAY (f, face);
1401 return face;
1405 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1406 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1408 static INLINE void
1409 x_append_glyph (it)
1410 struct it *it;
1412 struct glyph *glyph;
1413 enum glyph_row_area area = it->area;
1415 xassert (it->glyph_row);
1416 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1418 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1419 if (glyph < it->glyph_row->glyphs[area + 1])
1421 glyph->charpos = CHARPOS (it->position);
1422 glyph->object = it->object;
1423 glyph->pixel_width = it->pixel_width;
1424 glyph->voffset = it->voffset;
1425 glyph->type = CHAR_GLYPH;
1426 glyph->multibyte_p = it->multibyte_p;
1427 glyph->left_box_line_p = it->start_of_box_run_p;
1428 glyph->right_box_line_p = it->end_of_box_run_p;
1429 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1430 || it->phys_descent > it->descent);
1431 glyph->padding_p = 0;
1432 glyph->glyph_not_available_p = it->glyph_not_available_p;
1433 glyph->face_id = it->face_id;
1434 glyph->u.ch = it->char_to_display;
1435 ++it->glyph_row->used[area];
1439 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1440 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1442 static INLINE void
1443 x_append_composite_glyph (it)
1444 struct it *it;
1446 struct glyph *glyph;
1447 enum glyph_row_area area = it->area;
1449 xassert (it->glyph_row);
1451 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1452 if (glyph < it->glyph_row->glyphs[area + 1])
1454 glyph->charpos = CHARPOS (it->position);
1455 glyph->object = it->object;
1456 glyph->pixel_width = it->pixel_width;
1457 glyph->voffset = it->voffset;
1458 glyph->type = COMPOSITE_GLYPH;
1459 glyph->multibyte_p = it->multibyte_p;
1460 glyph->left_box_line_p = it->start_of_box_run_p;
1461 glyph->right_box_line_p = it->end_of_box_run_p;
1462 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1463 || it->phys_descent > it->descent);
1464 glyph->padding_p = 0;
1465 glyph->glyph_not_available_p = 0;
1466 glyph->face_id = it->face_id;
1467 glyph->u.cmp_id = it->cmp_id;
1468 ++it->glyph_row->used[area];
1473 /* Change IT->ascent and IT->height according to the setting of
1474 IT->voffset. */
1476 static INLINE void
1477 take_vertical_position_into_account (it)
1478 struct it *it;
1480 if (it->voffset)
1482 if (it->voffset < 0)
1483 /* Increase the ascent so that we can display the text higher
1484 in the line. */
1485 it->ascent += abs (it->voffset);
1486 else
1487 /* Increase the descent so that we can display the text lower
1488 in the line. */
1489 it->descent += it->voffset;
1494 /* Produce glyphs/get display metrics for the image IT is loaded with.
1495 See the description of struct display_iterator in dispextern.h for
1496 an overview of struct display_iterator. */
1498 static void
1499 x_produce_image_glyph (it)
1500 struct it *it;
1502 struct image *img;
1503 struct face *face;
1505 xassert (it->what == IT_IMAGE);
1507 face = FACE_FROM_ID (it->f, it->face_id);
1508 img = IMAGE_FROM_ID (it->f, it->image_id);
1509 xassert (img);
1511 /* Make sure X resources of the face and image are loaded. */
1512 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1513 prepare_image_for_display (it->f, img);
1515 it->ascent = it->phys_ascent = image_ascent (img, face);
1516 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1517 it->pixel_width = img->width + 2 * img->hmargin;
1519 it->nglyphs = 1;
1521 if (face->box != FACE_NO_BOX)
1523 if (face->box_line_width > 0)
1525 it->ascent += face->box_line_width;
1526 it->descent += face->box_line_width;
1529 if (it->start_of_box_run_p)
1530 it->pixel_width += abs (face->box_line_width);
1531 if (it->end_of_box_run_p)
1532 it->pixel_width += abs (face->box_line_width);
1535 take_vertical_position_into_account (it);
1537 if (it->glyph_row)
1539 struct glyph *glyph;
1540 enum glyph_row_area area = it->area;
1542 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1543 if (glyph < it->glyph_row->glyphs[area + 1])
1545 glyph->charpos = CHARPOS (it->position);
1546 glyph->object = it->object;
1547 glyph->pixel_width = it->pixel_width;
1548 glyph->voffset = it->voffset;
1549 glyph->type = IMAGE_GLYPH;
1550 glyph->multibyte_p = it->multibyte_p;
1551 glyph->left_box_line_p = it->start_of_box_run_p;
1552 glyph->right_box_line_p = it->end_of_box_run_p;
1553 glyph->overlaps_vertically_p = 0;
1554 glyph->padding_p = 0;
1555 glyph->glyph_not_available_p = 0;
1556 glyph->face_id = it->face_id;
1557 glyph->u.img_id = img->id;
1558 ++it->glyph_row->used[area];
1564 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1565 of the glyph, WIDTH and HEIGHT are the width and height of the
1566 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1567 ascent of the glyph (0 <= ASCENT <= 1). */
1569 static void
1570 x_append_stretch_glyph (it, object, width, height, ascent)
1571 struct it *it;
1572 Lisp_Object object;
1573 int width, height;
1574 double ascent;
1576 struct glyph *glyph;
1577 enum glyph_row_area area = it->area;
1579 xassert (ascent >= 0 && ascent <= 1);
1581 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1582 if (glyph < it->glyph_row->glyphs[area + 1])
1584 glyph->charpos = CHARPOS (it->position);
1585 glyph->object = object;
1586 glyph->pixel_width = width;
1587 glyph->voffset = it->voffset;
1588 glyph->type = STRETCH_GLYPH;
1589 glyph->multibyte_p = it->multibyte_p;
1590 glyph->left_box_line_p = it->start_of_box_run_p;
1591 glyph->right_box_line_p = it->end_of_box_run_p;
1592 glyph->overlaps_vertically_p = 0;
1593 glyph->padding_p = 0;
1594 glyph->glyph_not_available_p = 0;
1595 glyph->face_id = it->face_id;
1596 glyph->u.stretch.ascent = height * ascent;
1597 glyph->u.stretch.height = height;
1598 ++it->glyph_row->used[area];
1603 /* Produce a stretch glyph for iterator IT. IT->object is the value
1604 of the glyph property displayed. The value must be a list
1605 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1606 being recognized:
1608 1. `:width WIDTH' specifies that the space should be WIDTH *
1609 canonical char width wide. WIDTH may be an integer or floating
1610 point number.
1612 2. `:relative-width FACTOR' specifies that the width of the stretch
1613 should be computed from the width of the first character having the
1614 `glyph' property, and should be FACTOR times that width.
1616 3. `:align-to HPOS' specifies that the space should be wide enough
1617 to reach HPOS, a value in canonical character units.
1619 Exactly one of the above pairs must be present.
1621 4. `:height HEIGHT' specifies that the height of the stretch produced
1622 should be HEIGHT, measured in canonical character units.
1624 5. `:relative-height FACTOR' specifies that the height of the the
1625 stretch should be FACTOR times the height of the characters having
1626 the glyph property.
1628 Either none or exactly one of 4 or 5 must be present.
1630 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1631 of the stretch should be used for the ascent of the stretch.
1632 ASCENT must be in the range 0 <= ASCENT <= 100. */
1634 #define NUMVAL(X) \
1635 ((INTEGERP (X) || FLOATP (X)) \
1636 ? XFLOATINT (X) \
1637 : - 1)
1640 static void
1641 x_produce_stretch_glyph (it)
1642 struct it *it;
1644 /* (space :width WIDTH :height HEIGHT. */
1645 #if GLYPH_DEBUG
1646 extern Lisp_Object Qspace;
1647 #endif
1648 extern Lisp_Object QCwidth, QCheight, QCascent;
1649 extern Lisp_Object QCrelative_width, QCrelative_height;
1650 extern Lisp_Object QCalign_to;
1651 Lisp_Object prop, plist;
1652 double width = 0, height = 0, ascent = 0;
1653 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1654 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1656 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1658 /* List should start with `space'. */
1659 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1660 plist = XCDR (it->object);
1662 /* Compute the width of the stretch. */
1663 if (prop = Fplist_get (plist, QCwidth),
1664 NUMVAL (prop) > 0)
1665 /* Absolute width `:width WIDTH' specified and valid. */
1666 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1667 else if (prop = Fplist_get (plist, QCrelative_width),
1668 NUMVAL (prop) > 0)
1670 /* Relative width `:relative-width FACTOR' specified and valid.
1671 Compute the width of the characters having the `glyph'
1672 property. */
1673 struct it it2;
1674 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1676 it2 = *it;
1677 if (it->multibyte_p)
1679 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1680 - IT_BYTEPOS (*it));
1681 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1683 else
1684 it2.c = *p, it2.len = 1;
1686 it2.glyph_row = NULL;
1687 it2.what = IT_CHARACTER;
1688 x_produce_glyphs (&it2);
1689 width = NUMVAL (prop) * it2.pixel_width;
1691 else if (prop = Fplist_get (plist, QCalign_to),
1692 NUMVAL (prop) > 0)
1693 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1694 else
1695 /* Nothing specified -> width defaults to canonical char width. */
1696 width = CANON_X_UNIT (it->f);
1698 /* Compute height. */
1699 if (prop = Fplist_get (plist, QCheight),
1700 NUMVAL (prop) > 0)
1701 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1702 else if (prop = Fplist_get (plist, QCrelative_height),
1703 NUMVAL (prop) > 0)
1704 height = FONT_HEIGHT (font) * NUMVAL (prop);
1705 else
1706 height = FONT_HEIGHT (font);
1708 /* Compute percentage of height used for ascent. If
1709 `:ascent ASCENT' is present and valid, use that. Otherwise,
1710 derive the ascent from the font in use. */
1711 if (prop = Fplist_get (plist, QCascent),
1712 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1713 ascent = NUMVAL (prop) / 100.0;
1714 else
1715 ascent = (double) font->ascent / FONT_HEIGHT (font);
1717 if (width <= 0)
1718 width = 1;
1719 if (height <= 0)
1720 height = 1;
1722 if (it->glyph_row)
1724 Lisp_Object object = it->stack[it->sp - 1].string;
1725 if (!STRINGP (object))
1726 object = it->w->buffer;
1727 x_append_stretch_glyph (it, object, width, height, ascent);
1730 it->pixel_width = width;
1731 it->ascent = it->phys_ascent = height * ascent;
1732 it->descent = it->phys_descent = height - it->ascent;
1733 it->nglyphs = 1;
1735 if (face->box != FACE_NO_BOX)
1737 if (face->box_line_width > 0)
1739 it->ascent += face->box_line_width;
1740 it->descent += face->box_line_width;
1743 if (it->start_of_box_run_p)
1744 it->pixel_width += abs (face->box_line_width);
1745 if (it->end_of_box_run_p)
1746 it->pixel_width += abs (face->box_line_width);
1749 take_vertical_position_into_account (it);
1752 /* Return proper value to be used as baseline offset of font that has
1753 ASCENT and DESCENT to draw characters by the font at the vertical
1754 center of the line of frame F.
1756 Here, out task is to find the value of BOFF in the following figure;
1758 -------------------------+-----------+-
1759 -+-+---------+-+ | |
1760 | | | | | |
1761 | | | | F_ASCENT F_HEIGHT
1762 | | | ASCENT | |
1763 HEIGHT | | | | |
1764 | | |-|-+------+-----------|------- baseline
1765 | | | | BOFF | |
1766 | |---------|-+-+ | |
1767 | | | DESCENT | |
1768 -+-+---------+-+ F_DESCENT |
1769 -------------------------+-----------+-
1771 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1772 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1773 DESCENT = FONT->descent
1774 HEIGHT = FONT_HEIGHT (FONT)
1775 F_DESCENT = (F->output_data.x->font->descent
1776 - F->output_data.x->baseline_offset)
1777 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1780 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1781 ((FONT)->descent \
1782 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1783 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1784 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1786 /* Produce glyphs/get display metrics for the display element IT is
1787 loaded with. See the description of struct display_iterator in
1788 dispextern.h for an overview of struct display_iterator. */
1790 static void
1791 x_produce_glyphs (it)
1792 struct it *it;
1794 it->glyph_not_available_p = 0;
1796 if (it->what == IT_CHARACTER)
1798 XChar2b char2b;
1799 XFontStruct *font;
1800 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1801 XCharStruct *pcm;
1802 int font_not_found_p;
1803 struct font_info *font_info;
1804 int boff; /* baseline offset */
1805 /* We may change it->multibyte_p upon unibyte<->multibyte
1806 conversion. So, save the current value now and restore it
1807 later.
1809 Note: It seems that we don't have to record multibyte_p in
1810 struct glyph because the character code itself tells if or
1811 not the character is multibyte. Thus, in the future, we must
1812 consider eliminating the field `multibyte_p' in the struct
1813 glyph.
1815 int saved_multibyte_p = it->multibyte_p;
1817 /* Maybe translate single-byte characters to multibyte, or the
1818 other way. */
1819 it->char_to_display = it->c;
1820 if (!ASCII_BYTE_P (it->c))
1822 if (unibyte_display_via_language_environment
1823 && SINGLE_BYTE_CHAR_P (it->c)
1824 && (it->c >= 0240
1825 || !NILP (Vnonascii_translation_table)))
1827 it->char_to_display = unibyte_char_to_multibyte (it->c);
1828 it->multibyte_p = 1;
1829 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1830 face = FACE_FROM_ID (it->f, it->face_id);
1832 else if (!SINGLE_BYTE_CHAR_P (it->c)
1833 && !it->multibyte_p)
1835 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1836 it->multibyte_p = 0;
1837 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1838 face = FACE_FROM_ID (it->f, it->face_id);
1842 /* Get font to use. Encode IT->char_to_display. */
1843 x_get_char_face_and_encoding (it->f, it->char_to_display,
1844 it->face_id, &char2b,
1845 it->multibyte_p);
1846 font = face->font;
1848 /* When no suitable font found, use the default font. */
1849 font_not_found_p = font == NULL;
1850 if (font_not_found_p)
1852 font = FRAME_FONT (it->f);
1853 boff = it->f->output_data.x->baseline_offset;
1854 font_info = NULL;
1856 else
1858 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1859 boff = font_info->baseline_offset;
1860 if (font_info->vertical_centering)
1861 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1864 if (it->char_to_display >= ' '
1865 && (!it->multibyte_p || it->char_to_display < 128))
1867 /* Either unibyte or ASCII. */
1868 int stretched_p;
1870 it->nglyphs = 1;
1872 pcm = x_per_char_metric (font, &char2b);
1873 it->ascent = font->ascent + boff;
1874 it->descent = font->descent - boff;
1876 if (pcm)
1878 it->phys_ascent = pcm->ascent + boff;
1879 it->phys_descent = pcm->descent - boff;
1880 it->pixel_width = pcm->width;
1882 else
1884 it->glyph_not_available_p = 1;
1885 it->phys_ascent = font->ascent + boff;
1886 it->phys_descent = font->descent - boff;
1887 it->pixel_width = FONT_WIDTH (font);
1890 /* If this is a space inside a region of text with
1891 `space-width' property, change its width. */
1892 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1893 if (stretched_p)
1894 it->pixel_width *= XFLOATINT (it->space_width);
1896 /* If face has a box, add the box thickness to the character
1897 height. If character has a box line to the left and/or
1898 right, add the box line width to the character's width. */
1899 if (face->box != FACE_NO_BOX)
1901 int thick = face->box_line_width;
1903 if (thick > 0)
1905 it->ascent += thick;
1906 it->descent += thick;
1908 else
1909 thick = -thick;
1911 if (it->start_of_box_run_p)
1912 it->pixel_width += thick;
1913 if (it->end_of_box_run_p)
1914 it->pixel_width += thick;
1917 /* If face has an overline, add the height of the overline
1918 (1 pixel) and a 1 pixel margin to the character height. */
1919 if (face->overline_p)
1920 it->ascent += 2;
1922 take_vertical_position_into_account (it);
1924 /* If we have to actually produce glyphs, do it. */
1925 if (it->glyph_row)
1927 if (stretched_p)
1929 /* Translate a space with a `space-width' property
1930 into a stretch glyph. */
1931 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1932 x_append_stretch_glyph (it, it->object, it->pixel_width,
1933 it->ascent + it->descent, ascent);
1935 else
1936 x_append_glyph (it);
1938 /* If characters with lbearing or rbearing are displayed
1939 in this line, record that fact in a flag of the
1940 glyph row. This is used to optimize X output code. */
1941 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1942 it->glyph_row->contains_overlapping_glyphs_p = 1;
1945 else if (it->char_to_display == '\n')
1947 /* A newline has no width but we need the height of the line. */
1948 it->pixel_width = 0;
1949 it->nglyphs = 0;
1950 it->ascent = it->phys_ascent = font->ascent + boff;
1951 it->descent = it->phys_descent = font->descent - boff;
1953 if (face->box != FACE_NO_BOX
1954 && face->box_line_width > 0)
1956 it->ascent += face->box_line_width;
1957 it->descent += face->box_line_width;
1960 else if (it->char_to_display == '\t')
1962 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1963 int x = it->current_x + it->continuation_lines_width;
1964 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1966 /* If the distance from the current position to the next tab
1967 stop is less than a canonical character width, use the
1968 tab stop after that. */
1969 if (next_tab_x - x < CANON_X_UNIT (it->f))
1970 next_tab_x += tab_width;
1972 it->pixel_width = next_tab_x - x;
1973 it->nglyphs = 1;
1974 it->ascent = it->phys_ascent = font->ascent + boff;
1975 it->descent = it->phys_descent = font->descent - boff;
1977 if (it->glyph_row)
1979 double ascent = (double) it->ascent / (it->ascent + it->descent);
1980 x_append_stretch_glyph (it, it->object, it->pixel_width,
1981 it->ascent + it->descent, ascent);
1984 else
1986 /* A multi-byte character. Assume that the display width of the
1987 character is the width of the character multiplied by the
1988 width of the font. */
1990 /* If we found a font, this font should give us the right
1991 metrics. If we didn't find a font, use the frame's
1992 default font and calculate the width of the character
1993 from the charset width; this is what old redisplay code
1994 did. */
1995 pcm = x_per_char_metric (font, &char2b);
1996 if (font_not_found_p || !pcm)
1998 int charset = CHAR_CHARSET (it->char_to_display);
2000 it->glyph_not_available_p = 1;
2001 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2002 * CHARSET_WIDTH (charset));
2003 it->phys_ascent = font->ascent + boff;
2004 it->phys_descent = font->descent - boff;
2006 else
2008 it->pixel_width = pcm->width;
2009 it->phys_ascent = pcm->ascent + boff;
2010 it->phys_descent = pcm->descent - boff;
2011 if (it->glyph_row
2012 && (pcm->lbearing < 0
2013 || pcm->rbearing > pcm->width))
2014 it->glyph_row->contains_overlapping_glyphs_p = 1;
2016 it->nglyphs = 1;
2017 it->ascent = font->ascent + boff;
2018 it->descent = font->descent - boff;
2019 if (face->box != FACE_NO_BOX)
2021 int thick = face->box_line_width;
2023 if (thick > 0)
2025 it->ascent += thick;
2026 it->descent += thick;
2028 else
2029 thick = - thick;
2031 if (it->start_of_box_run_p)
2032 it->pixel_width += thick;
2033 if (it->end_of_box_run_p)
2034 it->pixel_width += thick;
2037 /* If face has an overline, add the height of the overline
2038 (1 pixel) and a 1 pixel margin to the character height. */
2039 if (face->overline_p)
2040 it->ascent += 2;
2042 take_vertical_position_into_account (it);
2044 if (it->glyph_row)
2045 x_append_glyph (it);
2047 it->multibyte_p = saved_multibyte_p;
2049 else if (it->what == IT_COMPOSITION)
2051 /* Note: A composition is represented as one glyph in the
2052 glyph matrix. There are no padding glyphs. */
2053 XChar2b char2b;
2054 XFontStruct *font;
2055 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2056 XCharStruct *pcm;
2057 int font_not_found_p;
2058 struct font_info *font_info;
2059 int boff; /* baseline offset */
2060 struct composition *cmp = composition_table[it->cmp_id];
2062 /* Maybe translate single-byte characters to multibyte. */
2063 it->char_to_display = it->c;
2064 if (unibyte_display_via_language_environment
2065 && SINGLE_BYTE_CHAR_P (it->c)
2066 && (it->c >= 0240
2067 || (it->c >= 0200
2068 && !NILP (Vnonascii_translation_table))))
2070 it->char_to_display = unibyte_char_to_multibyte (it->c);
2073 /* Get face and font to use. Encode IT->char_to_display. */
2074 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2075 face = FACE_FROM_ID (it->f, it->face_id);
2076 x_get_char_face_and_encoding (it->f, it->char_to_display,
2077 it->face_id, &char2b, it->multibyte_p);
2078 font = face->font;
2080 /* When no suitable font found, use the default font. */
2081 font_not_found_p = font == NULL;
2082 if (font_not_found_p)
2084 font = FRAME_FONT (it->f);
2085 boff = it->f->output_data.x->baseline_offset;
2086 font_info = NULL;
2088 else
2090 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2091 boff = font_info->baseline_offset;
2092 if (font_info->vertical_centering)
2093 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2096 /* There are no padding glyphs, so there is only one glyph to
2097 produce for the composition. Important is that pixel_width,
2098 ascent and descent are the values of what is drawn by
2099 draw_glyphs (i.e. the values of the overall glyphs composed). */
2100 it->nglyphs = 1;
2102 /* If we have not yet calculated pixel size data of glyphs of
2103 the composition for the current face font, calculate them
2104 now. Theoretically, we have to check all fonts for the
2105 glyphs, but that requires much time and memory space. So,
2106 here we check only the font of the first glyph. This leads
2107 to incorrect display very rarely, and C-l (recenter) can
2108 correct the display anyway. */
2109 if (cmp->font != (void *) font)
2111 /* Ascent and descent of the font of the first character of
2112 this composition (adjusted by baseline offset). Ascent
2113 and descent of overall glyphs should not be less than
2114 them respectively. */
2115 int font_ascent = font->ascent + boff;
2116 int font_descent = font->descent - boff;
2117 /* Bounding box of the overall glyphs. */
2118 int leftmost, rightmost, lowest, highest;
2119 int i, width, ascent, descent;
2121 cmp->font = (void *) font;
2123 /* Initialize the bounding box. */
2124 if (font_info
2125 && (pcm = x_per_char_metric (font, &char2b)))
2127 width = pcm->width;
2128 ascent = pcm->ascent;
2129 descent = pcm->descent;
2131 else
2133 width = FONT_WIDTH (font);
2134 ascent = font->ascent;
2135 descent = font->descent;
2138 rightmost = width;
2139 lowest = - descent + boff;
2140 highest = ascent + boff;
2141 leftmost = 0;
2143 if (font_info
2144 && font_info->default_ascent
2145 && CHAR_TABLE_P (Vuse_default_ascent)
2146 && !NILP (Faref (Vuse_default_ascent,
2147 make_number (it->char_to_display))))
2148 highest = font_info->default_ascent + boff;
2150 /* Draw the first glyph at the normal position. It may be
2151 shifted to right later if some other glyphs are drawn at
2152 the left. */
2153 cmp->offsets[0] = 0;
2154 cmp->offsets[1] = boff;
2156 /* Set cmp->offsets for the remaining glyphs. */
2157 for (i = 1; i < cmp->glyph_len; i++)
2159 int left, right, btm, top;
2160 int ch = COMPOSITION_GLYPH (cmp, i);
2161 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2163 face = FACE_FROM_ID (it->f, face_id);
2164 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2165 it->multibyte_p);
2166 font = face->font;
2167 if (font == NULL)
2169 font = FRAME_FONT (it->f);
2170 boff = it->f->output_data.x->baseline_offset;
2171 font_info = NULL;
2173 else
2175 font_info
2176 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2177 boff = font_info->baseline_offset;
2178 if (font_info->vertical_centering)
2179 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2182 if (font_info
2183 && (pcm = x_per_char_metric (font, &char2b)))
2185 width = pcm->width;
2186 ascent = pcm->ascent;
2187 descent = pcm->descent;
2189 else
2191 width = FONT_WIDTH (font);
2192 ascent = 1;
2193 descent = 0;
2196 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2198 /* Relative composition with or without
2199 alternate chars. */
2200 left = (leftmost + rightmost - width) / 2;
2201 btm = - descent + boff;
2202 if (font_info && font_info->relative_compose
2203 && (! CHAR_TABLE_P (Vignore_relative_composition)
2204 || NILP (Faref (Vignore_relative_composition,
2205 make_number (ch)))))
2208 if (- descent >= font_info->relative_compose)
2209 /* One extra pixel between two glyphs. */
2210 btm = highest + 1;
2211 else if (ascent <= 0)
2212 /* One extra pixel between two glyphs. */
2213 btm = lowest - 1 - ascent - descent;
2216 else
2218 /* A composition rule is specified by an integer
2219 value that encodes global and new reference
2220 points (GREF and NREF). GREF and NREF are
2221 specified by numbers as below:
2223 0---1---2 -- ascent
2227 9--10--11 -- center
2229 ---3---4---5--- baseline
2231 6---7---8 -- descent
2233 int rule = COMPOSITION_RULE (cmp, i);
2234 int gref, nref, grefx, grefy, nrefx, nrefy;
2236 COMPOSITION_DECODE_RULE (rule, gref, nref);
2237 grefx = gref % 3, nrefx = nref % 3;
2238 grefy = gref / 3, nrefy = nref / 3;
2240 left = (leftmost
2241 + grefx * (rightmost - leftmost) / 2
2242 - nrefx * width / 2);
2243 btm = ((grefy == 0 ? highest
2244 : grefy == 1 ? 0
2245 : grefy == 2 ? lowest
2246 : (highest + lowest) / 2)
2247 - (nrefy == 0 ? ascent + descent
2248 : nrefy == 1 ? descent - boff
2249 : nrefy == 2 ? 0
2250 : (ascent + descent) / 2));
2253 cmp->offsets[i * 2] = left;
2254 cmp->offsets[i * 2 + 1] = btm + descent;
2256 /* Update the bounding box of the overall glyphs. */
2257 right = left + width;
2258 top = btm + descent + ascent;
2259 if (left < leftmost)
2260 leftmost = left;
2261 if (right > rightmost)
2262 rightmost = right;
2263 if (top > highest)
2264 highest = top;
2265 if (btm < lowest)
2266 lowest = btm;
2269 /* If there are glyphs whose x-offsets are negative,
2270 shift all glyphs to the right and make all x-offsets
2271 non-negative. */
2272 if (leftmost < 0)
2274 for (i = 0; i < cmp->glyph_len; i++)
2275 cmp->offsets[i * 2] -= leftmost;
2276 rightmost -= leftmost;
2279 cmp->pixel_width = rightmost;
2280 cmp->ascent = highest;
2281 cmp->descent = - lowest;
2282 if (cmp->ascent < font_ascent)
2283 cmp->ascent = font_ascent;
2284 if (cmp->descent < font_descent)
2285 cmp->descent = font_descent;
2288 it->pixel_width = cmp->pixel_width;
2289 it->ascent = it->phys_ascent = cmp->ascent;
2290 it->descent = it->phys_descent = cmp->descent;
2292 if (face->box != FACE_NO_BOX)
2294 int thick = face->box_line_width;
2296 if (thick > 0)
2298 it->ascent += thick;
2299 it->descent += thick;
2301 else
2302 thick = - thick;
2304 if (it->start_of_box_run_p)
2305 it->pixel_width += thick;
2306 if (it->end_of_box_run_p)
2307 it->pixel_width += thick;
2310 /* If face has an overline, add the height of the overline
2311 (1 pixel) and a 1 pixel margin to the character height. */
2312 if (face->overline_p)
2313 it->ascent += 2;
2315 take_vertical_position_into_account (it);
2317 if (it->glyph_row)
2318 x_append_composite_glyph (it);
2320 else if (it->what == IT_IMAGE)
2321 x_produce_image_glyph (it);
2322 else if (it->what == IT_STRETCH)
2323 x_produce_stretch_glyph (it);
2325 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2326 because this isn't true for images with `:ascent 100'. */
2327 xassert (it->ascent >= 0 && it->descent >= 0);
2328 if (it->area == TEXT_AREA)
2329 it->current_x += it->pixel_width;
2331 it->descent += it->extra_line_spacing;
2333 it->max_ascent = max (it->max_ascent, it->ascent);
2334 it->max_descent = max (it->max_descent, it->descent);
2335 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2336 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2340 /* Estimate the pixel height of the mode or top line on frame F.
2341 FACE_ID specifies what line's height to estimate. */
2344 x_estimate_mode_line_height (f, face_id)
2345 struct frame *f;
2346 enum face_id face_id;
2348 int height = FONT_HEIGHT (FRAME_FONT (f));
2350 /* This function is called so early when Emacs starts that the face
2351 cache and mode line face are not yet initialized. */
2352 if (FRAME_FACE_CACHE (f))
2354 struct face *face = FACE_FROM_ID (f, face_id);
2355 if (face)
2357 if (face->font)
2358 height = FONT_HEIGHT (face->font);
2359 if (face->box_line_width > 0)
2360 height += 2 * face->box_line_width;
2364 return height;
2368 /***********************************************************************
2369 Glyph display
2370 ***********************************************************************/
2372 /* A sequence of glyphs to be drawn in the same face.
2374 This data structure is not really completely X specific, so it
2375 could possibly, at least partially, be useful for other systems. It
2376 is currently not part of the external redisplay interface because
2377 it's not clear what other systems will need. */
2379 struct glyph_string
2381 /* X-origin of the string. */
2382 int x;
2384 /* Y-origin and y-position of the base line of this string. */
2385 int y, ybase;
2387 /* The width of the string, not including a face extension. */
2388 int width;
2390 /* The width of the string, including a face extension. */
2391 int background_width;
2393 /* The height of this string. This is the height of the line this
2394 string is drawn in, and can be different from the height of the
2395 font the string is drawn in. */
2396 int height;
2398 /* Number of pixels this string overwrites in front of its x-origin.
2399 This number is zero if the string has an lbearing >= 0; it is
2400 -lbearing, if the string has an lbearing < 0. */
2401 int left_overhang;
2403 /* Number of pixels this string overwrites past its right-most
2404 nominal x-position, i.e. x + width. Zero if the string's
2405 rbearing is <= its nominal width, rbearing - width otherwise. */
2406 int right_overhang;
2408 /* The frame on which the glyph string is drawn. */
2409 struct frame *f;
2411 /* The window on which the glyph string is drawn. */
2412 struct window *w;
2414 /* X display and window for convenience. */
2415 Display *display;
2416 Window window;
2418 /* The glyph row for which this string was built. It determines the
2419 y-origin and height of the string. */
2420 struct glyph_row *row;
2422 /* The area within row. */
2423 enum glyph_row_area area;
2425 /* Characters to be drawn, and number of characters. */
2426 XChar2b *char2b;
2427 int nchars;
2429 /* A face-override for drawing cursors, mouse face and similar. */
2430 enum draw_glyphs_face hl;
2432 /* Face in which this string is to be drawn. */
2433 struct face *face;
2435 /* Font in which this string is to be drawn. */
2436 XFontStruct *font;
2438 /* Font info for this string. */
2439 struct font_info *font_info;
2441 /* Non-null means this string describes (part of) a composition.
2442 All characters from char2b are drawn composed. */
2443 struct composition *cmp;
2445 /* Index of this glyph string's first character in the glyph
2446 definition of CMP. If this is zero, this glyph string describes
2447 the first character of a composition. */
2448 int gidx;
2450 /* 1 means this glyph strings face has to be drawn to the right end
2451 of the window's drawing area. */
2452 unsigned extends_to_end_of_line_p : 1;
2454 /* 1 means the background of this string has been drawn. */
2455 unsigned background_filled_p : 1;
2457 /* 1 means glyph string must be drawn with 16-bit functions. */
2458 unsigned two_byte_p : 1;
2460 /* 1 means that the original font determined for drawing this glyph
2461 string could not be loaded. The member `font' has been set to
2462 the frame's default font in this case. */
2463 unsigned font_not_found_p : 1;
2465 /* 1 means that the face in which this glyph string is drawn has a
2466 stipple pattern. */
2467 unsigned stippled_p : 1;
2469 /* 1 means only the foreground of this glyph string must be drawn,
2470 and we should use the physical height of the line this glyph
2471 string appears in as clip rect. */
2472 unsigned for_overlaps_p : 1;
2474 /* The GC to use for drawing this glyph string. */
2475 GC gc;
2477 /* A pointer to the first glyph in the string. This glyph
2478 corresponds to char2b[0]. Needed to draw rectangles if
2479 font_not_found_p is 1. */
2480 struct glyph *first_glyph;
2482 /* Image, if any. */
2483 struct image *img;
2485 struct glyph_string *next, *prev;
2489 #if 1
2491 static void
2492 x_dump_glyph_string (s)
2493 struct glyph_string *s;
2495 fprintf (stderr, "glyph string\n");
2496 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2497 s->x, s->y, s->width, s->height);
2498 fprintf (stderr, " ybase = %d\n", s->ybase);
2499 fprintf (stderr, " hl = %d\n", s->hl);
2500 fprintf (stderr, " left overhang = %d, right = %d\n",
2501 s->left_overhang, s->right_overhang);
2502 fprintf (stderr, " nchars = %d\n", s->nchars);
2503 fprintf (stderr, " extends to end of line = %d\n",
2504 s->extends_to_end_of_line_p);
2505 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2506 fprintf (stderr, " bg width = %d\n", s->background_width);
2509 #endif /* GLYPH_DEBUG */
2513 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2514 struct glyph_string **,
2515 struct glyph_string *,
2516 struct glyph_string *));
2517 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2518 struct glyph_string **,
2519 struct glyph_string *,
2520 struct glyph_string *));
2521 static void x_append_glyph_string P_ ((struct glyph_string **,
2522 struct glyph_string **,
2523 struct glyph_string *));
2524 static int x_left_overwritten P_ ((struct glyph_string *));
2525 static int x_left_overwriting P_ ((struct glyph_string *));
2526 static int x_right_overwritten P_ ((struct glyph_string *));
2527 static int x_right_overwriting P_ ((struct glyph_string *));
2528 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2529 int));
2530 static void x_init_glyph_string P_ ((struct glyph_string *,
2531 XChar2b *, struct window *,
2532 struct glyph_row *,
2533 enum glyph_row_area, int,
2534 enum draw_glyphs_face));
2535 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2536 enum glyph_row_area, int, int,
2537 enum draw_glyphs_face, int *, int *, int));
2538 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2539 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2540 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2541 int));
2542 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2543 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2544 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2545 static void x_draw_glyph_string P_ ((struct glyph_string *));
2546 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2547 static void x_set_cursor_gc P_ ((struct glyph_string *));
2548 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2549 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2550 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2551 int *, int *));
2552 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2553 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2554 unsigned long *, double, int));
2555 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2556 double, int, unsigned long));
2557 static void x_setup_relief_colors P_ ((struct glyph_string *));
2558 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2559 static void x_draw_image_relief P_ ((struct glyph_string *));
2560 static void x_draw_image_foreground P_ ((struct glyph_string *));
2561 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2562 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2563 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2564 int, int, int));
2565 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2566 int, int, int, int, XRectangle *));
2567 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2568 int, int, int, XRectangle *));
2569 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2570 enum glyph_row_area));
2571 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2572 struct glyph_row *,
2573 enum glyph_row_area, int, int));
2575 #if GLYPH_DEBUG
2576 static void x_check_font P_ ((struct frame *, XFontStruct *));
2577 #endif
2580 /* Append the list of glyph strings with head H and tail T to the list
2581 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2583 static INLINE void
2584 x_append_glyph_string_lists (head, tail, h, t)
2585 struct glyph_string **head, **tail;
2586 struct glyph_string *h, *t;
2588 if (h)
2590 if (*head)
2591 (*tail)->next = h;
2592 else
2593 *head = h;
2594 h->prev = *tail;
2595 *tail = t;
2600 /* Prepend the list of glyph strings with head H and tail T to the
2601 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2602 result. */
2604 static INLINE void
2605 x_prepend_glyph_string_lists (head, tail, h, t)
2606 struct glyph_string **head, **tail;
2607 struct glyph_string *h, *t;
2609 if (h)
2611 if (*head)
2612 (*head)->prev = t;
2613 else
2614 *tail = t;
2615 t->next = *head;
2616 *head = h;
2621 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2622 Set *HEAD and *TAIL to the resulting list. */
2624 static INLINE void
2625 x_append_glyph_string (head, tail, s)
2626 struct glyph_string **head, **tail;
2627 struct glyph_string *s;
2629 s->next = s->prev = NULL;
2630 x_append_glyph_string_lists (head, tail, s, s);
2634 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2635 face. */
2637 static void
2638 x_set_cursor_gc (s)
2639 struct glyph_string *s;
2641 if (s->font == FRAME_FONT (s->f)
2642 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2643 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2644 && !s->cmp)
2645 s->gc = s->f->output_data.x->cursor_gc;
2646 else
2648 /* Cursor on non-default face: must merge. */
2649 XGCValues xgcv;
2650 unsigned long mask;
2652 xgcv.background = s->f->output_data.x->cursor_pixel;
2653 xgcv.foreground = s->face->background;
2655 /* If the glyph would be invisible, try a different foreground. */
2656 if (xgcv.foreground == xgcv.background)
2657 xgcv.foreground = s->face->foreground;
2658 if (xgcv.foreground == xgcv.background)
2659 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2660 if (xgcv.foreground == xgcv.background)
2661 xgcv.foreground = s->face->foreground;
2663 /* Make sure the cursor is distinct from text in this face. */
2664 if (xgcv.background == s->face->background
2665 && xgcv.foreground == s->face->foreground)
2667 xgcv.background = s->face->foreground;
2668 xgcv.foreground = s->face->background;
2671 IF_DEBUG (x_check_font (s->f, s->font));
2672 xgcv.font = s->font->fid;
2673 xgcv.graphics_exposures = False;
2674 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2676 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2677 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2678 mask, &xgcv);
2679 else
2680 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2681 = XCreateGC (s->display, s->window, mask, &xgcv);
2683 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2688 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2690 static void
2691 x_set_mouse_face_gc (s)
2692 struct glyph_string *s;
2694 int face_id;
2695 struct face *face;
2697 /* What face has to be used last for the mouse face? */
2698 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2699 face = FACE_FROM_ID (s->f, face_id);
2700 if (face == NULL)
2701 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2703 if (s->first_glyph->type == CHAR_GLYPH)
2704 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2705 else
2706 face_id = FACE_FOR_CHAR (s->f, face, 0);
2707 s->face = FACE_FROM_ID (s->f, face_id);
2708 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2710 /* If font in this face is same as S->font, use it. */
2711 if (s->font == s->face->font)
2712 s->gc = s->face->gc;
2713 else
2715 /* Otherwise construct scratch_cursor_gc with values from FACE
2716 but font FONT. */
2717 XGCValues xgcv;
2718 unsigned long mask;
2720 xgcv.background = s->face->background;
2721 xgcv.foreground = s->face->foreground;
2722 IF_DEBUG (x_check_font (s->f, s->font));
2723 xgcv.font = s->font->fid;
2724 xgcv.graphics_exposures = False;
2725 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2727 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2728 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2729 mask, &xgcv);
2730 else
2731 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2732 = XCreateGC (s->display, s->window, mask, &xgcv);
2734 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2737 xassert (s->gc != 0);
2741 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2742 Faces to use in the mode line have already been computed when the
2743 matrix was built, so there isn't much to do, here. */
2745 static INLINE void
2746 x_set_mode_line_face_gc (s)
2747 struct glyph_string *s;
2749 s->gc = s->face->gc;
2753 /* Set S->gc of glyph string S for drawing that glyph string. Set
2754 S->stippled_p to a non-zero value if the face of S has a stipple
2755 pattern. */
2757 static INLINE void
2758 x_set_glyph_string_gc (s)
2759 struct glyph_string *s;
2761 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2763 if (s->hl == DRAW_NORMAL_TEXT)
2765 s->gc = s->face->gc;
2766 s->stippled_p = s->face->stipple != 0;
2768 else if (s->hl == DRAW_INVERSE_VIDEO)
2770 x_set_mode_line_face_gc (s);
2771 s->stippled_p = s->face->stipple != 0;
2773 else if (s->hl == DRAW_CURSOR)
2775 x_set_cursor_gc (s);
2776 s->stippled_p = 0;
2778 else if (s->hl == DRAW_MOUSE_FACE)
2780 x_set_mouse_face_gc (s);
2781 s->stippled_p = s->face->stipple != 0;
2783 else if (s->hl == DRAW_IMAGE_RAISED
2784 || s->hl == DRAW_IMAGE_SUNKEN)
2786 s->gc = s->face->gc;
2787 s->stippled_p = s->face->stipple != 0;
2789 else
2791 s->gc = s->face->gc;
2792 s->stippled_p = s->face->stipple != 0;
2795 /* GC must have been set. */
2796 xassert (s->gc != 0);
2800 /* Return in *R the clipping rectangle for glyph string S. */
2802 static void
2803 x_get_glyph_string_clip_rect (s, r)
2804 struct glyph_string *s;
2805 XRectangle *r;
2807 if (s->row->full_width_p)
2809 /* Draw full-width. X coordinates are relative to S->w->left. */
2810 int canon_x = CANON_X_UNIT (s->f);
2812 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2813 r->width = XFASTINT (s->w->width) * canon_x;
2815 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2817 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2818 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2819 r->x -= width;
2822 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2824 /* Unless displaying a mode or menu bar line, which are always
2825 fully visible, clip to the visible part of the row. */
2826 if (s->w->pseudo_window_p)
2827 r->height = s->row->visible_height;
2828 else
2829 r->height = s->height;
2831 else
2833 /* This is a text line that may be partially visible. */
2834 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2835 r->width = window_box_width (s->w, s->area);
2836 r->height = s->row->visible_height;
2839 /* Don't use S->y for clipping because it doesn't take partially
2840 visible lines into account. For example, it can be negative for
2841 partially visible lines at the top of a window. */
2842 if (!s->row->full_width_p
2843 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2844 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2845 else
2846 r->y = max (0, s->row->y);
2848 /* If drawing a tool-bar window, draw it over the internal border
2849 at the top of the window. */
2850 if (s->w == XWINDOW (s->f->tool_bar_window))
2851 r->y -= s->f->output_data.x->internal_border_width;
2853 /* If S draws overlapping rows, it's sufficient to use the top and
2854 bottom of the window for clipping because this glyph string
2855 intentionally draws over other lines. */
2856 if (s->for_overlaps_p)
2858 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2859 r->height = window_text_bottom_y (s->w) - r->y;
2862 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2866 /* Set clipping for output of glyph string S. S may be part of a mode
2867 line or menu if we don't have X toolkit support. */
2869 static INLINE void
2870 x_set_glyph_string_clipping (s)
2871 struct glyph_string *s;
2873 XRectangle r;
2874 x_get_glyph_string_clip_rect (s, &r);
2875 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2879 /* Compute left and right overhang of glyph string S. If S is a glyph
2880 string for a composition, assume overhangs don't exist. */
2882 static INLINE void
2883 x_compute_glyph_string_overhangs (s)
2884 struct glyph_string *s;
2886 if (s->cmp == NULL
2887 && s->first_glyph->type == CHAR_GLYPH)
2889 XCharStruct cs;
2890 int direction, font_ascent, font_descent;
2891 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2892 &font_ascent, &font_descent, &cs);
2893 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2894 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2899 /* Compute overhangs and x-positions for glyph string S and its
2900 predecessors, or successors. X is the starting x-position for S.
2901 BACKWARD_P non-zero means process predecessors. */
2903 static void
2904 x_compute_overhangs_and_x (s, x, backward_p)
2905 struct glyph_string *s;
2906 int x;
2907 int backward_p;
2909 if (backward_p)
2911 while (s)
2913 x_compute_glyph_string_overhangs (s);
2914 x -= s->width;
2915 s->x = x;
2916 s = s->prev;
2919 else
2921 while (s)
2923 x_compute_glyph_string_overhangs (s);
2924 s->x = x;
2925 x += s->width;
2926 s = s->next;
2932 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2933 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2934 assumed to be zero. */
2936 static void
2937 x_get_glyph_overhangs (glyph, f, left, right)
2938 struct glyph *glyph;
2939 struct frame *f;
2940 int *left, *right;
2942 *left = *right = 0;
2944 if (glyph->type == CHAR_GLYPH)
2946 XFontStruct *font;
2947 struct face *face;
2948 struct font_info *font_info;
2949 XChar2b char2b;
2950 XCharStruct *pcm;
2952 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2953 font = face->font;
2954 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2955 if (font
2956 && (pcm = x_per_char_metric (font, &char2b)))
2958 if (pcm->rbearing > pcm->width)
2959 *right = pcm->rbearing - pcm->width;
2960 if (pcm->lbearing < 0)
2961 *left = -pcm->lbearing;
2967 /* Return the index of the first glyph preceding glyph string S that
2968 is overwritten by S because of S's left overhang. Value is -1
2969 if no glyphs are overwritten. */
2971 static int
2972 x_left_overwritten (s)
2973 struct glyph_string *s;
2975 int k;
2977 if (s->left_overhang)
2979 int x = 0, i;
2980 struct glyph *glyphs = s->row->glyphs[s->area];
2981 int first = s->first_glyph - glyphs;
2983 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2984 x -= glyphs[i].pixel_width;
2986 k = i + 1;
2988 else
2989 k = -1;
2991 return k;
2995 /* Return the index of the first glyph preceding glyph string S that
2996 is overwriting S because of its right overhang. Value is -1 if no
2997 glyph in front of S overwrites S. */
2999 static int
3000 x_left_overwriting (s)
3001 struct glyph_string *s;
3003 int i, k, x;
3004 struct glyph *glyphs = s->row->glyphs[s->area];
3005 int first = s->first_glyph - glyphs;
3007 k = -1;
3008 x = 0;
3009 for (i = first - 1; i >= 0; --i)
3011 int left, right;
3012 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3013 if (x + right > 0)
3014 k = i;
3015 x -= glyphs[i].pixel_width;
3018 return k;
3022 /* Return the index of the last glyph following glyph string S that is
3023 not overwritten by S because of S's right overhang. Value is -1 if
3024 no such glyph is found. */
3026 static int
3027 x_right_overwritten (s)
3028 struct glyph_string *s;
3030 int k = -1;
3032 if (s->right_overhang)
3034 int x = 0, i;
3035 struct glyph *glyphs = s->row->glyphs[s->area];
3036 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3037 int end = s->row->used[s->area];
3039 for (i = first; i < end && s->right_overhang > x; ++i)
3040 x += glyphs[i].pixel_width;
3042 k = i;
3045 return k;
3049 /* Return the index of the last glyph following glyph string S that
3050 overwrites S because of its left overhang. Value is negative
3051 if no such glyph is found. */
3053 static int
3054 x_right_overwriting (s)
3055 struct glyph_string *s;
3057 int i, k, x;
3058 int end = s->row->used[s->area];
3059 struct glyph *glyphs = s->row->glyphs[s->area];
3060 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3062 k = -1;
3063 x = 0;
3064 for (i = first; i < end; ++i)
3066 int left, right;
3067 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3068 if (x - left < 0)
3069 k = i;
3070 x += glyphs[i].pixel_width;
3073 return k;
3077 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3079 static INLINE void
3080 x_clear_glyph_string_rect (s, x, y, w, h)
3081 struct glyph_string *s;
3082 int x, y, w, h;
3084 XGCValues xgcv;
3085 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3086 XSetForeground (s->display, s->gc, xgcv.background);
3087 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3088 XSetForeground (s->display, s->gc, xgcv.foreground);
3092 /* Draw the background of glyph_string S. If S->background_filled_p
3093 is non-zero don't draw it. FORCE_P non-zero means draw the
3094 background even if it wouldn't be drawn normally. This is used
3095 when a string preceding S draws into the background of S, or S
3096 contains the first component of a composition. */
3098 static void
3099 x_draw_glyph_string_background (s, force_p)
3100 struct glyph_string *s;
3101 int force_p;
3103 /* Nothing to do if background has already been drawn or if it
3104 shouldn't be drawn in the first place. */
3105 if (!s->background_filled_p)
3107 int box_line_width = max (s->face->box_line_width, 0);
3109 if (s->stippled_p)
3111 /* Fill background with a stipple pattern. */
3112 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3113 XFillRectangle (s->display, s->window, s->gc, s->x,
3114 s->y + box_line_width,
3115 s->background_width,
3116 s->height - 2 * box_line_width);
3117 XSetFillStyle (s->display, s->gc, FillSolid);
3118 s->background_filled_p = 1;
3120 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3121 || s->font_not_found_p
3122 || s->extends_to_end_of_line_p
3123 || force_p)
3125 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3126 s->background_width,
3127 s->height - 2 * box_line_width);
3128 s->background_filled_p = 1;
3134 /* Draw the foreground of glyph string S. */
3136 static void
3137 x_draw_glyph_string_foreground (s)
3138 struct glyph_string *s;
3140 int i, x;
3142 /* If first glyph of S has a left box line, start drawing the text
3143 of S to the right of that box line. */
3144 if (s->face->box != FACE_NO_BOX
3145 && s->first_glyph->left_box_line_p)
3146 x = s->x + abs (s->face->box_line_width);
3147 else
3148 x = s->x;
3150 /* Draw characters of S as rectangles if S's font could not be
3151 loaded. */
3152 if (s->font_not_found_p)
3154 for (i = 0; i < s->nchars; ++i)
3156 struct glyph *g = s->first_glyph + i;
3157 XDrawRectangle (s->display, s->window,
3158 s->gc, x, s->y, g->pixel_width - 1,
3159 s->height - 1);
3160 x += g->pixel_width;
3163 else
3165 char *char1b = (char *) s->char2b;
3166 int boff = s->font_info->baseline_offset;
3168 if (s->font_info->vertical_centering)
3169 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3171 /* If we can use 8-bit functions, condense S->char2b. */
3172 if (!s->two_byte_p)
3173 for (i = 0; i < s->nchars; ++i)
3174 char1b[i] = s->char2b[i].byte2;
3176 /* Draw text with XDrawString if background has already been
3177 filled. Otherwise, use XDrawImageString. (Note that
3178 XDrawImageString is usually faster than XDrawString.) Always
3179 use XDrawImageString when drawing the cursor so that there is
3180 no chance that characters under a box cursor are invisible. */
3181 if (s->for_overlaps_p
3182 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3184 /* Draw characters with 16-bit or 8-bit functions. */
3185 if (s->two_byte_p)
3186 XDrawString16 (s->display, s->window, s->gc, x,
3187 s->ybase - boff, s->char2b, s->nchars);
3188 else
3189 XDrawString (s->display, s->window, s->gc, x,
3190 s->ybase - boff, char1b, s->nchars);
3192 else
3194 if (s->two_byte_p)
3195 XDrawImageString16 (s->display, s->window, s->gc, x,
3196 s->ybase - boff, s->char2b, s->nchars);
3197 else
3198 XDrawImageString (s->display, s->window, s->gc, x,
3199 s->ybase - boff, char1b, s->nchars);
3204 /* Draw the foreground of composite glyph string S. */
3206 static void
3207 x_draw_composite_glyph_string_foreground (s)
3208 struct glyph_string *s;
3210 int i, x;
3212 /* If first glyph of S has a left box line, start drawing the text
3213 of S to the right of that box line. */
3214 if (s->face->box != FACE_NO_BOX
3215 && s->first_glyph->left_box_line_p)
3216 x = s->x + abs (s->face->box_line_width);
3217 else
3218 x = s->x;
3220 /* S is a glyph string for a composition. S->gidx is the index of
3221 the first character drawn for glyphs of this composition.
3222 S->gidx == 0 means we are drawing the very first character of
3223 this composition. */
3225 /* Draw a rectangle for the composition if the font for the very
3226 first character of the composition could not be loaded. */
3227 if (s->font_not_found_p)
3229 if (s->gidx == 0)
3230 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3231 s->width - 1, s->height - 1);
3233 else
3235 for (i = 0; i < s->nchars; i++, ++s->gidx)
3236 XDrawString16 (s->display, s->window, s->gc,
3237 x + s->cmp->offsets[s->gidx * 2],
3238 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3239 s->char2b + i, 1);
3244 #ifdef USE_X_TOOLKIT
3246 static struct frame *x_frame_of_widget P_ ((Widget));
3249 /* Return the frame on which widget WIDGET is used.. Abort if frame
3250 cannot be determined. */
3252 static struct frame *
3253 x_frame_of_widget (widget)
3254 Widget widget;
3256 struct x_display_info *dpyinfo;
3257 Lisp_Object tail;
3258 struct frame *f;
3260 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3262 /* Find the top-level shell of the widget. Note that this function
3263 can be called when the widget is not yet realized, so XtWindow
3264 (widget) == 0. That's the reason we can't simply use
3265 x_any_window_to_frame. */
3266 while (!XtIsTopLevelShell (widget))
3267 widget = XtParent (widget);
3269 /* Look for a frame with that top-level widget. Allocate the color
3270 on that frame to get the right gamma correction value. */
3271 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3272 if (GC_FRAMEP (XCAR (tail))
3273 && (f = XFRAME (XCAR (tail)),
3274 (f->output_data.nothing != 1
3275 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3276 && f->output_data.x->widget == widget)
3277 return f;
3279 abort ();
3283 /* Allocate the color COLOR->pixel on the screen and display of
3284 widget WIDGET in colormap CMAP. If an exact match cannot be
3285 allocated, try the nearest color available. Value is non-zero
3286 if successful. This is called from lwlib. */
3289 x_alloc_nearest_color_for_widget (widget, cmap, color)
3290 Widget widget;
3291 Colormap cmap;
3292 XColor *color;
3294 struct frame *f = x_frame_of_widget (widget);
3295 return x_alloc_nearest_color (f, cmap, color);
3299 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3300 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3301 If this produces the same color as PIXEL, try a color where all RGB
3302 values have DELTA added. Return the allocated color in *PIXEL.
3303 DISPLAY is the X display, CMAP is the colormap to operate on.
3304 Value is non-zero if successful. */
3307 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3308 Widget widget;
3309 Display *display;
3310 Colormap cmap;
3311 unsigned long *pixel;
3312 double factor;
3313 int delta;
3315 struct frame *f = x_frame_of_widget (widget);
3316 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3320 #endif /* USE_X_TOOLKIT */
3323 /* Value is an array of XColor structures for the contents of the
3324 color map of frame F. Set *NCELLS to the size of the array.
3325 Note that this probably shouldn't be called for large color maps,
3326 say a 24-bit TrueColor map. */
3328 static const XColor *
3329 x_color_cells (f, ncells)
3330 struct frame *f;
3331 int *ncells;
3333 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3335 if (dpyinfo->color_cells == NULL)
3337 Display *display = FRAME_X_DISPLAY (f);
3338 Screen *screen = FRAME_X_SCREEN (f);
3339 int i;
3341 dpyinfo->ncolor_cells
3342 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3343 dpyinfo->color_cells
3344 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3345 * sizeof *dpyinfo->color_cells);
3347 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3348 dpyinfo->color_cells[i].pixel = i;
3350 XQueryColors (display, FRAME_X_COLORMAP (f),
3351 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3354 *ncells = dpyinfo->ncolor_cells;
3355 return dpyinfo->color_cells;
3359 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3360 colors in COLORS. Use cached information, if available. */
3362 void
3363 x_query_colors (f, colors, ncolors)
3364 struct frame *f;
3365 XColor *colors;
3366 int ncolors;
3368 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3370 if (dpyinfo->color_cells)
3372 int i;
3373 for (i = 0; i < ncolors; ++i)
3375 unsigned long pixel = colors[i].pixel;
3376 xassert (pixel < dpyinfo->ncolor_cells);
3377 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3378 colors[i] = dpyinfo->color_cells[pixel];
3381 else
3382 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3386 /* On frame F, translate pixel color to RGB values for the color in
3387 COLOR. Use cached information, if available. */
3389 void
3390 x_query_color (f, color)
3391 struct frame *f;
3392 XColor *color;
3394 x_query_colors (f, color, 1);
3398 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3399 CMAP. If an exact match can't be allocated, try the nearest color
3400 available. Value is non-zero if successful. Set *COLOR to the
3401 color allocated. */
3404 x_alloc_nearest_color (f, cmap, color)
3405 struct frame *f;
3406 Colormap cmap;
3407 XColor *color;
3409 Display *display = FRAME_X_DISPLAY (f);
3410 Screen *screen = FRAME_X_SCREEN (f);
3411 int rc;
3413 gamma_correct (f, color);
3414 rc = XAllocColor (display, cmap, color);
3415 if (rc == 0)
3417 /* If we got to this point, the colormap is full, so we're going
3418 to try to get the next closest color. The algorithm used is
3419 a least-squares matching, which is what X uses for closest
3420 color matching with StaticColor visuals. */
3421 int nearest, i;
3422 unsigned long nearest_delta = ~0;
3423 int ncells;
3424 const XColor *cells = x_color_cells (f, &ncells);
3426 for (nearest = i = 0; i < ncells; ++i)
3428 long dred = (color->red >> 8) - (cells[i].red >> 8);
3429 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3430 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3431 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3433 if (delta < nearest_delta)
3435 nearest = i;
3436 nearest_delta = delta;
3440 color->red = cells[nearest].red;
3441 color->green = cells[nearest].green;
3442 color->blue = cells[nearest].blue;
3443 rc = XAllocColor (display, cmap, color);
3445 else
3447 /* If allocation succeeded, and the allocated pixel color is not
3448 equal to a cached pixel color recorded earlier, there was a
3449 change in the colormap, so clear the color cache. */
3450 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3451 XColor *cached_color;
3453 if (dpyinfo->color_cells
3454 && (cached_color = &dpyinfo->color_cells[color->pixel],
3455 (cached_color->red != color->red
3456 || cached_color->blue != color->blue
3457 || cached_color->green != color->green)))
3459 xfree (dpyinfo->color_cells);
3460 dpyinfo->color_cells = NULL;
3461 dpyinfo->ncolor_cells = 0;
3465 #ifdef DEBUG_X_COLORS
3466 if (rc)
3467 register_color (color->pixel);
3468 #endif /* DEBUG_X_COLORS */
3470 return rc;
3474 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3475 It's necessary to do this instead of just using PIXEL directly to
3476 get color reference counts right. */
3478 unsigned long
3479 x_copy_color (f, pixel)
3480 struct frame *f;
3481 unsigned long pixel;
3483 XColor color;
3485 color.pixel = pixel;
3486 BLOCK_INPUT;
3487 x_query_color (f, &color);
3488 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3489 UNBLOCK_INPUT;
3490 #ifdef DEBUG_X_COLORS
3491 register_color (pixel);
3492 #endif
3493 return color.pixel;
3497 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3498 It's necessary to do this instead of just using PIXEL directly to
3499 get color reference counts right. */
3501 unsigned long
3502 x_copy_dpy_color (dpy, cmap, pixel)
3503 Display *dpy;
3504 Colormap cmap;
3505 unsigned long pixel;
3507 XColor color;
3509 color.pixel = pixel;
3510 BLOCK_INPUT;
3511 XQueryColor (dpy, cmap, &color);
3512 XAllocColor (dpy, cmap, &color);
3513 UNBLOCK_INPUT;
3514 #ifdef DEBUG_X_COLORS
3515 register_color (pixel);
3516 #endif
3517 return color.pixel;
3521 /* Brightness beyond which a color won't have its highlight brightness
3522 boosted.
3524 Nominally, highlight colors for `3d' faces are calculated by
3525 brightening an object's color by a constant scale factor, but this
3526 doesn't yield good results for dark colors, so for colors who's
3527 brightness is less than this value (on a scale of 0-65535) have an
3528 use an additional additive factor.
3530 The value here is set so that the default menu-bar/mode-line color
3531 (grey75) will not have its highlights changed at all. */
3532 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3535 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3536 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3537 If this produces the same color as PIXEL, try a color where all RGB
3538 values have DELTA added. Return the allocated color in *PIXEL.
3539 DISPLAY is the X display, CMAP is the colormap to operate on.
3540 Value is non-zero if successful. */
3542 static int
3543 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3544 struct frame *f;
3545 Display *display;
3546 Colormap cmap;
3547 unsigned long *pixel;
3548 double factor;
3549 int delta;
3551 XColor color, new;
3552 long bright;
3553 int success_p;
3555 /* Get RGB color values. */
3556 color.pixel = *pixel;
3557 x_query_color (f, &color);
3559 /* Change RGB values by specified FACTOR. Avoid overflow! */
3560 xassert (factor >= 0);
3561 new.red = min (0xffff, factor * color.red);
3562 new.green = min (0xffff, factor * color.green);
3563 new.blue = min (0xffff, factor * color.blue);
3565 /* Calculate brightness of COLOR. */
3566 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3568 /* We only boost colors that are darker than
3569 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3570 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3571 /* Make an additive adjustment to NEW, because it's dark enough so
3572 that scaling by FACTOR alone isn't enough. */
3574 /* How far below the limit this color is (0 - 1, 1 being darker). */
3575 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3576 /* The additive adjustment. */
3577 int min_delta = delta * dimness * factor / 2;
3579 if (factor < 1)
3581 new.red = max (0, new.red - min_delta);
3582 new.green = max (0, new.green - min_delta);
3583 new.blue = max (0, new.blue - min_delta);
3585 else
3587 new.red = min (0xffff, min_delta + new.red);
3588 new.green = min (0xffff, min_delta + new.green);
3589 new.blue = min (0xffff, min_delta + new.blue);
3593 /* Try to allocate the color. */
3594 success_p = x_alloc_nearest_color (f, cmap, &new);
3595 if (success_p)
3597 if (new.pixel == *pixel)
3599 /* If we end up with the same color as before, try adding
3600 delta to the RGB values. */
3601 x_free_colors (f, &new.pixel, 1);
3603 new.red = min (0xffff, delta + color.red);
3604 new.green = min (0xffff, delta + color.green);
3605 new.blue = min (0xffff, delta + color.blue);
3606 success_p = x_alloc_nearest_color (f, cmap, &new);
3608 else
3609 success_p = 1;
3610 *pixel = new.pixel;
3613 return success_p;
3617 /* Set up the foreground color for drawing relief lines of glyph
3618 string S. RELIEF is a pointer to a struct relief containing the GC
3619 with which lines will be drawn. Use a color that is FACTOR or
3620 DELTA lighter or darker than the relief's background which is found
3621 in S->f->output_data.x->relief_background. If such a color cannot
3622 be allocated, use DEFAULT_PIXEL, instead. */
3624 static void
3625 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3626 struct frame *f;
3627 struct relief *relief;
3628 double factor;
3629 int delta;
3630 unsigned long default_pixel;
3632 XGCValues xgcv;
3633 struct x_output *di = f->output_data.x;
3634 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3635 unsigned long pixel;
3636 unsigned long background = di->relief_background;
3637 Colormap cmap = FRAME_X_COLORMAP (f);
3638 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3639 Display *dpy = FRAME_X_DISPLAY (f);
3641 xgcv.graphics_exposures = False;
3642 xgcv.line_width = 1;
3644 /* Free previously allocated color. The color cell will be reused
3645 when it has been freed as many times as it was allocated, so this
3646 doesn't affect faces using the same colors. */
3647 if (relief->gc
3648 && relief->allocated_p)
3650 x_free_colors (f, &relief->pixel, 1);
3651 relief->allocated_p = 0;
3654 /* Allocate new color. */
3655 xgcv.foreground = default_pixel;
3656 pixel = background;
3657 if (dpyinfo->n_planes != 1
3658 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3660 relief->allocated_p = 1;
3661 xgcv.foreground = relief->pixel = pixel;
3664 if (relief->gc == 0)
3666 xgcv.stipple = dpyinfo->gray;
3667 mask |= GCStipple;
3668 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3670 else
3671 XChangeGC (dpy, relief->gc, mask, &xgcv);
3675 /* Set up colors for the relief lines around glyph string S. */
3677 static void
3678 x_setup_relief_colors (s)
3679 struct glyph_string *s;
3681 struct x_output *di = s->f->output_data.x;
3682 unsigned long color;
3684 if (s->face->use_box_color_for_shadows_p)
3685 color = s->face->box_color;
3686 else
3688 XGCValues xgcv;
3690 /* Get the background color of the face. */
3691 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3692 color = xgcv.background;
3695 if (di->white_relief.gc == 0
3696 || color != di->relief_background)
3698 di->relief_background = color;
3699 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3700 WHITE_PIX_DEFAULT (s->f));
3701 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3702 BLACK_PIX_DEFAULT (s->f));
3707 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3708 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3709 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3710 relief. LEFT_P non-zero means draw a relief on the left side of
3711 the rectangle. RIGHT_P non-zero means draw a relief on the right
3712 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3713 when drawing. */
3715 static void
3716 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3717 raised_p, left_p, right_p, clip_rect)
3718 struct frame *f;
3719 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3720 XRectangle *clip_rect;
3722 int i;
3723 GC gc;
3725 if (raised_p)
3726 gc = f->output_data.x->white_relief.gc;
3727 else
3728 gc = f->output_data.x->black_relief.gc;
3729 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3731 /* Top. */
3732 for (i = 0; i < width; ++i)
3733 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3734 left_x + i * left_p, top_y + i,
3735 right_x + 1 - i * right_p, top_y + i);
3737 /* Left. */
3738 if (left_p)
3739 for (i = 0; i < width; ++i)
3740 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3741 left_x + i, top_y + i, left_x + i, bottom_y - i);
3743 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3744 if (raised_p)
3745 gc = f->output_data.x->black_relief.gc;
3746 else
3747 gc = f->output_data.x->white_relief.gc;
3748 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3750 /* Bottom. */
3751 for (i = 0; i < width; ++i)
3752 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3753 left_x + i * left_p, bottom_y - i,
3754 right_x + 1 - i * right_p, bottom_y - i);
3756 /* Right. */
3757 if (right_p)
3758 for (i = 0; i < width; ++i)
3759 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3760 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3762 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3766 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3767 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3768 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3769 left side of the rectangle. RIGHT_P non-zero means draw a line
3770 on the right side of the rectangle. CLIP_RECT is the clipping
3771 rectangle to use when drawing. */
3773 static void
3774 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3775 left_p, right_p, clip_rect)
3776 struct glyph_string *s;
3777 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3778 XRectangle *clip_rect;
3780 XGCValues xgcv;
3782 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3783 XSetForeground (s->display, s->gc, s->face->box_color);
3784 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3786 /* Top. */
3787 XFillRectangle (s->display, s->window, s->gc,
3788 left_x, top_y, right_x - left_x + 1, width);
3790 /* Left. */
3791 if (left_p)
3792 XFillRectangle (s->display, s->window, s->gc,
3793 left_x, top_y, width, bottom_y - top_y + 1);
3795 /* Bottom. */
3796 XFillRectangle (s->display, s->window, s->gc,
3797 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3799 /* Right. */
3800 if (right_p)
3801 XFillRectangle (s->display, s->window, s->gc,
3802 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3804 XSetForeground (s->display, s->gc, xgcv.foreground);
3805 XSetClipMask (s->display, s->gc, None);
3809 /* Draw a box around glyph string S. */
3811 static void
3812 x_draw_glyph_string_box (s)
3813 struct glyph_string *s;
3815 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3816 int left_p, right_p;
3817 struct glyph *last_glyph;
3818 XRectangle clip_rect;
3820 last_x = window_box_right (s->w, s->area);
3821 if (s->row->full_width_p
3822 && !s->w->pseudo_window_p)
3824 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3825 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3826 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3829 /* The glyph that may have a right box line. */
3830 last_glyph = (s->cmp || s->img
3831 ? s->first_glyph
3832 : s->first_glyph + s->nchars - 1);
3834 width = abs (s->face->box_line_width);
3835 raised_p = s->face->box == FACE_RAISED_BOX;
3836 left_x = s->x;
3837 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3838 ? last_x - 1
3839 : min (last_x, s->x + s->background_width) - 1);
3840 top_y = s->y;
3841 bottom_y = top_y + s->height - 1;
3843 left_p = (s->first_glyph->left_box_line_p
3844 || (s->hl == DRAW_MOUSE_FACE
3845 && (s->prev == NULL
3846 || s->prev->hl != s->hl)));
3847 right_p = (last_glyph->right_box_line_p
3848 || (s->hl == DRAW_MOUSE_FACE
3849 && (s->next == NULL
3850 || s->next->hl != s->hl)));
3852 x_get_glyph_string_clip_rect (s, &clip_rect);
3854 if (s->face->box == FACE_SIMPLE_BOX)
3855 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3856 left_p, right_p, &clip_rect);
3857 else
3859 x_setup_relief_colors (s);
3860 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3861 width, raised_p, left_p, right_p, &clip_rect);
3866 /* Draw foreground of image glyph string S. */
3868 static void
3869 x_draw_image_foreground (s)
3870 struct glyph_string *s;
3872 int x;
3873 int y = s->ybase - image_ascent (s->img, s->face);
3875 /* If first glyph of S has a left box line, start drawing it to the
3876 right of that line. */
3877 if (s->face->box != FACE_NO_BOX
3878 && s->first_glyph->left_box_line_p)
3879 x = s->x + abs (s->face->box_line_width);
3880 else
3881 x = s->x;
3883 /* If there is a margin around the image, adjust x- and y-position
3884 by that margin. */
3885 x += s->img->hmargin;
3886 y += s->img->vmargin;
3888 if (s->img->pixmap)
3890 if (s->img->mask)
3892 /* We can't set both a clip mask and use XSetClipRectangles
3893 because the latter also sets a clip mask. We also can't
3894 trust on the shape extension to be available
3895 (XShapeCombineRegion). So, compute the rectangle to draw
3896 manually. */
3897 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3898 | GCFunction);
3899 XGCValues xgcv;
3900 XRectangle clip_rect, image_rect, r;
3902 xgcv.clip_mask = s->img->mask;
3903 xgcv.clip_x_origin = x;
3904 xgcv.clip_y_origin = y;
3905 xgcv.function = GXcopy;
3906 XChangeGC (s->display, s->gc, mask, &xgcv);
3908 x_get_glyph_string_clip_rect (s, &clip_rect);
3909 image_rect.x = x;
3910 image_rect.y = y;
3911 image_rect.width = s->img->width;
3912 image_rect.height = s->img->height;
3913 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3914 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3915 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3917 else
3919 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3920 XGCValues xgcv;
3921 XRectangle clip_rect, image_rect, r;
3923 x_get_glyph_string_clip_rect (s, &clip_rect);
3924 image_rect.x = x;
3925 image_rect.y = y;
3926 image_rect.width = s->img->width;
3927 image_rect.height = s->img->height;
3928 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3929 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3930 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3932 /* When the image has a mask, we can expect that at
3933 least part of a mouse highlight or a block cursor will
3934 be visible. If the image doesn't have a mask, make
3935 a block cursor visible by drawing a rectangle around
3936 the image. I believe it's looking better if we do
3937 nothing here for mouse-face. */
3938 if (s->hl == DRAW_CURSOR)
3939 XDrawRectangle (s->display, s->window, s->gc, x, y,
3940 s->img->width - 1, s->img->height - 1);
3943 else
3944 /* Draw a rectangle if image could not be loaded. */
3945 XDrawRectangle (s->display, s->window, s->gc, x, y,
3946 s->img->width - 1, s->img->height - 1);
3950 /* Draw a relief around the image glyph string S. */
3952 static void
3953 x_draw_image_relief (s)
3954 struct glyph_string *s;
3956 int x0, y0, x1, y1, thick, raised_p;
3957 XRectangle r;
3958 int x;
3959 int y = s->ybase - image_ascent (s->img, s->face);
3961 /* If first glyph of S has a left box line, start drawing it to the
3962 right of that line. */
3963 if (s->face->box != FACE_NO_BOX
3964 && s->first_glyph->left_box_line_p)
3965 x = s->x + abs (s->face->box_line_width);
3966 else
3967 x = s->x;
3969 /* If there is a margin around the image, adjust x- and y-position
3970 by that margin. */
3971 x += s->img->hmargin;
3972 y += s->img->vmargin;
3974 if (s->hl == DRAW_IMAGE_SUNKEN
3975 || s->hl == DRAW_IMAGE_RAISED)
3977 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3978 raised_p = s->hl == DRAW_IMAGE_RAISED;
3980 else
3982 thick = abs (s->img->relief);
3983 raised_p = s->img->relief > 0;
3986 x0 = x - thick;
3987 y0 = y - thick;
3988 x1 = x + s->img->width + thick - 1;
3989 y1 = y + s->img->height + thick - 1;
3991 x_setup_relief_colors (s);
3992 x_get_glyph_string_clip_rect (s, &r);
3993 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3997 /* Draw the foreground of image glyph string S to PIXMAP. */
3999 static void
4000 x_draw_image_foreground_1 (s, pixmap)
4001 struct glyph_string *s;
4002 Pixmap pixmap;
4004 int x;
4005 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4007 /* If first glyph of S has a left box line, start drawing it to the
4008 right of that line. */
4009 if (s->face->box != FACE_NO_BOX
4010 && s->first_glyph->left_box_line_p)
4011 x = abs (s->face->box_line_width);
4012 else
4013 x = 0;
4015 /* If there is a margin around the image, adjust x- and y-position
4016 by that margin. */
4017 x += s->img->hmargin;
4018 y += s->img->vmargin;
4020 if (s->img->pixmap)
4022 if (s->img->mask)
4024 /* We can't set both a clip mask and use XSetClipRectangles
4025 because the latter also sets a clip mask. We also can't
4026 trust on the shape extension to be available
4027 (XShapeCombineRegion). So, compute the rectangle to draw
4028 manually. */
4029 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4030 | GCFunction);
4031 XGCValues xgcv;
4033 xgcv.clip_mask = s->img->mask;
4034 xgcv.clip_x_origin = x;
4035 xgcv.clip_y_origin = y;
4036 xgcv.function = GXcopy;
4037 XChangeGC (s->display, s->gc, mask, &xgcv);
4039 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4040 0, 0, s->img->width, s->img->height, x, y);
4041 XSetClipMask (s->display, s->gc, None);
4043 else
4045 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4046 0, 0, s->img->width, s->img->height, x, y);
4048 /* When the image has a mask, we can expect that at
4049 least part of a mouse highlight or a block cursor will
4050 be visible. If the image doesn't have a mask, make
4051 a block cursor visible by drawing a rectangle around
4052 the image. I believe it's looking better if we do
4053 nothing here for mouse-face. */
4054 if (s->hl == DRAW_CURSOR)
4055 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4056 s->img->width - 1, s->img->height - 1);
4059 else
4060 /* Draw a rectangle if image could not be loaded. */
4061 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4062 s->img->width - 1, s->img->height - 1);
4066 /* Draw part of the background of glyph string S. X, Y, W, and H
4067 give the rectangle to draw. */
4069 static void
4070 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4071 struct glyph_string *s;
4072 int x, y, w, h;
4074 if (s->stippled_p)
4076 /* Fill background with a stipple pattern. */
4077 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4078 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4079 XSetFillStyle (s->display, s->gc, FillSolid);
4081 else
4082 x_clear_glyph_string_rect (s, x, y, w, h);
4086 /* Draw image glyph string S.
4088 s->y
4089 s->x +-------------------------
4090 | s->face->box
4092 | +-------------------------
4093 | | s->img->margin
4095 | | +-------------------
4096 | | | the image
4100 static void
4101 x_draw_image_glyph_string (s)
4102 struct glyph_string *s;
4104 int x, y;
4105 int box_line_hwidth = abs (s->face->box_line_width);
4106 int box_line_vwidth = max (s->face->box_line_width, 0);
4107 int height;
4108 Pixmap pixmap = None;
4110 height = s->height - 2 * box_line_vwidth;
4112 /* Fill background with face under the image. Do it only if row is
4113 taller than image or if image has a clip mask to reduce
4114 flickering. */
4115 s->stippled_p = s->face->stipple != 0;
4116 if (height > s->img->height
4117 || s->img->hmargin
4118 || s->img->vmargin
4119 || s->img->mask
4120 || s->img->pixmap == 0
4121 || s->width != s->background_width)
4123 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4124 x = s->x + box_line_hwidth;
4125 else
4126 x = s->x;
4128 y = s->y + box_line_vwidth;
4130 if (s->img->mask)
4132 /* Create a pixmap as large as the glyph string. Fill it
4133 with the background color. Copy the image to it, using
4134 its mask. Copy the temporary pixmap to the display. */
4135 Screen *screen = FRAME_X_SCREEN (s->f);
4136 int depth = DefaultDepthOfScreen (screen);
4138 /* Create a pixmap as large as the glyph string. */
4139 pixmap = XCreatePixmap (s->display, s->window,
4140 s->background_width,
4141 s->height, depth);
4143 /* Don't clip in the following because we're working on the
4144 pixmap. */
4145 XSetClipMask (s->display, s->gc, None);
4147 /* Fill the pixmap with the background color/stipple. */
4148 if (s->stippled_p)
4150 /* Fill background with a stipple pattern. */
4151 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4152 XFillRectangle (s->display, pixmap, s->gc,
4153 0, 0, s->background_width, s->height);
4154 XSetFillStyle (s->display, s->gc, FillSolid);
4156 else
4158 XGCValues xgcv;
4159 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4160 &xgcv);
4161 XSetForeground (s->display, s->gc, xgcv.background);
4162 XFillRectangle (s->display, pixmap, s->gc,
4163 0, 0, s->background_width, s->height);
4164 XSetForeground (s->display, s->gc, xgcv.foreground);
4167 else
4168 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4170 s->background_filled_p = 1;
4173 /* Draw the foreground. */
4174 if (pixmap != None)
4176 x_draw_image_foreground_1 (s, pixmap);
4177 x_set_glyph_string_clipping (s);
4178 XCopyArea (s->display, pixmap, s->window, s->gc,
4179 0, 0, s->background_width, s->height, s->x, s->y);
4180 XFreePixmap (s->display, pixmap);
4182 else
4183 x_draw_image_foreground (s);
4185 /* If we must draw a relief around the image, do it. */
4186 if (s->img->relief
4187 || s->hl == DRAW_IMAGE_RAISED
4188 || s->hl == DRAW_IMAGE_SUNKEN)
4189 x_draw_image_relief (s);
4193 /* Draw stretch glyph string S. */
4195 static void
4196 x_draw_stretch_glyph_string (s)
4197 struct glyph_string *s;
4199 xassert (s->first_glyph->type == STRETCH_GLYPH);
4200 s->stippled_p = s->face->stipple != 0;
4202 if (s->hl == DRAW_CURSOR
4203 && !x_stretch_cursor_p)
4205 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4206 as wide as the stretch glyph. */
4207 int width = min (CANON_X_UNIT (s->f), s->background_width);
4209 /* Draw cursor. */
4210 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4212 /* Clear rest using the GC of the original non-cursor face. */
4213 if (width < s->background_width)
4215 GC gc = s->face->gc;
4216 int x = s->x + width, y = s->y;
4217 int w = s->background_width - width, h = s->height;
4218 XRectangle r;
4220 x_get_glyph_string_clip_rect (s, &r);
4221 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4223 if (s->face->stipple)
4225 /* Fill background with a stipple pattern. */
4226 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4227 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4228 XSetFillStyle (s->display, gc, FillSolid);
4230 else
4232 XGCValues xgcv;
4233 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4234 XSetForeground (s->display, gc, xgcv.background);
4235 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4236 XSetForeground (s->display, gc, xgcv.foreground);
4240 else
4241 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4242 s->height);
4244 s->background_filled_p = 1;
4248 /* Draw glyph string S. */
4250 static void
4251 x_draw_glyph_string (s)
4252 struct glyph_string *s;
4254 int relief_drawn_p = 0;
4256 /* If S draws into the background of its successor, draw the
4257 background of the successor first so that S can draw into it.
4258 This makes S->next use XDrawString instead of XDrawImageString. */
4259 if (s->next && s->right_overhang && !s->for_overlaps_p)
4261 xassert (s->next->img == NULL);
4262 x_set_glyph_string_gc (s->next);
4263 x_set_glyph_string_clipping (s->next);
4264 x_draw_glyph_string_background (s->next, 1);
4267 /* Set up S->gc, set clipping and draw S. */
4268 x_set_glyph_string_gc (s);
4269 x_set_glyph_string_clipping (s);
4271 /* Draw relief (if any) in advance for char/composition so that the
4272 glyph string can be drawn over it. */
4273 if (!s->for_overlaps_p
4274 && s->face->box != FACE_NO_BOX
4275 && (s->first_glyph->type == CHAR_GLYPH
4276 || s->first_glyph->type == COMPOSITE_GLYPH))
4279 x_draw_glyph_string_background (s, 1);
4280 x_draw_glyph_string_box (s);
4281 relief_drawn_p = 1;
4284 switch (s->first_glyph->type)
4286 case IMAGE_GLYPH:
4287 x_draw_image_glyph_string (s);
4288 break;
4290 case STRETCH_GLYPH:
4291 x_draw_stretch_glyph_string (s);
4292 break;
4294 case CHAR_GLYPH:
4295 if (s->for_overlaps_p)
4296 s->background_filled_p = 1;
4297 else
4298 x_draw_glyph_string_background (s, 0);
4299 x_draw_glyph_string_foreground (s);
4300 break;
4302 case COMPOSITE_GLYPH:
4303 if (s->for_overlaps_p || s->gidx > 0)
4304 s->background_filled_p = 1;
4305 else
4306 x_draw_glyph_string_background (s, 1);
4307 x_draw_composite_glyph_string_foreground (s);
4308 break;
4310 default:
4311 abort ();
4314 if (!s->for_overlaps_p)
4316 /* Draw underline. */
4317 if (s->face->underline_p)
4319 unsigned long tem, h;
4320 int y;
4322 /* Get the underline thickness. Default is 1 pixel. */
4323 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4324 h = 1;
4326 /* Get the underline position. This is the recommended
4327 vertical offset in pixels from the baseline to the top of
4328 the underline. This is a signed value according to the
4329 specs, and its default is
4331 ROUND ((maximum descent) / 2), with
4332 ROUND(x) = floor (x + 0.5) */
4334 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4335 y = s->ybase + (long) tem;
4336 else if (s->face->font)
4337 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4338 else
4339 y = s->height - h;
4341 if (s->face->underline_defaulted_p)
4342 XFillRectangle (s->display, s->window, s->gc,
4343 s->x, y, s->width, h);
4344 else
4346 XGCValues xgcv;
4347 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4348 XSetForeground (s->display, s->gc, s->face->underline_color);
4349 XFillRectangle (s->display, s->window, s->gc,
4350 s->x, y, s->width, h);
4351 XSetForeground (s->display, s->gc, xgcv.foreground);
4355 /* Draw overline. */
4356 if (s->face->overline_p)
4358 unsigned long dy = 0, h = 1;
4360 if (s->face->overline_color_defaulted_p)
4361 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4362 s->width, h);
4363 else
4365 XGCValues xgcv;
4366 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4367 XSetForeground (s->display, s->gc, s->face->overline_color);
4368 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4369 s->width, h);
4370 XSetForeground (s->display, s->gc, xgcv.foreground);
4374 /* Draw strike-through. */
4375 if (s->face->strike_through_p)
4377 unsigned long h = 1;
4378 unsigned long dy = (s->height - h) / 2;
4380 if (s->face->strike_through_color_defaulted_p)
4381 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4382 s->width, h);
4383 else
4385 XGCValues xgcv;
4386 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4387 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4388 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4389 s->width, h);
4390 XSetForeground (s->display, s->gc, xgcv.foreground);
4394 /* Draw relief if not yet drawn. */
4395 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4396 x_draw_glyph_string_box (s);
4399 /* Reset clipping. */
4400 XSetClipMask (s->display, s->gc, None);
4404 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4405 struct face **, int));
4408 /* Fill glyph string S with composition components specified by S->cmp.
4410 FACES is an array of faces for all components of this composition.
4411 S->gidx is the index of the first component for S.
4412 OVERLAPS_P non-zero means S should draw the foreground only, and
4413 use its physical height for clipping.
4415 Value is the index of a component not in S. */
4417 static int
4418 x_fill_composite_glyph_string (s, faces, overlaps_p)
4419 struct glyph_string *s;
4420 struct face **faces;
4421 int overlaps_p;
4423 int i;
4425 xassert (s);
4427 s->for_overlaps_p = overlaps_p;
4429 s->face = faces[s->gidx];
4430 s->font = s->face->font;
4431 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4433 /* For all glyphs of this composition, starting at the offset
4434 S->gidx, until we reach the end of the definition or encounter a
4435 glyph that requires the different face, add it to S. */
4436 ++s->nchars;
4437 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4438 ++s->nchars;
4440 /* All glyph strings for the same composition has the same width,
4441 i.e. the width set for the first component of the composition. */
4443 s->width = s->first_glyph->pixel_width;
4445 /* If the specified font could not be loaded, use the frame's
4446 default font, but record the fact that we couldn't load it in
4447 the glyph string so that we can draw rectangles for the
4448 characters of the glyph string. */
4449 if (s->font == NULL)
4451 s->font_not_found_p = 1;
4452 s->font = FRAME_FONT (s->f);
4455 /* Adjust base line for subscript/superscript text. */
4456 s->ybase += s->first_glyph->voffset;
4458 xassert (s->face && s->face->gc);
4460 /* This glyph string must always be drawn with 16-bit functions. */
4461 s->two_byte_p = 1;
4463 return s->gidx + s->nchars;
4467 /* Fill glyph string S from a sequence of character glyphs.
4469 FACE_ID is the face id of the string. START is the index of the
4470 first glyph to consider, END is the index of the last + 1.
4471 OVERLAPS_P non-zero means S should draw the foreground only, and
4472 use its physical height for clipping.
4474 Value is the index of the first glyph not in S. */
4476 static int
4477 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4478 struct glyph_string *s;
4479 int face_id;
4480 int start, end, overlaps_p;
4482 struct glyph *glyph, *last;
4483 int voffset;
4484 int glyph_not_available_p;
4486 xassert (s->f == XFRAME (s->w->frame));
4487 xassert (s->nchars == 0);
4488 xassert (start >= 0 && end > start);
4490 s->for_overlaps_p = overlaps_p,
4491 glyph = s->row->glyphs[s->area] + start;
4492 last = s->row->glyphs[s->area] + end;
4493 voffset = glyph->voffset;
4495 glyph_not_available_p = glyph->glyph_not_available_p;
4497 while (glyph < last
4498 && glyph->type == CHAR_GLYPH
4499 && glyph->voffset == voffset
4500 /* Same face id implies same font, nowadays. */
4501 && glyph->face_id == face_id
4502 && glyph->glyph_not_available_p == glyph_not_available_p)
4504 int two_byte_p;
4506 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4507 s->char2b + s->nchars,
4508 &two_byte_p);
4509 s->two_byte_p = two_byte_p;
4510 ++s->nchars;
4511 xassert (s->nchars <= end - start);
4512 s->width += glyph->pixel_width;
4513 ++glyph;
4516 s->font = s->face->font;
4517 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4519 /* If the specified font could not be loaded, use the frame's font,
4520 but record the fact that we couldn't load it in
4521 S->font_not_found_p so that we can draw rectangles for the
4522 characters of the glyph string. */
4523 if (s->font == NULL || glyph_not_available_p)
4525 s->font_not_found_p = 1;
4526 s->font = FRAME_FONT (s->f);
4529 /* Adjust base line for subscript/superscript text. */
4530 s->ybase += voffset;
4532 xassert (s->face && s->face->gc);
4533 return glyph - s->row->glyphs[s->area];
4537 /* Fill glyph string S from image glyph S->first_glyph. */
4539 static void
4540 x_fill_image_glyph_string (s)
4541 struct glyph_string *s;
4543 xassert (s->first_glyph->type == IMAGE_GLYPH);
4544 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4545 xassert (s->img);
4546 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4547 s->font = s->face->font;
4548 s->width = s->first_glyph->pixel_width;
4550 /* Adjust base line for subscript/superscript text. */
4551 s->ybase += s->first_glyph->voffset;
4555 /* Fill glyph string S from a sequence of stretch glyphs.
4557 ROW is the glyph row in which the glyphs are found, AREA is the
4558 area within the row. START is the index of the first glyph to
4559 consider, END is the index of the last + 1.
4561 Value is the index of the first glyph not in S. */
4563 static int
4564 x_fill_stretch_glyph_string (s, row, area, start, end)
4565 struct glyph_string *s;
4566 struct glyph_row *row;
4567 enum glyph_row_area area;
4568 int start, end;
4570 struct glyph *glyph, *last;
4571 int voffset, face_id;
4573 xassert (s->first_glyph->type == STRETCH_GLYPH);
4575 glyph = s->row->glyphs[s->area] + start;
4576 last = s->row->glyphs[s->area] + end;
4577 face_id = glyph->face_id;
4578 s->face = FACE_FROM_ID (s->f, face_id);
4579 s->font = s->face->font;
4580 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4581 s->width = glyph->pixel_width;
4582 voffset = glyph->voffset;
4584 for (++glyph;
4585 (glyph < last
4586 && glyph->type == STRETCH_GLYPH
4587 && glyph->voffset == voffset
4588 && glyph->face_id == face_id);
4589 ++glyph)
4590 s->width += glyph->pixel_width;
4592 /* Adjust base line for subscript/superscript text. */
4593 s->ybase += voffset;
4595 xassert (s->face && s->face->gc);
4596 return glyph - s->row->glyphs[s->area];
4600 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4601 of XChar2b structures for S; it can't be allocated in
4602 x_init_glyph_string because it must be allocated via `alloca'. W
4603 is the window on which S is drawn. ROW and AREA are the glyph row
4604 and area within the row from which S is constructed. START is the
4605 index of the first glyph structure covered by S. HL is a
4606 face-override for drawing S. */
4608 static void
4609 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4610 struct glyph_string *s;
4611 XChar2b *char2b;
4612 struct window *w;
4613 struct glyph_row *row;
4614 enum glyph_row_area area;
4615 int start;
4616 enum draw_glyphs_face hl;
4618 bzero (s, sizeof *s);
4619 s->w = w;
4620 s->f = XFRAME (w->frame);
4621 s->display = FRAME_X_DISPLAY (s->f);
4622 s->window = FRAME_X_WINDOW (s->f);
4623 s->char2b = char2b;
4624 s->hl = hl;
4625 s->row = row;
4626 s->area = area;
4627 s->first_glyph = row->glyphs[area] + start;
4628 s->height = row->height;
4629 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4631 /* Display the internal border below the tool-bar window. */
4632 if (s->w == XWINDOW (s->f->tool_bar_window))
4633 s->y -= s->f->output_data.x->internal_border_width;
4635 s->ybase = s->y + row->ascent;
4639 /* Set background width of glyph string S. START is the index of the
4640 first glyph following S. LAST_X is the right-most x-position + 1
4641 in the drawing area. */
4643 static INLINE void
4644 x_set_glyph_string_background_width (s, start, last_x)
4645 struct glyph_string *s;
4646 int start;
4647 int last_x;
4649 /* If the face of this glyph string has to be drawn to the end of
4650 the drawing area, set S->extends_to_end_of_line_p. */
4651 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4653 if (start == s->row->used[s->area]
4654 && s->hl == DRAW_NORMAL_TEXT
4655 && s->area == TEXT_AREA
4656 && (s->row->fill_line_p
4657 || s->face->background != default_face->background
4658 || s->face->stipple != default_face->stipple))
4659 s->extends_to_end_of_line_p = 1;
4661 /* If S extends its face to the end of the line, set its
4662 background_width to the distance to the right edge of the drawing
4663 area. */
4664 if (s->extends_to_end_of_line_p)
4665 s->background_width = last_x - s->x + 1;
4666 else
4667 s->background_width = s->width;
4671 /* Add a glyph string for a stretch glyph to the list of strings
4672 between HEAD and TAIL. START is the index of the stretch glyph in
4673 row area AREA of glyph row ROW. END is the index of the last glyph
4674 in that glyph row area. X is the current output position assigned
4675 to the new glyph string constructed. HL overrides that face of the
4676 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4677 is the right-most x-position of the drawing area. */
4679 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4680 and below -- keep them on one line. */
4681 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4682 do \
4684 s = (struct glyph_string *) alloca (sizeof *s); \
4685 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4686 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4687 x_append_glyph_string (&HEAD, &TAIL, s); \
4688 s->x = (X); \
4690 while (0)
4693 /* Add a glyph string for an image glyph to the list of strings
4694 between HEAD and TAIL. START is the index of the image glyph in
4695 row area AREA of glyph row ROW. END is the index of the last glyph
4696 in that glyph row area. X is the current output position assigned
4697 to the new glyph string constructed. HL overrides that face of the
4698 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4699 is the right-most x-position of the drawing area. */
4701 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4702 do \
4704 s = (struct glyph_string *) alloca (sizeof *s); \
4705 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4706 x_fill_image_glyph_string (s); \
4707 x_append_glyph_string (&HEAD, &TAIL, s); \
4708 ++START; \
4709 s->x = (X); \
4711 while (0)
4714 /* Add a glyph string for a sequence of character glyphs to the list
4715 of strings between HEAD and TAIL. START is the index of the first
4716 glyph in row area AREA of glyph row ROW that is part of the new
4717 glyph string. END is the index of the last glyph in that glyph row
4718 area. X is the current output position assigned to the new glyph
4719 string constructed. HL overrides that face of the glyph; e.g. it
4720 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4721 right-most x-position of the drawing area. */
4723 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4724 do \
4726 int c, face_id; \
4727 XChar2b *char2b; \
4729 c = (ROW)->glyphs[AREA][START].u.ch; \
4730 face_id = (ROW)->glyphs[AREA][START].face_id; \
4732 s = (struct glyph_string *) alloca (sizeof *s); \
4733 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4734 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4735 x_append_glyph_string (&HEAD, &TAIL, s); \
4736 s->x = (X); \
4737 START = x_fill_glyph_string (s, face_id, START, END, \
4738 OVERLAPS_P); \
4740 while (0)
4743 /* Add a glyph string for a composite sequence to the list of strings
4744 between HEAD and TAIL. START is the index of the first glyph in
4745 row area AREA of glyph row ROW that is part of the new glyph
4746 string. END is the index of the last glyph in that glyph row area.
4747 X is the current output position assigned to the new glyph string
4748 constructed. HL overrides that face of the glyph; e.g. it is
4749 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4750 x-position of the drawing area. */
4752 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4753 do { \
4754 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4755 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4756 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4757 struct composition *cmp = composition_table[cmp_id]; \
4758 int glyph_len = cmp->glyph_len; \
4759 XChar2b *char2b; \
4760 struct face **faces; \
4761 struct glyph_string *first_s = NULL; \
4762 int n; \
4764 base_face = base_face->ascii_face; \
4765 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4766 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4767 /* At first, fill in `char2b' and `faces'. */ \
4768 for (n = 0; n < glyph_len; n++) \
4770 int c = COMPOSITION_GLYPH (cmp, n); \
4771 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4772 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4773 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4774 this_face_id, char2b + n, 1); \
4777 /* Make glyph_strings for each glyph sequence that is drawable by \
4778 the same face, and append them to HEAD/TAIL. */ \
4779 for (n = 0; n < cmp->glyph_len;) \
4781 s = (struct glyph_string *) alloca (sizeof *s); \
4782 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4783 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4784 s->cmp = cmp; \
4785 s->gidx = n; \
4786 s->x = (X); \
4788 if (n == 0) \
4789 first_s = s; \
4791 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4794 ++START; \
4795 s = first_s; \
4796 } while (0)
4799 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4800 of AREA of glyph row ROW on window W between indices START and END.
4801 HL overrides the face for drawing glyph strings, e.g. it is
4802 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4803 x-positions of the drawing area.
4805 This is an ugly monster macro construct because we must use alloca
4806 to allocate glyph strings (because x_draw_glyphs can be called
4807 asynchronously). */
4809 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4810 do \
4812 HEAD = TAIL = NULL; \
4813 while (START < END) \
4815 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4816 switch (first_glyph->type) \
4818 case CHAR_GLYPH: \
4819 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4820 TAIL, HL, X, LAST_X, \
4821 OVERLAPS_P); \
4822 break; \
4824 case COMPOSITE_GLYPH: \
4825 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4826 HEAD, TAIL, HL, X, LAST_X,\
4827 OVERLAPS_P); \
4828 break; \
4830 case STRETCH_GLYPH: \
4831 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4832 HEAD, TAIL, HL, X, LAST_X); \
4833 break; \
4835 case IMAGE_GLYPH: \
4836 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4837 TAIL, HL, X, LAST_X); \
4838 break; \
4840 default: \
4841 abort (); \
4844 x_set_glyph_string_background_width (s, START, LAST_X); \
4845 (X) += s->width; \
4848 while (0)
4851 /* Draw glyphs between START and END in AREA of ROW on window W,
4852 starting at x-position X. X is relative to AREA in W. HL is a
4853 face-override with the following meaning:
4855 DRAW_NORMAL_TEXT draw normally
4856 DRAW_CURSOR draw in cursor face
4857 DRAW_MOUSE_FACE draw in mouse face.
4858 DRAW_INVERSE_VIDEO draw in mode line face
4859 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4860 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4862 If REAL_START is non-null, return in *REAL_START the real starting
4863 position for display. This can be different from START in case
4864 overlapping glyphs must be displayed. If REAL_END is non-null,
4865 return in *REAL_END the real end position for display. This can be
4866 different from END in case overlapping glyphs must be displayed.
4868 If OVERLAPS_P is non-zero, draw only the foreground of characters
4869 and clip to the physical height of ROW.
4871 Value is the x-position reached, relative to AREA of W. */
4873 static int
4874 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4875 overlaps_p)
4876 struct window *w;
4877 int x;
4878 struct glyph_row *row;
4879 enum glyph_row_area area;
4880 int start, end;
4881 enum draw_glyphs_face hl;
4882 int *real_start, *real_end;
4883 int overlaps_p;
4885 struct glyph_string *head, *tail;
4886 struct glyph_string *s;
4887 int last_x, area_width;
4888 int x_reached;
4889 int i, j;
4891 /* Let's rather be paranoid than getting a SEGV. */
4892 end = min (end, row->used[area]);
4893 start = max (0, start);
4894 start = min (end, start);
4895 if (real_start)
4896 *real_start = start;
4897 if (real_end)
4898 *real_end = end;
4900 /* Translate X to frame coordinates. Set last_x to the right
4901 end of the drawing area. */
4902 if (row->full_width_p)
4904 /* X is relative to the left edge of W, without scroll bars
4905 or flag areas. */
4906 struct frame *f = XFRAME (w->frame);
4907 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4908 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4910 x += window_left_x;
4911 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4912 last_x = window_left_x + area_width;
4914 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4916 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4917 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4918 last_x += width;
4919 else
4920 x -= width;
4923 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4924 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4926 else
4928 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4929 area_width = window_box_width (w, area);
4930 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4933 /* Build a doubly-linked list of glyph_string structures between
4934 head and tail from what we have to draw. Note that the macro
4935 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4936 the reason we use a separate variable `i'. */
4937 i = start;
4938 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4939 overlaps_p);
4940 if (tail)
4941 x_reached = tail->x + tail->background_width;
4942 else
4943 x_reached = x;
4945 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4946 the row, redraw some glyphs in front or following the glyph
4947 strings built above. */
4948 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4950 int dummy_x = 0;
4951 struct glyph_string *h, *t;
4953 /* Compute overhangs for all glyph strings. */
4954 for (s = head; s; s = s->next)
4955 x_compute_glyph_string_overhangs (s);
4957 /* Prepend glyph strings for glyphs in front of the first glyph
4958 string that are overwritten because of the first glyph
4959 string's left overhang. The background of all strings
4960 prepended must be drawn because the first glyph string
4961 draws over it. */
4962 i = x_left_overwritten (head);
4963 if (i >= 0)
4965 j = i;
4966 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4967 DRAW_NORMAL_TEXT, dummy_x, last_x,
4968 overlaps_p);
4969 start = i;
4970 if (real_start)
4971 *real_start = start;
4972 x_compute_overhangs_and_x (t, head->x, 1);
4973 x_prepend_glyph_string_lists (&head, &tail, h, t);
4976 /* Prepend glyph strings for glyphs in front of the first glyph
4977 string that overwrite that glyph string because of their
4978 right overhang. For these strings, only the foreground must
4979 be drawn, because it draws over the glyph string at `head'.
4980 The background must not be drawn because this would overwrite
4981 right overhangs of preceding glyphs for which no glyph
4982 strings exist. */
4983 i = x_left_overwriting (head);
4984 if (i >= 0)
4986 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4987 DRAW_NORMAL_TEXT, dummy_x, last_x,
4988 overlaps_p);
4989 for (s = h; s; s = s->next)
4990 s->background_filled_p = 1;
4991 if (real_start)
4992 *real_start = i;
4993 x_compute_overhangs_and_x (t, head->x, 1);
4994 x_prepend_glyph_string_lists (&head, &tail, h, t);
4997 /* Append glyphs strings for glyphs following the last glyph
4998 string tail that are overwritten by tail. The background of
4999 these strings has to be drawn because tail's foreground draws
5000 over it. */
5001 i = x_right_overwritten (tail);
5002 if (i >= 0)
5004 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5005 DRAW_NORMAL_TEXT, x, last_x,
5006 overlaps_p);
5007 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5008 x_append_glyph_string_lists (&head, &tail, h, t);
5009 if (real_end)
5010 *real_end = i;
5013 /* Append glyph strings for glyphs following the last glyph
5014 string tail that overwrite tail. The foreground of such
5015 glyphs has to be drawn because it writes into the background
5016 of tail. The background must not be drawn because it could
5017 paint over the foreground of following glyphs. */
5018 i = x_right_overwriting (tail);
5019 if (i >= 0)
5021 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5022 DRAW_NORMAL_TEXT, x, last_x,
5023 overlaps_p);
5024 for (s = h; s; s = s->next)
5025 s->background_filled_p = 1;
5026 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5027 x_append_glyph_string_lists (&head, &tail, h, t);
5028 if (real_end)
5029 *real_end = i;
5033 /* Draw all strings. */
5034 for (s = head; s; s = s->next)
5035 x_draw_glyph_string (s);
5037 /* Value is the x-position up to which drawn, relative to AREA of W.
5038 This doesn't include parts drawn because of overhangs. */
5039 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5040 if (!row->full_width_p)
5042 if (area > LEFT_MARGIN_AREA)
5043 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5044 if (area > TEXT_AREA)
5045 x_reached -= window_box_width (w, TEXT_AREA);
5048 return x_reached;
5052 /* Fix the display of area AREA of overlapping row ROW in window W. */
5054 static void
5055 x_fix_overlapping_area (w, row, area)
5056 struct window *w;
5057 struct glyph_row *row;
5058 enum glyph_row_area area;
5060 int i, x;
5062 BLOCK_INPUT;
5064 if (area == LEFT_MARGIN_AREA)
5065 x = 0;
5066 else if (area == TEXT_AREA)
5067 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5068 else
5069 x = (window_box_width (w, LEFT_MARGIN_AREA)
5070 + window_box_width (w, TEXT_AREA));
5072 for (i = 0; i < row->used[area];)
5074 if (row->glyphs[area][i].overlaps_vertically_p)
5076 int start = i, start_x = x;
5080 x += row->glyphs[area][i].pixel_width;
5081 ++i;
5083 while (i < row->used[area]
5084 && row->glyphs[area][i].overlaps_vertically_p);
5086 x_draw_glyphs (w, start_x, row, area, start, i,
5087 (row->inverse_p
5088 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5089 NULL, NULL, 1);
5091 else
5093 x += row->glyphs[area][i].pixel_width;
5094 ++i;
5098 UNBLOCK_INPUT;
5102 /* Output LEN glyphs starting at START at the nominal cursor position.
5103 Advance the nominal cursor over the text. The global variable
5104 updated_window contains the window being updated, updated_row is
5105 the glyph row being updated, and updated_area is the area of that
5106 row being updated. */
5108 static void
5109 x_write_glyphs (start, len)
5110 struct glyph *start;
5111 int len;
5113 int x, hpos, real_start, real_end;
5115 xassert (updated_window && updated_row);
5116 BLOCK_INPUT;
5118 /* Write glyphs. */
5120 hpos = start - updated_row->glyphs[updated_area];
5121 x = x_draw_glyphs (updated_window, output_cursor.x,
5122 updated_row, updated_area,
5123 hpos, hpos + len,
5124 (updated_row->inverse_p
5125 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5126 &real_start, &real_end, 0);
5128 /* If we drew over the cursor, note that it is not visible any more. */
5129 note_overwritten_text_cursor (updated_window, real_start,
5130 real_end - real_start);
5132 UNBLOCK_INPUT;
5134 /* Advance the output cursor. */
5135 output_cursor.hpos += len;
5136 output_cursor.x = x;
5140 /* Insert LEN glyphs from START at the nominal cursor position. */
5142 static void
5143 x_insert_glyphs (start, len)
5144 struct glyph *start;
5145 register int len;
5147 struct frame *f;
5148 struct window *w;
5149 int line_height, shift_by_width, shifted_region_width;
5150 struct glyph_row *row;
5151 struct glyph *glyph;
5152 int frame_x, frame_y, hpos, real_start, real_end;
5154 xassert (updated_window && updated_row);
5155 BLOCK_INPUT;
5156 w = updated_window;
5157 f = XFRAME (WINDOW_FRAME (w));
5159 /* Get the height of the line we are in. */
5160 row = updated_row;
5161 line_height = row->height;
5163 /* Get the width of the glyphs to insert. */
5164 shift_by_width = 0;
5165 for (glyph = start; glyph < start + len; ++glyph)
5166 shift_by_width += glyph->pixel_width;
5168 /* Get the width of the region to shift right. */
5169 shifted_region_width = (window_box_width (w, updated_area)
5170 - output_cursor.x
5171 - shift_by_width);
5173 /* Shift right. */
5174 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5175 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5176 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5177 f->output_data.x->normal_gc,
5178 frame_x, frame_y,
5179 shifted_region_width, line_height,
5180 frame_x + shift_by_width, frame_y);
5182 /* Write the glyphs. */
5183 hpos = start - row->glyphs[updated_area];
5184 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5185 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5186 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5188 /* Advance the output cursor. */
5189 output_cursor.hpos += len;
5190 output_cursor.x += shift_by_width;
5191 UNBLOCK_INPUT;
5195 /* Delete N glyphs at the nominal cursor position. Not implemented
5196 for X frames. */
5198 static void
5199 x_delete_glyphs (n)
5200 register int n;
5202 abort ();
5206 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5207 If they are <= 0, this is probably an error. */
5209 void
5210 x_clear_area (dpy, window, x, y, width, height, exposures)
5211 Display *dpy;
5212 Window window;
5213 int x, y;
5214 int width, height;
5215 int exposures;
5217 xassert (width > 0 && height > 0);
5218 XClearArea (dpy, window, x, y, width, height, exposures);
5222 /* Erase the current text line from the nominal cursor position
5223 (inclusive) to pixel column TO_X (exclusive). The idea is that
5224 everything from TO_X onward is already erased.
5226 TO_X is a pixel position relative to updated_area of
5227 updated_window. TO_X == -1 means clear to the end of this area. */
5229 static void
5230 x_clear_end_of_line (to_x)
5231 int to_x;
5233 struct frame *f;
5234 struct window *w = updated_window;
5235 int max_x, min_y, max_y;
5236 int from_x, from_y, to_y;
5238 xassert (updated_window && updated_row);
5239 f = XFRAME (w->frame);
5241 if (updated_row->full_width_p)
5243 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5244 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5245 && !w->pseudo_window_p)
5246 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5248 else
5249 max_x = window_box_width (w, updated_area);
5250 max_y = window_text_bottom_y (w);
5252 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5253 of window. For TO_X > 0, truncate to end of drawing area. */
5254 if (to_x == 0)
5255 return;
5256 else if (to_x < 0)
5257 to_x = max_x;
5258 else
5259 to_x = min (to_x, max_x);
5261 to_y = min (max_y, output_cursor.y + updated_row->height);
5263 /* Notice if the cursor will be cleared by this operation. */
5264 if (!updated_row->full_width_p)
5265 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5267 from_x = output_cursor.x;
5269 /* Translate to frame coordinates. */
5270 if (updated_row->full_width_p)
5272 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5273 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5275 else
5277 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5278 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5281 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5282 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5283 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5285 /* Prevent inadvertently clearing to end of the X window. */
5286 if (to_x > from_x && to_y > from_y)
5288 BLOCK_INPUT;
5289 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5290 from_x, from_y, to_x - from_x, to_y - from_y,
5291 False);
5292 UNBLOCK_INPUT;
5297 /* Clear entire frame. If updating_frame is non-null, clear that
5298 frame. Otherwise clear the selected frame. */
5300 static void
5301 x_clear_frame ()
5303 struct frame *f;
5305 if (updating_frame)
5306 f = updating_frame;
5307 else
5308 f = SELECTED_FRAME ();
5310 /* Clearing the frame will erase any cursor, so mark them all as no
5311 longer visible. */
5312 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5313 output_cursor.hpos = output_cursor.vpos = 0;
5314 output_cursor.x = -1;
5316 /* We don't set the output cursor here because there will always
5317 follow an explicit cursor_to. */
5318 BLOCK_INPUT;
5319 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5321 /* We have to clear the scroll bars, too. If we have changed
5322 colors or something like that, then they should be notified. */
5323 x_scroll_bar_clear (f);
5325 XFlush (FRAME_X_DISPLAY (f));
5326 UNBLOCK_INPUT;
5331 /* Invert the middle quarter of the frame for .15 sec. */
5333 /* We use the select system call to do the waiting, so we have to make
5334 sure it's available. If it isn't, we just won't do visual bells. */
5336 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5339 /* Subtract the `struct timeval' values X and Y, storing the result in
5340 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5342 static int
5343 timeval_subtract (result, x, y)
5344 struct timeval *result, x, y;
5346 /* Perform the carry for the later subtraction by updating y. This
5347 is safer because on some systems the tv_sec member is unsigned. */
5348 if (x.tv_usec < y.tv_usec)
5350 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5351 y.tv_usec -= 1000000 * nsec;
5352 y.tv_sec += nsec;
5355 if (x.tv_usec - y.tv_usec > 1000000)
5357 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5358 y.tv_usec += 1000000 * nsec;
5359 y.tv_sec -= nsec;
5362 /* Compute the time remaining to wait. tv_usec is certainly
5363 positive. */
5364 result->tv_sec = x.tv_sec - y.tv_sec;
5365 result->tv_usec = x.tv_usec - y.tv_usec;
5367 /* Return indication of whether the result should be considered
5368 negative. */
5369 return x.tv_sec < y.tv_sec;
5372 void
5373 XTflash (f)
5374 struct frame *f;
5376 BLOCK_INPUT;
5379 GC gc;
5381 /* Create a GC that will use the GXxor function to flip foreground
5382 pixels into background pixels. */
5384 XGCValues values;
5386 values.function = GXxor;
5387 values.foreground = (f->output_data.x->foreground_pixel
5388 ^ f->output_data.x->background_pixel);
5390 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5391 GCFunction | GCForeground, &values);
5395 /* Get the height not including a menu bar widget. */
5396 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5397 /* Height of each line to flash. */
5398 int flash_height = FRAME_LINE_HEIGHT (f);
5399 /* These will be the left and right margins of the rectangles. */
5400 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5401 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5403 int width;
5405 /* Don't flash the area between a scroll bar and the frame
5406 edge it is next to. */
5407 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5409 case vertical_scroll_bar_left:
5410 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5411 break;
5413 case vertical_scroll_bar_right:
5414 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5415 break;
5417 default:
5418 break;
5421 width = flash_right - flash_left;
5423 /* If window is tall, flash top and bottom line. */
5424 if (height > 3 * FRAME_LINE_HEIGHT (f))
5426 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5427 flash_left,
5428 (FRAME_INTERNAL_BORDER_WIDTH (f)
5429 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5430 width, flash_height);
5431 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5432 flash_left,
5433 (height - flash_height
5434 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5435 width, flash_height);
5437 else
5438 /* If it is short, flash it all. */
5439 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5440 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5441 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5443 x_flush (f);
5446 struct timeval wakeup;
5448 EMACS_GET_TIME (wakeup);
5450 /* Compute time to wait until, propagating carry from usecs. */
5451 wakeup.tv_usec += 150000;
5452 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5453 wakeup.tv_usec %= 1000000;
5455 /* Keep waiting until past the time wakeup or any input gets
5456 available. */
5457 while (! detect_input_pending ())
5459 struct timeval current;
5460 struct timeval timeout;
5462 EMACS_GET_TIME (current);
5464 /* Break if result would be negative. */
5465 if (timeval_subtract (&current, wakeup, current))
5466 break;
5468 /* How long `select' should wait. */
5469 timeout.tv_sec = 0;
5470 timeout.tv_usec = 10000;
5472 /* Try to wait that long--but we might wake up sooner. */
5473 select (0, NULL, NULL, NULL, &timeout);
5477 /* If window is tall, flash top and bottom line. */
5478 if (height > 3 * FRAME_LINE_HEIGHT (f))
5480 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5481 flash_left,
5482 (FRAME_INTERNAL_BORDER_WIDTH (f)
5483 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5484 width, flash_height);
5485 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5486 flash_left,
5487 (height - flash_height
5488 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5489 width, flash_height);
5491 else
5492 /* If it is short, flash it all. */
5493 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5494 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5495 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5497 XFreeGC (FRAME_X_DISPLAY (f), gc);
5498 x_flush (f);
5502 UNBLOCK_INPUT;
5505 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5508 /* Make audible bell. */
5510 void
5511 XTring_bell ()
5513 struct frame *f = SELECTED_FRAME ();
5515 if (FRAME_X_DISPLAY (f))
5517 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5518 if (visible_bell)
5519 XTflash (f);
5520 else
5521 #endif
5523 BLOCK_INPUT;
5524 XBell (FRAME_X_DISPLAY (f), 0);
5525 XFlush (FRAME_X_DISPLAY (f));
5526 UNBLOCK_INPUT;
5532 /* Specify how many text lines, from the top of the window,
5533 should be affected by insert-lines and delete-lines operations.
5534 This, and those operations, are used only within an update
5535 that is bounded by calls to x_update_begin and x_update_end. */
5537 static void
5538 XTset_terminal_window (n)
5539 register int n;
5541 /* This function intentionally left blank. */
5546 /***********************************************************************
5547 Line Dance
5548 ***********************************************************************/
5550 /* Perform an insert-lines or delete-lines operation, inserting N
5551 lines or deleting -N lines at vertical position VPOS. */
5553 static void
5554 x_ins_del_lines (vpos, n)
5555 int vpos, n;
5557 abort ();
5561 /* Scroll part of the display as described by RUN. */
5563 static void
5564 x_scroll_run (w, run)
5565 struct window *w;
5566 struct run *run;
5568 struct frame *f = XFRAME (w->frame);
5569 int x, y, width, height, from_y, to_y, bottom_y;
5571 /* Get frame-relative bounding box of the text display area of W,
5572 without mode lines. Include in this box the flags areas to the
5573 left and right of W. */
5574 window_box (w, -1, &x, &y, &width, &height);
5575 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5576 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5578 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5579 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5580 bottom_y = y + height;
5582 if (to_y < from_y)
5584 /* Scrolling up. Make sure we don't copy part of the mode
5585 line at the bottom. */
5586 if (from_y + run->height > bottom_y)
5587 height = bottom_y - from_y;
5588 else
5589 height = run->height;
5591 else
5593 /* Scolling down. Make sure we don't copy over the mode line.
5594 at the bottom. */
5595 if (to_y + run->height > bottom_y)
5596 height = bottom_y - to_y;
5597 else
5598 height = run->height;
5601 BLOCK_INPUT;
5603 /* Cursor off. Will be switched on again in x_update_window_end. */
5604 updated_window = w;
5605 x_clear_cursor (w);
5607 XCopyArea (FRAME_X_DISPLAY (f),
5608 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5609 f->output_data.x->normal_gc,
5610 x, from_y,
5611 width, height,
5612 x, to_y);
5614 UNBLOCK_INPUT;
5619 /***********************************************************************
5620 Exposure Events
5621 ***********************************************************************/
5623 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5624 corner of the exposed rectangle. W and H are width and height of
5625 the exposed area. All are pixel values. W or H zero means redraw
5626 the entire frame. */
5628 static void
5629 expose_frame (f, x, y, w, h)
5630 struct frame *f;
5631 int x, y, w, h;
5633 XRectangle r;
5635 TRACE ((stderr, "expose_frame "));
5637 /* No need to redraw if frame will be redrawn soon. */
5638 if (FRAME_GARBAGED_P (f))
5640 TRACE ((stderr, " garbaged\n"));
5641 return;
5644 /* If basic faces haven't been realized yet, there is no point in
5645 trying to redraw anything. This can happen when we get an expose
5646 event while Emacs is starting, e.g. by moving another window. */
5647 if (FRAME_FACE_CACHE (f) == NULL
5648 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5650 TRACE ((stderr, " no faces\n"));
5651 return;
5654 if (w == 0 || h == 0)
5656 r.x = r.y = 0;
5657 r.width = CANON_X_UNIT (f) * f->width;
5658 r.height = CANON_Y_UNIT (f) * f->height;
5660 else
5662 r.x = x;
5663 r.y = y;
5664 r.width = w;
5665 r.height = h;
5668 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5669 expose_window_tree (XWINDOW (f->root_window), &r);
5671 if (WINDOWP (f->tool_bar_window))
5673 struct window *w = XWINDOW (f->tool_bar_window);
5674 XRectangle window_rect;
5675 XRectangle intersection_rect;
5676 int window_x, window_y, window_width, window_height;
5679 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5680 window_rect.x = window_x;
5681 window_rect.y = window_y;
5682 window_rect.width = window_width;
5683 window_rect.height = window_height;
5685 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5686 expose_window (w, &intersection_rect);
5689 #ifndef USE_X_TOOLKIT
5690 if (WINDOWP (f->menu_bar_window))
5692 struct window *w = XWINDOW (f->menu_bar_window);
5693 XRectangle window_rect;
5694 XRectangle intersection_rect;
5695 int window_x, window_y, window_width, window_height;
5698 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5699 window_rect.x = window_x;
5700 window_rect.y = window_y;
5701 window_rect.width = window_width;
5702 window_rect.height = window_height;
5704 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5705 expose_window (w, &intersection_rect);
5707 #endif /* not USE_X_TOOLKIT */
5711 /* Redraw (parts) of all windows in the window tree rooted at W that
5712 intersect R. R contains frame pixel coordinates. */
5714 static void
5715 expose_window_tree (w, r)
5716 struct window *w;
5717 XRectangle *r;
5719 while (w)
5721 if (!NILP (w->hchild))
5722 expose_window_tree (XWINDOW (w->hchild), r);
5723 else if (!NILP (w->vchild))
5724 expose_window_tree (XWINDOW (w->vchild), r);
5725 else
5727 XRectangle window_rect;
5728 XRectangle intersection_rect;
5729 struct frame *f = XFRAME (w->frame);
5730 int window_x, window_y, window_width, window_height;
5732 /* Frame-relative pixel rectangle of W. */
5733 window_box (w, -1, &window_x, &window_y, &window_width,
5734 &window_height);
5735 window_rect.x
5736 = (window_x
5737 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5738 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5739 window_rect.y = window_y;
5740 window_rect.width
5741 = (window_width
5742 + FRAME_X_FLAGS_AREA_WIDTH (f)
5743 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5744 window_rect.height
5745 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5747 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5748 expose_window (w, &intersection_rect);
5751 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5756 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5757 which intersects rectangle R. R is in window-relative coordinates. */
5759 static void
5760 expose_area (w, row, r, area)
5761 struct window *w;
5762 struct glyph_row *row;
5763 XRectangle *r;
5764 enum glyph_row_area area;
5766 struct glyph *first = row->glyphs[area];
5767 struct glyph *end = row->glyphs[area] + row->used[area];
5768 struct glyph *last;
5769 int first_x, start_x, x;
5771 if (area == TEXT_AREA && row->fill_line_p)
5772 /* If row extends face to end of line write the whole line. */
5773 x_draw_glyphs (w, 0, row, area,
5774 0, row->used[area],
5775 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5776 NULL, NULL, 0);
5777 else
5779 /* Set START_X to the window-relative start position for drawing glyphs of
5780 AREA. The first glyph of the text area can be partially visible.
5781 The first glyphs of other areas cannot. */
5782 if (area == LEFT_MARGIN_AREA)
5783 start_x = 0;
5784 else if (area == TEXT_AREA)
5785 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5786 else
5787 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5788 + window_box_width (w, TEXT_AREA));
5789 x = start_x;
5791 /* Find the first glyph that must be redrawn. */
5792 while (first < end
5793 && x + first->pixel_width < r->x)
5795 x += first->pixel_width;
5796 ++first;
5799 /* Find the last one. */
5800 last = first;
5801 first_x = x;
5802 while (last < end
5803 && x < r->x + r->width)
5805 x += last->pixel_width;
5806 ++last;
5809 /* Repaint. */
5810 if (last > first)
5811 x_draw_glyphs (w, first_x - start_x, row, area,
5812 first - row->glyphs[area],
5813 last - row->glyphs[area],
5814 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5815 NULL, NULL, 0);
5820 /* Redraw the parts of the glyph row ROW on window W intersecting
5821 rectangle R. R is in window-relative coordinates. */
5823 static void
5824 expose_line (w, row, r)
5825 struct window *w;
5826 struct glyph_row *row;
5827 XRectangle *r;
5829 xassert (row->enabled_p);
5831 if (row->mode_line_p || w->pseudo_window_p)
5832 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5833 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5834 NULL, NULL, 0);
5835 else
5837 if (row->used[LEFT_MARGIN_AREA])
5838 expose_area (w, row, r, LEFT_MARGIN_AREA);
5839 if (row->used[TEXT_AREA])
5840 expose_area (w, row, r, TEXT_AREA);
5841 if (row->used[RIGHT_MARGIN_AREA])
5842 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5843 x_draw_row_bitmaps (w, row);
5848 /* Return non-zero if W's cursor intersects rectangle R. */
5850 static int
5851 x_phys_cursor_in_rect_p (w, r)
5852 struct window *w;
5853 XRectangle *r;
5855 XRectangle cr, result;
5856 struct glyph *cursor_glyph;
5858 cursor_glyph = get_phys_cursor_glyph (w);
5859 if (cursor_glyph)
5861 cr.x = w->phys_cursor.x;
5862 cr.y = w->phys_cursor.y;
5863 cr.width = cursor_glyph->pixel_width;
5864 cr.height = w->phys_cursor_height;
5865 return x_intersect_rectangles (&cr, r, &result);
5867 else
5868 return 0;
5872 /* Redraw a rectangle of window W. R is a rectangle in window
5873 relative coordinates. Call this function with input blocked. */
5875 static void
5876 expose_window (w, r)
5877 struct window *w;
5878 XRectangle *r;
5880 struct glyph_row *row;
5881 int y;
5882 int yb = window_text_bottom_y (w);
5883 int cursor_cleared_p;
5885 /* If window is not yet fully initialized, do nothing. This can
5886 happen when toolkit scroll bars are used and a window is split.
5887 Reconfiguring the scroll bar will generate an expose for a newly
5888 created window. */
5889 if (w->current_matrix == NULL || w == updated_window)
5890 return;
5892 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5893 r->x, r->y, r->width, r->height));
5895 /* Convert to window coordinates. */
5896 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5897 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5899 /* Turn off the cursor. */
5900 if (!w->pseudo_window_p
5901 && x_phys_cursor_in_rect_p (w, r))
5903 x_clear_cursor (w);
5904 cursor_cleared_p = 1;
5906 else
5907 cursor_cleared_p = 0;
5909 /* Find the first row intersecting the rectangle R. */
5910 row = w->current_matrix->rows;
5911 y = 0;
5912 while (row->enabled_p
5913 && y < yb
5914 && y + row->height < r->y)
5916 y += row->height;
5917 ++row;
5920 /* Display the text in the rectangle, one text line at a time. */
5921 while (row->enabled_p
5922 && y < yb
5923 && y < r->y + r->height)
5925 expose_line (w, row, r);
5926 y += row->height;
5927 ++row;
5930 /* Display the mode line if there is one. */
5931 if (WINDOW_WANTS_MODELINE_P (w)
5932 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5933 row->enabled_p)
5934 && row->y < r->y + r->height)
5935 expose_line (w, row, r);
5937 if (!w->pseudo_window_p)
5939 /* Draw border between windows. */
5940 x_draw_vertical_border (w);
5942 /* Turn the cursor on again. */
5943 if (cursor_cleared_p)
5944 x_update_window_cursor (w, 1);
5949 /* Determine the intersection of two rectangles R1 and R2. Return
5950 the intersection in *RESULT. Value is non-zero if RESULT is not
5951 empty. */
5953 static int
5954 x_intersect_rectangles (r1, r2, result)
5955 XRectangle *r1, *r2, *result;
5957 XRectangle *left, *right;
5958 XRectangle *upper, *lower;
5959 int intersection_p = 0;
5961 /* Rearrange so that R1 is the left-most rectangle. */
5962 if (r1->x < r2->x)
5963 left = r1, right = r2;
5964 else
5965 left = r2, right = r1;
5967 /* X0 of the intersection is right.x0, if this is inside R1,
5968 otherwise there is no intersection. */
5969 if (right->x <= left->x + left->width)
5971 result->x = right->x;
5973 /* The right end of the intersection is the minimum of the
5974 the right ends of left and right. */
5975 result->width = (min (left->x + left->width, right->x + right->width)
5976 - result->x);
5978 /* Same game for Y. */
5979 if (r1->y < r2->y)
5980 upper = r1, lower = r2;
5981 else
5982 upper = r2, lower = r1;
5984 /* The upper end of the intersection is lower.y0, if this is inside
5985 of upper. Otherwise, there is no intersection. */
5986 if (lower->y <= upper->y + upper->height)
5988 result->y = lower->y;
5990 /* The lower end of the intersection is the minimum of the lower
5991 ends of upper and lower. */
5992 result->height = (min (lower->y + lower->height,
5993 upper->y + upper->height)
5994 - result->y);
5995 intersection_p = 1;
5999 return intersection_p;
6006 static void
6007 frame_highlight (f)
6008 struct frame *f;
6010 /* We used to only do this if Vx_no_window_manager was non-nil, but
6011 the ICCCM (section 4.1.6) says that the window's border pixmap
6012 and border pixel are window attributes which are "private to the
6013 client", so we can always change it to whatever we want. */
6014 BLOCK_INPUT;
6015 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6016 f->output_data.x->border_pixel);
6017 UNBLOCK_INPUT;
6018 x_update_cursor (f, 1);
6021 static void
6022 frame_unhighlight (f)
6023 struct frame *f;
6025 /* We used to only do this if Vx_no_window_manager was non-nil, but
6026 the ICCCM (section 4.1.6) says that the window's border pixmap
6027 and border pixel are window attributes which are "private to the
6028 client", so we can always change it to whatever we want. */
6029 BLOCK_INPUT;
6030 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6031 f->output_data.x->border_tile);
6032 UNBLOCK_INPUT;
6033 x_update_cursor (f, 1);
6036 /* The focus has changed. Update the frames as necessary to reflect
6037 the new situation. Note that we can't change the selected frame
6038 here, because the Lisp code we are interrupting might become confused.
6039 Each event gets marked with the frame in which it occurred, so the
6040 Lisp code can tell when the switch took place by examining the events. */
6042 static void
6043 x_new_focus_frame (dpyinfo, frame)
6044 struct x_display_info *dpyinfo;
6045 struct frame *frame;
6047 struct frame *old_focus = dpyinfo->x_focus_frame;
6049 if (frame != dpyinfo->x_focus_frame)
6051 /* Set this before calling other routines, so that they see
6052 the correct value of x_focus_frame. */
6053 dpyinfo->x_focus_frame = frame;
6055 if (old_focus && old_focus->auto_lower)
6056 x_lower_frame (old_focus);
6058 #if 0
6059 selected_frame = frame;
6060 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6061 selected_frame);
6062 Fselect_window (selected_frame->selected_window);
6063 choose_minibuf_frame ();
6064 #endif /* ! 0 */
6066 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6067 pending_autoraise_frame = dpyinfo->x_focus_frame;
6068 else
6069 pending_autoraise_frame = 0;
6072 x_frame_rehighlight (dpyinfo);
6075 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6077 void
6078 x_mouse_leave (dpyinfo)
6079 struct x_display_info *dpyinfo;
6081 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6084 /* The focus has changed, or we have redirected a frame's focus to
6085 another frame (this happens when a frame uses a surrogate
6086 mini-buffer frame). Shift the highlight as appropriate.
6088 The FRAME argument doesn't necessarily have anything to do with which
6089 frame is being highlighted or un-highlighted; we only use it to find
6090 the appropriate X display info. */
6092 static void
6093 XTframe_rehighlight (frame)
6094 struct frame *frame;
6096 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6099 static void
6100 x_frame_rehighlight (dpyinfo)
6101 struct x_display_info *dpyinfo;
6103 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6105 if (dpyinfo->x_focus_frame)
6107 dpyinfo->x_highlight_frame
6108 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6109 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6110 : dpyinfo->x_focus_frame);
6111 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6113 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6114 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6117 else
6118 dpyinfo->x_highlight_frame = 0;
6120 if (dpyinfo->x_highlight_frame != old_highlight)
6122 if (old_highlight)
6123 frame_unhighlight (old_highlight);
6124 if (dpyinfo->x_highlight_frame)
6125 frame_highlight (dpyinfo->x_highlight_frame);
6131 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6133 /* Initialize mode_switch_bit and modifier_meaning. */
6134 static void
6135 x_find_modifier_meanings (dpyinfo)
6136 struct x_display_info *dpyinfo;
6138 int min_code, max_code;
6139 KeySym *syms;
6140 int syms_per_code;
6141 XModifierKeymap *mods;
6143 dpyinfo->meta_mod_mask = 0;
6144 dpyinfo->shift_lock_mask = 0;
6145 dpyinfo->alt_mod_mask = 0;
6146 dpyinfo->super_mod_mask = 0;
6147 dpyinfo->hyper_mod_mask = 0;
6149 #ifdef HAVE_X11R4
6150 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6151 #else
6152 min_code = dpyinfo->display->min_keycode;
6153 max_code = dpyinfo->display->max_keycode;
6154 #endif
6156 syms = XGetKeyboardMapping (dpyinfo->display,
6157 min_code, max_code - min_code + 1,
6158 &syms_per_code);
6159 mods = XGetModifierMapping (dpyinfo->display);
6161 /* Scan the modifier table to see which modifier bits the Meta and
6162 Alt keysyms are on. */
6164 int row, col; /* The row and column in the modifier table. */
6166 for (row = 3; row < 8; row++)
6167 for (col = 0; col < mods->max_keypermod; col++)
6169 KeyCode code
6170 = mods->modifiermap[(row * mods->max_keypermod) + col];
6172 /* Zeroes are used for filler. Skip them. */
6173 if (code == 0)
6174 continue;
6176 /* Are any of this keycode's keysyms a meta key? */
6178 int code_col;
6180 for (code_col = 0; code_col < syms_per_code; code_col++)
6182 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6184 switch (sym)
6186 case XK_Meta_L:
6187 case XK_Meta_R:
6188 dpyinfo->meta_mod_mask |= (1 << row);
6189 break;
6191 case XK_Alt_L:
6192 case XK_Alt_R:
6193 dpyinfo->alt_mod_mask |= (1 << row);
6194 break;
6196 case XK_Hyper_L:
6197 case XK_Hyper_R:
6198 dpyinfo->hyper_mod_mask |= (1 << row);
6199 break;
6201 case XK_Super_L:
6202 case XK_Super_R:
6203 dpyinfo->super_mod_mask |= (1 << row);
6204 break;
6206 case XK_Shift_Lock:
6207 /* Ignore this if it's not on the lock modifier. */
6208 if ((1 << row) == LockMask)
6209 dpyinfo->shift_lock_mask = LockMask;
6210 break;
6217 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6218 if (! dpyinfo->meta_mod_mask)
6220 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6221 dpyinfo->alt_mod_mask = 0;
6224 /* If some keys are both alt and meta,
6225 make them just meta, not alt. */
6226 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6228 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6231 XFree ((char *) syms);
6232 XFreeModifiermap (mods);
6235 /* Convert between the modifier bits X uses and the modifier bits
6236 Emacs uses. */
6238 static unsigned int
6239 x_x_to_emacs_modifiers (dpyinfo, state)
6240 struct x_display_info *dpyinfo;
6241 unsigned int state;
6243 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6244 | ((state & ControlMask) ? ctrl_modifier : 0)
6245 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6246 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6247 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6248 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6251 static unsigned int
6252 x_emacs_to_x_modifiers (dpyinfo, state)
6253 struct x_display_info *dpyinfo;
6254 unsigned int state;
6256 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6257 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6258 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6259 | ((state & shift_modifier) ? ShiftMask : 0)
6260 | ((state & ctrl_modifier) ? ControlMask : 0)
6261 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6264 /* Convert a keysym to its name. */
6266 char *
6267 x_get_keysym_name (keysym)
6268 KeySym keysym;
6270 char *value;
6272 BLOCK_INPUT;
6273 value = XKeysymToString (keysym);
6274 UNBLOCK_INPUT;
6276 return value;
6281 /* Mouse clicks and mouse movement. Rah. */
6283 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6284 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6285 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6286 not force the value into range. */
6288 void
6289 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6290 FRAME_PTR f;
6291 register int pix_x, pix_y;
6292 register int *x, *y;
6293 XRectangle *bounds;
6294 int noclip;
6296 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6297 even for negative values. */
6298 if (pix_x < 0)
6299 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6300 if (pix_y < 0)
6301 pix_y -= (f)->output_data.x->line_height - 1;
6303 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6304 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6306 if (bounds)
6308 bounds->width = FONT_WIDTH (f->output_data.x->font);
6309 bounds->height = f->output_data.x->line_height;
6310 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6311 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6314 if (!noclip)
6316 if (pix_x < 0)
6317 pix_x = 0;
6318 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6319 pix_x = FRAME_WINDOW_WIDTH (f);
6321 if (pix_y < 0)
6322 pix_y = 0;
6323 else if (pix_y > f->height)
6324 pix_y = f->height;
6327 *x = pix_x;
6328 *y = pix_y;
6332 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6333 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6334 can't tell the positions because W's display is not up to date,
6335 return 0. */
6338 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6339 struct window *w;
6340 int hpos, vpos;
6341 int *frame_x, *frame_y;
6343 int success_p;
6345 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6346 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6348 if (display_completed)
6350 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6351 struct glyph *glyph = row->glyphs[TEXT_AREA];
6352 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6354 *frame_y = row->y;
6355 *frame_x = row->x;
6356 while (glyph < end)
6358 *frame_x += glyph->pixel_width;
6359 ++glyph;
6362 success_p = 1;
6364 else
6366 *frame_y = *frame_x = 0;
6367 success_p = 0;
6370 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6371 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6372 return success_p;
6376 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6378 If the event is a button press, then note that we have grabbed
6379 the mouse. */
6381 static Lisp_Object
6382 construct_mouse_click (result, event, f)
6383 struct input_event *result;
6384 XButtonEvent *event;
6385 struct frame *f;
6387 /* Make the event type no_event; we'll change that when we decide
6388 otherwise. */
6389 result->kind = mouse_click;
6390 result->code = event->button - Button1;
6391 result->timestamp = event->time;
6392 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6393 event->state)
6394 | (event->type == ButtonRelease
6395 ? up_modifier
6396 : down_modifier));
6398 XSETINT (result->x, event->x);
6399 XSETINT (result->y, event->y);
6400 XSETFRAME (result->frame_or_window, f);
6401 result->arg = Qnil;
6402 return Qnil;
6406 /* Function to report a mouse movement to the mainstream Emacs code.
6407 The input handler calls this.
6409 We have received a mouse movement event, which is given in *event.
6410 If the mouse is over a different glyph than it was last time, tell
6411 the mainstream emacs code by setting mouse_moved. If not, ask for
6412 another motion event, so we can check again the next time it moves. */
6414 static XMotionEvent last_mouse_motion_event;
6415 static Lisp_Object last_mouse_motion_frame;
6417 static void
6418 note_mouse_movement (frame, event)
6419 FRAME_PTR frame;
6420 XMotionEvent *event;
6422 last_mouse_movement_time = event->time;
6423 last_mouse_motion_event = *event;
6424 XSETFRAME (last_mouse_motion_frame, frame);
6426 if (event->window != FRAME_X_WINDOW (frame))
6428 frame->mouse_moved = 1;
6429 last_mouse_scroll_bar = Qnil;
6430 note_mouse_highlight (frame, -1, -1);
6433 /* Has the mouse moved off the glyph it was on at the last sighting? */
6434 else if (event->x < last_mouse_glyph.x
6435 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6436 || event->y < last_mouse_glyph.y
6437 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6439 frame->mouse_moved = 1;
6440 last_mouse_scroll_bar = Qnil;
6441 note_mouse_highlight (frame, event->x, event->y);
6445 /* This is used for debugging, to turn off note_mouse_highlight. */
6447 int disable_mouse_highlight;
6451 /************************************************************************
6452 Mouse Face
6453 ************************************************************************/
6455 /* Find the glyph under window-relative coordinates X/Y in window W.
6456 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6457 strings. Return in *HPOS and *VPOS the row and column number of
6458 the glyph found. Return in *AREA the glyph area containing X.
6459 Value is a pointer to the glyph found or null if X/Y is not on
6460 text, or we can't tell because W's current matrix is not up to
6461 date. */
6463 static struct glyph *
6464 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6465 struct window *w;
6466 int x, y;
6467 int *hpos, *vpos, *area;
6468 int buffer_only_p;
6470 struct glyph *glyph, *end;
6471 struct glyph_row *row = NULL;
6472 int x0, i, left_area_width;
6474 /* Find row containing Y. Give up if some row is not enabled. */
6475 for (i = 0; i < w->current_matrix->nrows; ++i)
6477 row = MATRIX_ROW (w->current_matrix, i);
6478 if (!row->enabled_p)
6479 return NULL;
6480 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6481 break;
6484 *vpos = i;
6485 *hpos = 0;
6487 /* Give up if Y is not in the window. */
6488 if (i == w->current_matrix->nrows)
6489 return NULL;
6491 /* Get the glyph area containing X. */
6492 if (w->pseudo_window_p)
6494 *area = TEXT_AREA;
6495 x0 = 0;
6497 else
6499 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6500 if (x < left_area_width)
6502 *area = LEFT_MARGIN_AREA;
6503 x0 = 0;
6505 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6507 *area = TEXT_AREA;
6508 x0 = row->x + left_area_width;
6510 else
6512 *area = RIGHT_MARGIN_AREA;
6513 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6517 /* Find glyph containing X. */
6518 glyph = row->glyphs[*area];
6519 end = glyph + row->used[*area];
6520 while (glyph < end)
6522 if (x < x0 + glyph->pixel_width)
6524 if (w->pseudo_window_p)
6525 break;
6526 else if (!buffer_only_p || BUFFERP (glyph->object))
6527 break;
6530 x0 += glyph->pixel_width;
6531 ++glyph;
6534 if (glyph == end)
6535 return NULL;
6537 *hpos = glyph - row->glyphs[*area];
6538 return glyph;
6542 /* Convert frame-relative x/y to coordinates relative to window W.
6543 Takes pseudo-windows into account. */
6545 static void
6546 frame_to_window_pixel_xy (w, x, y)
6547 struct window *w;
6548 int *x, *y;
6550 if (w->pseudo_window_p)
6552 /* A pseudo-window is always full-width, and starts at the
6553 left edge of the frame, plus a frame border. */
6554 struct frame *f = XFRAME (w->frame);
6555 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6556 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6558 else
6560 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6561 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6566 /* Take proper action when mouse has moved to the mode or header line of
6567 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6568 mode line. X is relative to the start of the text display area of
6569 W, so the width of bitmap areas and scroll bars must be subtracted
6570 to get a position relative to the start of the mode line. */
6572 static void
6573 note_mode_line_highlight (w, x, mode_line_p)
6574 struct window *w;
6575 int x, mode_line_p;
6577 struct frame *f = XFRAME (w->frame);
6578 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6579 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6580 struct glyph_row *row;
6582 if (mode_line_p)
6583 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6584 else
6585 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6587 if (row->enabled_p)
6589 struct glyph *glyph, *end;
6590 Lisp_Object help, map;
6591 int x0;
6593 /* Find the glyph under X. */
6594 glyph = row->glyphs[TEXT_AREA];
6595 end = glyph + row->used[TEXT_AREA];
6596 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6597 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6599 while (glyph < end
6600 && x >= x0 + glyph->pixel_width)
6602 x0 += glyph->pixel_width;
6603 ++glyph;
6606 if (glyph < end
6607 && STRINGP (glyph->object)
6608 && XSTRING (glyph->object)->intervals
6609 && glyph->charpos >= 0
6610 && glyph->charpos < XSTRING (glyph->object)->size)
6612 /* If we're on a string with `help-echo' text property,
6613 arrange for the help to be displayed. This is done by
6614 setting the global variable help_echo to the help string. */
6615 help = Fget_text_property (make_number (glyph->charpos),
6616 Qhelp_echo, glyph->object);
6617 if (!NILP (help))
6619 help_echo = help;
6620 XSETWINDOW (help_echo_window, w);
6621 help_echo_object = glyph->object;
6622 help_echo_pos = glyph->charpos;
6625 /* Change the mouse pointer according to what is under X/Y. */
6626 map = Fget_text_property (make_number (glyph->charpos),
6627 Qlocal_map, glyph->object);
6628 if (KEYMAPP (map))
6629 cursor = f->output_data.x->nontext_cursor;
6630 else
6632 map = Fget_text_property (make_number (glyph->charpos),
6633 Qkeymap, glyph->object);
6634 if (KEYMAPP (map))
6635 cursor = f->output_data.x->nontext_cursor;
6640 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6644 /* Take proper action when the mouse has moved to position X, Y on
6645 frame F as regards highlighting characters that have mouse-face
6646 properties. Also de-highlighting chars where the mouse was before.
6647 X and Y can be negative or out of range. */
6649 static void
6650 note_mouse_highlight (f, x, y)
6651 struct frame *f;
6652 int x, y;
6654 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6655 int portion;
6656 Lisp_Object window;
6657 struct window *w;
6659 /* When a menu is active, don't highlight because this looks odd. */
6660 #ifdef USE_X_TOOLKIT
6661 if (popup_activated ())
6662 return;
6663 #endif
6665 if (disable_mouse_highlight
6666 || !f->glyphs_initialized_p)
6667 return;
6669 dpyinfo->mouse_face_mouse_x = x;
6670 dpyinfo->mouse_face_mouse_y = y;
6671 dpyinfo->mouse_face_mouse_frame = f;
6673 if (dpyinfo->mouse_face_defer)
6674 return;
6676 if (gc_in_progress)
6678 dpyinfo->mouse_face_deferred_gc = 1;
6679 return;
6682 /* Which window is that in? */
6683 window = window_from_coordinates (f, x, y, &portion, 1);
6685 /* If we were displaying active text in another window, clear that. */
6686 if (! EQ (window, dpyinfo->mouse_face_window))
6687 clear_mouse_face (dpyinfo);
6689 /* Not on a window -> return. */
6690 if (!WINDOWP (window))
6691 return;
6693 /* Convert to window-relative pixel coordinates. */
6694 w = XWINDOW (window);
6695 frame_to_window_pixel_xy (w, &x, &y);
6697 /* Handle tool-bar window differently since it doesn't display a
6698 buffer. */
6699 if (EQ (window, f->tool_bar_window))
6701 note_tool_bar_highlight (f, x, y);
6702 return;
6705 if (portion == 1 || portion == 3)
6707 /* Mouse is on the mode or top line. */
6708 note_mode_line_highlight (w, x, portion == 1);
6709 return;
6711 else if (portion == 2)
6712 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6713 f->output_data.x->horizontal_drag_cursor);
6714 else
6715 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6716 f->output_data.x->text_cursor);
6718 /* Are we in a window whose display is up to date?
6719 And verify the buffer's text has not changed. */
6720 if (/* Within text portion of the window. */
6721 portion == 0
6722 && EQ (w->window_end_valid, w->buffer)
6723 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6724 && (XFASTINT (w->last_overlay_modified)
6725 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6727 int hpos, vpos, pos, i, area;
6728 struct glyph *glyph;
6729 Lisp_Object object;
6731 /* Find the glyph under X/Y. */
6732 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6734 /* Clear mouse face if X/Y not over text. */
6735 if (glyph == NULL
6736 || area != TEXT_AREA
6737 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6739 clear_mouse_face (dpyinfo);
6740 return;
6743 pos = glyph->charpos;
6744 object = glyph->object;
6745 if (!STRINGP (object) && !BUFFERP (object))
6746 return;
6749 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6750 Lisp_Object *overlay_vec = NULL;
6751 int len, noverlays;
6752 struct buffer *obuf;
6753 int obegv, ozv;
6755 /* If we get an out-of-range value, return now; avoid an error. */
6756 if (BUFFERP (object) && pos > BUF_Z (XBUFFER (w->buffer)))
6757 return;
6759 /* Make the window's buffer temporarily current for
6760 overlays_at and compute_char_face. */
6761 obuf = current_buffer;
6762 current_buffer = XBUFFER (w->buffer);
6763 obegv = BEGV;
6764 ozv = ZV;
6765 BEGV = BEG;
6766 ZV = Z;
6768 /* Is this char mouse-active or does it have help-echo? */
6769 position = make_number (pos);
6771 if (BUFFERP (object))
6773 /* Put all the overlays we want in a vector in overlay_vec.
6774 Store the length in len. If there are more than 10, make
6775 enough space for all, and try again. */
6776 len = 10;
6777 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6778 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6779 if (noverlays > len)
6781 len = noverlays;
6782 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6783 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6786 /* Sort overlays into increasing priority order. */
6787 noverlays = sort_overlays (overlay_vec, noverlays, w);
6789 else
6790 noverlays = 0;
6792 /* Check mouse-face highlighting. */
6793 if (! (EQ (window, dpyinfo->mouse_face_window)
6794 && vpos >= dpyinfo->mouse_face_beg_row
6795 && vpos <= dpyinfo->mouse_face_end_row
6796 && (vpos > dpyinfo->mouse_face_beg_row
6797 || hpos >= dpyinfo->mouse_face_beg_col)
6798 && (vpos < dpyinfo->mouse_face_end_row
6799 || hpos < dpyinfo->mouse_face_end_col
6800 || dpyinfo->mouse_face_past_end))
6801 /* If there exists an overlay with mouse-face overlapping
6802 the one we are currently highlighting, we have to
6803 check if we enter the overlapping overlay, and then
6804 highlight only that. */
6805 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6806 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6809 /* Clear the display of the old active region, if any. */
6810 clear_mouse_face (dpyinfo);
6812 /* Find the highest priority overlay that has a mouse-face
6813 property. */
6814 overlay = Qnil;
6815 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6817 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6818 if (!NILP (mouse_face))
6819 overlay = overlay_vec[i];
6821 dpyinfo->mouse_face_overlay = overlay;
6823 /* If no overlay applies, get a text property. */
6824 if (NILP (overlay))
6825 mouse_face = Fget_text_property (position, Qmouse_face, object);
6827 /* Handle the overlay case. */
6828 if (!NILP (overlay))
6830 /* Find the range of text around this char that
6831 should be active. */
6832 Lisp_Object before, after;
6833 int ignore;
6835 before = Foverlay_start (overlay);
6836 after = Foverlay_end (overlay);
6837 /* Record this as the current active region. */
6838 fast_find_position (w, XFASTINT (before),
6839 &dpyinfo->mouse_face_beg_col,
6840 &dpyinfo->mouse_face_beg_row,
6841 &dpyinfo->mouse_face_beg_x,
6842 &dpyinfo->mouse_face_beg_y);
6843 dpyinfo->mouse_face_past_end
6844 = !fast_find_position (w, XFASTINT (after),
6845 &dpyinfo->mouse_face_end_col,
6846 &dpyinfo->mouse_face_end_row,
6847 &dpyinfo->mouse_face_end_x,
6848 &dpyinfo->mouse_face_end_y);
6849 dpyinfo->mouse_face_window = window;
6850 dpyinfo->mouse_face_face_id
6851 = face_at_buffer_position (w, pos, 0, 0,
6852 &ignore, pos + 1, 1);
6854 /* Display it as active. */
6855 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6857 /* Handle the text property case. */
6858 else if (!NILP (mouse_face) && BUFFERP (object))
6860 /* Find the range of text around this char that
6861 should be active. */
6862 Lisp_Object before, after, beginning, end;
6863 int ignore;
6865 beginning = Fmarker_position (w->start);
6866 end = make_number (BUF_Z (XBUFFER (object))
6867 - XFASTINT (w->window_end_pos));
6868 before
6869 = Fprevious_single_property_change (make_number (pos + 1),
6870 Qmouse_face,
6871 object, beginning);
6872 after
6873 = Fnext_single_property_change (position, Qmouse_face,
6874 object, end);
6876 /* Record this as the current active region. */
6877 fast_find_position (w, XFASTINT (before),
6878 &dpyinfo->mouse_face_beg_col,
6879 &dpyinfo->mouse_face_beg_row,
6880 &dpyinfo->mouse_face_beg_x,
6881 &dpyinfo->mouse_face_beg_y);
6882 dpyinfo->mouse_face_past_end
6883 = !fast_find_position (w, XFASTINT (after),
6884 &dpyinfo->mouse_face_end_col,
6885 &dpyinfo->mouse_face_end_row,
6886 &dpyinfo->mouse_face_end_x,
6887 &dpyinfo->mouse_face_end_y);
6888 dpyinfo->mouse_face_window = window;
6890 if (BUFFERP (object))
6891 dpyinfo->mouse_face_face_id
6892 = face_at_buffer_position (w, pos, 0, 0,
6893 &ignore, pos + 1, 1);
6895 /* Display it as active. */
6896 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6898 else if (!NILP (mouse_face) && STRINGP (object))
6900 Lisp_Object b, e;
6901 int ignore;
6903 b = Fprevious_single_property_change (make_number (pos + 1),
6904 Qmouse_face,
6905 object, Qnil);
6906 e = Fnext_single_property_change (position, Qmouse_face,
6907 object, Qnil);
6908 if (NILP (b))
6909 b = make_number (0);
6910 if (NILP (e))
6911 e = make_number (XSTRING (object)->size - 1);
6912 fast_find_string_pos (w, XINT (b), object,
6913 &dpyinfo->mouse_face_beg_col,
6914 &dpyinfo->mouse_face_beg_row,
6915 &dpyinfo->mouse_face_beg_x,
6916 &dpyinfo->mouse_face_beg_y, 0);
6917 fast_find_string_pos (w, XINT (e), object,
6918 &dpyinfo->mouse_face_end_col,
6919 &dpyinfo->mouse_face_end_row,
6920 &dpyinfo->mouse_face_end_x,
6921 &dpyinfo->mouse_face_end_y, 1);
6922 dpyinfo->mouse_face_past_end = 0;
6923 dpyinfo->mouse_face_window = window;
6924 dpyinfo->mouse_face_face_id
6925 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6926 glyph->face_id, 1);
6927 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6931 /* Look for a `help-echo' property. */
6933 Lisp_Object help, overlay;
6935 /* Check overlays first. */
6936 help = overlay = Qnil;
6937 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6939 overlay = overlay_vec[i];
6940 help = Foverlay_get (overlay, Qhelp_echo);
6943 if (!NILP (help))
6945 help_echo = help;
6946 help_echo_window = window;
6947 help_echo_object = overlay;
6948 help_echo_pos = pos;
6950 else
6952 Lisp_Object object = glyph->object;
6953 int charpos = glyph->charpos;
6955 /* Try text properties. */
6956 if (STRINGP (object)
6957 && charpos >= 0
6958 && charpos < XSTRING (object)->size)
6960 help = Fget_text_property (make_number (charpos),
6961 Qhelp_echo, object);
6962 if (NILP (help))
6964 /* If the string itself doesn't specify a help-echo,
6965 see if the buffer text ``under'' it does. */
6966 struct glyph_row *r
6967 = MATRIX_ROW (w->current_matrix, vpos);
6968 int start = MATRIX_ROW_START_CHARPOS (r);
6969 int pos = string_buffer_position (w, object, start);
6970 if (pos > 0)
6972 help = Fget_text_property (make_number (pos),
6973 Qhelp_echo, w->buffer);
6974 if (!NILP (help))
6976 charpos = pos;
6977 object = w->buffer;
6982 else if (BUFFERP (object)
6983 && charpos >= BEGV
6984 && charpos < ZV)
6985 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6986 object);
6988 if (!NILP (help))
6990 help_echo = help;
6991 help_echo_window = window;
6992 help_echo_object = object;
6993 help_echo_pos = charpos;
6998 BEGV = obegv;
6999 ZV = ozv;
7000 current_buffer = obuf;
7005 static void
7006 redo_mouse_highlight ()
7008 if (!NILP (last_mouse_motion_frame)
7009 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7010 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7011 last_mouse_motion_event.x,
7012 last_mouse_motion_event.y);
7017 /***********************************************************************
7018 Tool-bars
7019 ***********************************************************************/
7021 static int x_tool_bar_item P_ ((struct frame *, int, int,
7022 struct glyph **, int *, int *, int *));
7024 /* Tool-bar item index of the item on which a mouse button was pressed
7025 or -1. */
7027 static int last_tool_bar_item;
7030 /* Get information about the tool-bar item at position X/Y on frame F.
7031 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7032 the current matrix of the tool-bar window of F, or NULL if not
7033 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7034 item in F->tool_bar_items. Value is
7036 -1 if X/Y is not on a tool-bar item
7037 0 if X/Y is on the same item that was highlighted before.
7038 1 otherwise. */
7040 static int
7041 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7042 struct frame *f;
7043 int x, y;
7044 struct glyph **glyph;
7045 int *hpos, *vpos, *prop_idx;
7047 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7048 struct window *w = XWINDOW (f->tool_bar_window);
7049 int area;
7051 /* Find the glyph under X/Y. */
7052 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7053 if (*glyph == NULL)
7054 return -1;
7056 /* Get the start of this tool-bar item's properties in
7057 f->tool_bar_items. */
7058 if (!tool_bar_item_info (f, *glyph, prop_idx))
7059 return -1;
7061 /* Is mouse on the highlighted item? */
7062 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7063 && *vpos >= dpyinfo->mouse_face_beg_row
7064 && *vpos <= dpyinfo->mouse_face_end_row
7065 && (*vpos > dpyinfo->mouse_face_beg_row
7066 || *hpos >= dpyinfo->mouse_face_beg_col)
7067 && (*vpos < dpyinfo->mouse_face_end_row
7068 || *hpos < dpyinfo->mouse_face_end_col
7069 || dpyinfo->mouse_face_past_end))
7070 return 0;
7072 return 1;
7076 /* Handle mouse button event on the tool-bar of frame F, at
7077 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7078 or ButtonRelase. */
7080 static void
7081 x_handle_tool_bar_click (f, button_event)
7082 struct frame *f;
7083 XButtonEvent *button_event;
7085 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7086 struct window *w = XWINDOW (f->tool_bar_window);
7087 int hpos, vpos, prop_idx;
7088 struct glyph *glyph;
7089 Lisp_Object enabled_p;
7090 int x = button_event->x;
7091 int y = button_event->y;
7093 /* If not on the highlighted tool-bar item, return. */
7094 frame_to_window_pixel_xy (w, &x, &y);
7095 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7096 return;
7098 /* If item is disabled, do nothing. */
7099 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7100 if (NILP (enabled_p))
7101 return;
7103 if (button_event->type == ButtonPress)
7105 /* Show item in pressed state. */
7106 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7107 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7108 last_tool_bar_item = prop_idx;
7110 else
7112 Lisp_Object key, frame;
7113 struct input_event event;
7115 /* Show item in released state. */
7116 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7117 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7119 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7121 XSETFRAME (frame, f);
7122 event.kind = TOOL_BAR_EVENT;
7123 event.frame_or_window = frame;
7124 event.arg = frame;
7125 kbd_buffer_store_event (&event);
7127 event.kind = TOOL_BAR_EVENT;
7128 event.frame_or_window = frame;
7129 event.arg = key;
7130 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7131 button_event->state);
7132 kbd_buffer_store_event (&event);
7133 last_tool_bar_item = -1;
7138 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7139 tool-bar window-relative coordinates X/Y. Called from
7140 note_mouse_highlight. */
7142 static void
7143 note_tool_bar_highlight (f, x, y)
7144 struct frame *f;
7145 int x, y;
7147 Lisp_Object window = f->tool_bar_window;
7148 struct window *w = XWINDOW (window);
7149 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7150 int hpos, vpos;
7151 struct glyph *glyph;
7152 struct glyph_row *row;
7153 int i;
7154 Lisp_Object enabled_p;
7155 int prop_idx;
7156 enum draw_glyphs_face draw;
7157 int mouse_down_p, rc;
7159 /* Function note_mouse_highlight is called with negative x(y
7160 values when mouse moves outside of the frame. */
7161 if (x <= 0 || y <= 0)
7163 clear_mouse_face (dpyinfo);
7164 return;
7167 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7168 if (rc < 0)
7170 /* Not on tool-bar item. */
7171 clear_mouse_face (dpyinfo);
7172 return;
7174 else if (rc == 0)
7175 goto set_help_echo;
7177 clear_mouse_face (dpyinfo);
7179 /* Mouse is down, but on different tool-bar item? */
7180 mouse_down_p = (dpyinfo->grabbed
7181 && f == last_mouse_frame
7182 && FRAME_LIVE_P (f));
7183 if (mouse_down_p
7184 && last_tool_bar_item != prop_idx)
7185 return;
7187 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7188 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7190 /* If tool-bar item is not enabled, don't highlight it. */
7191 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7192 if (!NILP (enabled_p))
7194 /* Compute the x-position of the glyph. In front and past the
7195 image is a space. We include this is the highlighted area. */
7196 row = MATRIX_ROW (w->current_matrix, vpos);
7197 for (i = x = 0; i < hpos; ++i)
7198 x += row->glyphs[TEXT_AREA][i].pixel_width;
7200 /* Record this as the current active region. */
7201 dpyinfo->mouse_face_beg_col = hpos;
7202 dpyinfo->mouse_face_beg_row = vpos;
7203 dpyinfo->mouse_face_beg_x = x;
7204 dpyinfo->mouse_face_beg_y = row->y;
7205 dpyinfo->mouse_face_past_end = 0;
7207 dpyinfo->mouse_face_end_col = hpos + 1;
7208 dpyinfo->mouse_face_end_row = vpos;
7209 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7210 dpyinfo->mouse_face_end_y = row->y;
7211 dpyinfo->mouse_face_window = window;
7212 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7214 /* Display it as active. */
7215 show_mouse_face (dpyinfo, draw);
7216 dpyinfo->mouse_face_image_state = draw;
7219 set_help_echo:
7221 /* Set help_echo to a help string.to display for this tool-bar item.
7222 XTread_socket does the rest. */
7223 help_echo_object = help_echo_window = Qnil;
7224 help_echo_pos = -1;
7225 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7226 if (NILP (help_echo))
7227 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7232 /* Find the glyph matrix position of buffer position POS in window W.
7233 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7234 current glyphs must be up to date. If POS is above window start
7235 return (0, 0, 0, 0). If POS is after end of W, return end of
7236 last line in W. */
7238 static int
7239 fast_find_position (w, pos, hpos, vpos, x, y)
7240 struct window *w;
7241 int pos;
7242 int *hpos, *vpos, *x, *y;
7244 int i;
7245 int lastcol;
7246 int maybe_next_line_p = 0;
7247 int line_start_position;
7248 int yb = window_text_bottom_y (w);
7249 struct glyph_row *row, *best_row;
7250 int row_vpos, best_row_vpos;
7251 int current_x;
7253 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7254 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7256 while (row->y < yb)
7258 if (row->used[TEXT_AREA])
7259 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7260 else
7261 line_start_position = 0;
7263 if (line_start_position > pos)
7264 break;
7265 /* If the position sought is the end of the buffer,
7266 don't include the blank lines at the bottom of the window. */
7267 else if (line_start_position == pos
7268 && pos == BUF_ZV (XBUFFER (w->buffer)))
7270 maybe_next_line_p = 1;
7271 break;
7273 else if (line_start_position > 0)
7275 best_row = row;
7276 best_row_vpos = row_vpos;
7279 if (row->y + row->height >= yb)
7280 break;
7282 ++row;
7283 ++row_vpos;
7286 /* Find the right column within BEST_ROW. */
7287 lastcol = 0;
7288 current_x = best_row->x;
7289 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7291 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7292 int charpos;
7294 charpos = glyph->charpos;
7295 if (charpos == pos)
7297 *hpos = i;
7298 *vpos = best_row_vpos;
7299 *x = current_x;
7300 *y = best_row->y;
7301 return 1;
7303 else if (charpos > pos)
7304 break;
7305 else if (charpos > 0)
7306 lastcol = i;
7308 current_x += glyph->pixel_width;
7311 /* If we're looking for the end of the buffer,
7312 and we didn't find it in the line we scanned,
7313 use the start of the following line. */
7314 if (maybe_next_line_p)
7316 ++best_row;
7317 ++best_row_vpos;
7318 lastcol = 0;
7319 current_x = best_row->x;
7322 *vpos = best_row_vpos;
7323 *hpos = lastcol + 1;
7324 *x = current_x;
7325 *y = best_row->y;
7326 return 0;
7330 /* Find the position of the the glyph for position POS in OBJECT in
7331 window W's current matrix, and return in *X/*Y the pixel
7332 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7334 RIGHT_P non-zero means return the position of the right edge of the
7335 glyph, RIGHT_P zero means return the left edge position.
7337 If no glyph for POS exists in the matrix, return the position of
7338 the glyph with the next smaller position that is in the matrix, if
7339 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7340 exists in the matrix, return the position of the glyph with the
7341 next larger position in OBJECT.
7343 Value is non-zero if a glyph was found. */
7345 static int
7346 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7347 struct window *w;
7348 int pos;
7349 Lisp_Object object;
7350 int *hpos, *vpos, *x, *y;
7351 int right_p;
7353 int yb = window_text_bottom_y (w);
7354 struct glyph_row *r;
7355 struct glyph *best_glyph = NULL;
7356 struct glyph_row *best_row = NULL;
7357 int best_x = 0;
7359 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7360 r->enabled_p && r->y < yb;
7361 ++r)
7363 struct glyph *g = r->glyphs[TEXT_AREA];
7364 struct glyph *e = g + r->used[TEXT_AREA];
7365 int gx;
7367 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7368 if (EQ (g->object, object))
7370 if (g->charpos == pos)
7372 best_glyph = g;
7373 best_x = gx;
7374 best_row = r;
7375 goto found;
7377 else if (best_glyph == NULL
7378 || ((abs (g->charpos - pos)
7379 < abs (best_glyph->charpos - pos))
7380 && (right_p
7381 ? g->charpos < pos
7382 : g->charpos > pos)))
7384 best_glyph = g;
7385 best_x = gx;
7386 best_row = r;
7391 found:
7393 if (best_glyph)
7395 *x = best_x;
7396 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7398 if (right_p)
7400 *x += best_glyph->pixel_width;
7401 ++*hpos;
7404 *y = best_row->y;
7405 *vpos = best_row - w->current_matrix->rows;
7408 return best_glyph != NULL;
7412 /* Display the active region described by mouse_face_*
7413 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7415 static void
7416 show_mouse_face (dpyinfo, draw)
7417 struct x_display_info *dpyinfo;
7418 enum draw_glyphs_face draw;
7420 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7421 struct frame *f = XFRAME (WINDOW_FRAME (w));
7422 int i;
7423 int cursor_off_p = 0;
7424 struct cursor_pos saved_cursor;
7426 saved_cursor = output_cursor;
7428 /* If window is in the process of being destroyed, don't bother
7429 to do anything. */
7430 if (w->current_matrix == NULL)
7431 goto set_x_cursor;
7433 /* Recognize when we are called to operate on rows that don't exist
7434 anymore. This can happen when a window is split. */
7435 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7436 goto set_x_cursor;
7438 set_output_cursor (&w->phys_cursor);
7440 /* Note that mouse_face_beg_row etc. are window relative. */
7441 for (i = dpyinfo->mouse_face_beg_row;
7442 i <= dpyinfo->mouse_face_end_row;
7443 i++)
7445 int start_hpos, end_hpos, start_x;
7446 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7448 /* Don't do anything if row doesn't have valid contents. */
7449 if (!row->enabled_p)
7450 continue;
7452 /* For all but the first row, the highlight starts at column 0. */
7453 if (i == dpyinfo->mouse_face_beg_row)
7455 start_hpos = dpyinfo->mouse_face_beg_col;
7456 start_x = dpyinfo->mouse_face_beg_x;
7458 else
7460 start_hpos = 0;
7461 start_x = 0;
7464 if (i == dpyinfo->mouse_face_end_row)
7465 end_hpos = dpyinfo->mouse_face_end_col;
7466 else
7467 end_hpos = row->used[TEXT_AREA];
7469 /* If the cursor's in the text we are about to rewrite, turn the
7470 cursor off. */
7471 if (!w->pseudo_window_p
7472 && i == output_cursor.vpos
7473 && output_cursor.hpos >= start_hpos - 1
7474 && output_cursor.hpos <= end_hpos)
7476 x_update_window_cursor (w, 0);
7477 cursor_off_p = 1;
7480 if (end_hpos > start_hpos)
7482 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7483 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7484 start_hpos, end_hpos, draw, NULL, NULL, 0);
7488 /* If we turned the cursor off, turn it back on. */
7489 if (cursor_off_p)
7490 x_display_cursor (w, 1,
7491 output_cursor.hpos, output_cursor.vpos,
7492 output_cursor.x, output_cursor.y);
7494 output_cursor = saved_cursor;
7496 set_x_cursor:
7498 /* Change the mouse cursor. */
7499 if (draw == DRAW_NORMAL_TEXT)
7500 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7501 f->output_data.x->text_cursor);
7502 else if (draw == DRAW_MOUSE_FACE)
7503 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7504 f->output_data.x->cross_cursor);
7505 else
7506 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7507 f->output_data.x->nontext_cursor);
7510 /* Clear out the mouse-highlighted active region.
7511 Redraw it un-highlighted first. */
7513 void
7514 clear_mouse_face (dpyinfo)
7515 struct x_display_info *dpyinfo;
7517 #if 0 /* This prevents redrawing tool bar items when changing from one
7518 to another while a tooltip is open, so don't do it. */
7519 if (!NILP (tip_frame))
7520 return;
7521 #endif
7523 if (! NILP (dpyinfo->mouse_face_window))
7524 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7526 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7527 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7528 dpyinfo->mouse_face_window = Qnil;
7532 /* Clear any mouse-face on window W. This function is part of the
7533 redisplay interface, and is called from try_window_id and similar
7534 functions to ensure the mouse-highlight is off. */
7536 static void
7537 x_clear_mouse_face (w)
7538 struct window *w;
7540 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7541 Lisp_Object window;
7543 BLOCK_INPUT;
7544 XSETWINDOW (window, w);
7545 if (EQ (window, dpyinfo->mouse_face_window))
7546 clear_mouse_face (dpyinfo);
7547 UNBLOCK_INPUT;
7551 /* Just discard the mouse face information for frame F, if any.
7552 This is used when the size of F is changed. */
7554 void
7555 cancel_mouse_face (f)
7556 FRAME_PTR f;
7558 Lisp_Object window;
7559 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7561 window = dpyinfo->mouse_face_window;
7562 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7564 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7565 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7566 dpyinfo->mouse_face_window = Qnil;
7571 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7574 /* Try to determine frame pixel position and size of the glyph under
7575 frame pixel coordinates X/Y on frame F . Return the position and
7576 size in *RECT. Value is non-zero if we could compute these
7577 values. */
7579 static int
7580 glyph_rect (f, x, y, rect)
7581 struct frame *f;
7582 int x, y;
7583 XRectangle *rect;
7585 Lisp_Object window;
7586 int part, found = 0;
7588 window = window_from_coordinates (f, x, y, &part, 0);
7589 if (!NILP (window))
7591 struct window *w = XWINDOW (window);
7592 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7593 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7594 int area;
7596 frame_to_window_pixel_xy (w, &x, &y);
7598 for (; !found && r < end && r->enabled_p; ++r)
7599 if (r->y >= y)
7601 struct glyph *g = r->glyphs[TEXT_AREA];
7602 struct glyph *end = g + r->used[TEXT_AREA];
7603 int gx;
7605 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7606 if (gx >= x)
7608 rect->width = g->pixel_width;
7609 rect->height = r->height;
7610 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7611 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7612 found = 1;
7617 return found;
7621 /* Return the current position of the mouse.
7622 *FP should be a frame which indicates which display to ask about.
7624 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7625 and *PART to the frame, window, and scroll bar part that the mouse
7626 is over. Set *X and *Y to the portion and whole of the mouse's
7627 position on the scroll bar.
7629 If the mouse movement started elsewhere, set *FP to the frame the
7630 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7631 the mouse is over.
7633 Set *TIME to the server time-stamp for the time at which the mouse
7634 was at this position.
7636 Don't store anything if we don't have a valid set of values to report.
7638 This clears the mouse_moved flag, so we can wait for the next mouse
7639 movement. */
7641 static void
7642 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7643 FRAME_PTR *fp;
7644 int insist;
7645 Lisp_Object *bar_window;
7646 enum scroll_bar_part *part;
7647 Lisp_Object *x, *y;
7648 unsigned long *time;
7650 FRAME_PTR f1;
7652 BLOCK_INPUT;
7654 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7655 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7656 else
7658 Window root;
7659 int root_x, root_y;
7661 Window dummy_window;
7662 int dummy;
7664 Lisp_Object frame, tail;
7666 /* Clear the mouse-moved flag for every frame on this display. */
7667 FOR_EACH_FRAME (tail, frame)
7668 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7669 XFRAME (frame)->mouse_moved = 0;
7671 last_mouse_scroll_bar = Qnil;
7673 /* Figure out which root window we're on. */
7674 XQueryPointer (FRAME_X_DISPLAY (*fp),
7675 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7677 /* The root window which contains the pointer. */
7678 &root,
7680 /* Trash which we can't trust if the pointer is on
7681 a different screen. */
7682 &dummy_window,
7684 /* The position on that root window. */
7685 &root_x, &root_y,
7687 /* More trash we can't trust. */
7688 &dummy, &dummy,
7690 /* Modifier keys and pointer buttons, about which
7691 we don't care. */
7692 (unsigned int *) &dummy);
7694 /* Now we have a position on the root; find the innermost window
7695 containing the pointer. */
7697 Window win, child;
7698 int win_x, win_y;
7699 int parent_x = 0, parent_y = 0;
7700 int count;
7702 win = root;
7704 /* XTranslateCoordinates can get errors if the window
7705 structure is changing at the same time this function
7706 is running. So at least we must not crash from them. */
7708 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7710 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7711 && FRAME_LIVE_P (last_mouse_frame))
7713 /* If mouse was grabbed on a frame, give coords for that frame
7714 even if the mouse is now outside it. */
7715 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7717 /* From-window, to-window. */
7718 root, FRAME_X_WINDOW (last_mouse_frame),
7720 /* From-position, to-position. */
7721 root_x, root_y, &win_x, &win_y,
7723 /* Child of win. */
7724 &child);
7725 f1 = last_mouse_frame;
7727 else
7729 while (1)
7731 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7733 /* From-window, to-window. */
7734 root, win,
7736 /* From-position, to-position. */
7737 root_x, root_y, &win_x, &win_y,
7739 /* Child of win. */
7740 &child);
7742 if (child == None || child == win)
7743 break;
7745 win = child;
7746 parent_x = win_x;
7747 parent_y = win_y;
7750 /* Now we know that:
7751 win is the innermost window containing the pointer
7752 (XTC says it has no child containing the pointer),
7753 win_x and win_y are the pointer's position in it
7754 (XTC did this the last time through), and
7755 parent_x and parent_y are the pointer's position in win's parent.
7756 (They are what win_x and win_y were when win was child.
7757 If win is the root window, it has no parent, and
7758 parent_{x,y} are invalid, but that's okay, because we'll
7759 never use them in that case.) */
7761 /* Is win one of our frames? */
7762 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7764 #ifdef USE_X_TOOLKIT
7765 /* If we end up with the menu bar window, say it's not
7766 on the frame. */
7767 if (f1 != NULL
7768 && f1->output_data.x->menubar_widget
7769 && win == XtWindow (f1->output_data.x->menubar_widget))
7770 f1 = NULL;
7771 #endif /* USE_X_TOOLKIT */
7774 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7775 f1 = 0;
7777 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7779 /* If not, is it one of our scroll bars? */
7780 if (! f1)
7782 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7784 if (bar)
7786 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7787 win_x = parent_x;
7788 win_y = parent_y;
7792 if (f1 == 0 && insist > 0)
7793 f1 = SELECTED_FRAME ();
7795 if (f1)
7797 /* Ok, we found a frame. Store all the values.
7798 last_mouse_glyph is a rectangle used to reduce the
7799 generation of mouse events. To not miss any motion
7800 events, we must divide the frame into rectangles of the
7801 size of the smallest character that could be displayed
7802 on it, i.e. into the same rectangles that matrices on
7803 the frame are divided into. */
7805 int width, height, gx, gy;
7806 XRectangle rect;
7808 if (glyph_rect (f1, win_x, win_y, &rect))
7809 last_mouse_glyph = rect;
7810 else
7812 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7813 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7814 gx = win_x;
7815 gy = win_y;
7817 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7818 round down even for negative values. */
7819 if (gx < 0)
7820 gx -= width - 1;
7821 if (gy < 0)
7822 gy -= height - 1;
7823 gx = (gx + width - 1) / width * width;
7824 gy = (gy + height - 1) / height * height;
7826 last_mouse_glyph.width = width;
7827 last_mouse_glyph.height = height;
7828 last_mouse_glyph.x = gx;
7829 last_mouse_glyph.y = gy;
7832 *bar_window = Qnil;
7833 *part = 0;
7834 *fp = f1;
7835 XSETINT (*x, win_x);
7836 XSETINT (*y, win_y);
7837 *time = last_mouse_movement_time;
7842 UNBLOCK_INPUT;
7846 #ifdef USE_X_TOOLKIT
7848 /* Atimer callback function for TIMER. Called every 0.1s to process
7849 Xt timeouts, if needed. We must avoid calling XtAppPending as
7850 much as possible because that function does an implicit XFlush
7851 that slows us down. */
7853 static void
7854 x_process_timeouts (timer)
7855 struct atimer *timer;
7857 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7859 BLOCK_INPUT;
7860 while (XtAppPending (Xt_app_con) & XtIMTimer)
7861 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7862 UNBLOCK_INPUT;
7866 #endif /* USE_X_TOOLKIT */
7869 /* Scroll bar support. */
7871 /* Given an X window ID, find the struct scroll_bar which manages it.
7872 This can be called in GC, so we have to make sure to strip off mark
7873 bits. */
7875 static struct scroll_bar *
7876 x_window_to_scroll_bar (window_id)
7877 Window window_id;
7879 Lisp_Object tail;
7881 for (tail = Vframe_list;
7882 XGCTYPE (tail) == Lisp_Cons;
7883 tail = XCDR (tail))
7885 Lisp_Object frame, bar, condemned;
7887 frame = XCAR (tail);
7888 /* All elements of Vframe_list should be frames. */
7889 if (! GC_FRAMEP (frame))
7890 abort ();
7892 /* Scan this frame's scroll bar list for a scroll bar with the
7893 right window ID. */
7894 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7895 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7896 /* This trick allows us to search both the ordinary and
7897 condemned scroll bar lists with one loop. */
7898 ! GC_NILP (bar) || (bar = condemned,
7899 condemned = Qnil,
7900 ! GC_NILP (bar));
7901 bar = XSCROLL_BAR (bar)->next)
7902 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7903 return XSCROLL_BAR (bar);
7906 return 0;
7911 /************************************************************************
7912 Toolkit scroll bars
7913 ************************************************************************/
7915 #ifdef USE_TOOLKIT_SCROLL_BARS
7917 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7918 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7919 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7920 struct scroll_bar *));
7921 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7922 int, int, int));
7925 /* Id of action hook installed for scroll bars. */
7927 static XtActionHookId action_hook_id;
7929 /* Lisp window being scrolled. Set when starting to interact with
7930 a toolkit scroll bar, reset to nil when ending the interaction. */
7932 static Lisp_Object window_being_scrolled;
7934 /* Last scroll bar part sent in xm_scroll_callback. */
7936 static int last_scroll_bar_part;
7938 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7939 that movements of 1/20 of the screen size are mapped to up/down. */
7941 static Boolean xaw3d_arrow_scroll;
7943 /* Whether the drag scrolling maintains the mouse at the top of the
7944 thumb. If not, resizing the thumb needs to be done more carefully
7945 to avoid jerkyness. */
7947 static Boolean xaw3d_pick_top;
7950 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7951 bars are used.. The hook is responsible for detecting when
7952 the user ends an interaction with the scroll bar, and generates
7953 a `end-scroll' scroll_bar_click' event if so. */
7955 static void
7956 xt_action_hook (widget, client_data, action_name, event, params,
7957 num_params)
7958 Widget widget;
7959 XtPointer client_data;
7960 String action_name;
7961 XEvent *event;
7962 String *params;
7963 Cardinal *num_params;
7965 int scroll_bar_p;
7966 char *end_action;
7968 #ifdef USE_MOTIF
7969 scroll_bar_p = XmIsScrollBar (widget);
7970 end_action = "Release";
7971 #else /* !USE_MOTIF i.e. use Xaw */
7972 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7973 end_action = "EndScroll";
7974 #endif /* USE_MOTIF */
7976 if (scroll_bar_p
7977 && strcmp (action_name, end_action) == 0
7978 && WINDOWP (window_being_scrolled))
7980 struct window *w;
7982 x_send_scroll_bar_event (window_being_scrolled,
7983 scroll_bar_end_scroll, 0, 0);
7984 w = XWINDOW (window_being_scrolled);
7985 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7986 window_being_scrolled = Qnil;
7987 last_scroll_bar_part = -1;
7989 /* Xt timeouts no longer needed. */
7990 toolkit_scroll_bar_interaction = 0;
7994 /* A vector of windows used for communication between
7995 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
7997 static struct window **scroll_bar_windows;
7998 static int scroll_bar_windows_size;
8001 /* Send a client message with message type Xatom_Scrollbar for a
8002 scroll action to the frame of WINDOW. PART is a value identifying
8003 the part of the scroll bar that was clicked on. PORTION is the
8004 amount to scroll of a whole of WHOLE. */
8006 static void
8007 x_send_scroll_bar_event (window, part, portion, whole)
8008 Lisp_Object window;
8009 int part, portion, whole;
8011 XEvent event;
8012 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8013 struct window *w = XWINDOW (window);
8014 struct frame *f = XFRAME (w->frame);
8015 int i;
8017 BLOCK_INPUT;
8019 /* Construct a ClientMessage event to send to the frame. */
8020 ev->type = ClientMessage;
8021 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8022 ev->display = FRAME_X_DISPLAY (f);
8023 ev->window = FRAME_X_WINDOW (f);
8024 ev->format = 32;
8026 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8027 not enough to store a pointer or Lisp_Object on a 64 bit system.
8028 So, store the window in scroll_bar_windows and pass the index
8029 into that array in the event. */
8030 for (i = 0; i < scroll_bar_windows_size; ++i)
8031 if (scroll_bar_windows[i] == NULL)
8032 break;
8034 if (i == scroll_bar_windows_size)
8036 int new_size = max (10, 2 * scroll_bar_windows_size);
8037 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8038 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8040 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8041 nbytes);
8042 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8043 scroll_bar_windows_size = new_size;
8046 scroll_bar_windows[i] = w;
8047 ev->data.l[0] = (long) i;
8048 ev->data.l[1] = (long) part;
8049 ev->data.l[2] = (long) 0;
8050 ev->data.l[3] = (long) portion;
8051 ev->data.l[4] = (long) whole;
8053 /* Make Xt timeouts work while the scroll bar is active. */
8054 toolkit_scroll_bar_interaction = 1;
8056 /* Setting the event mask to zero means that the message will
8057 be sent to the client that created the window, and if that
8058 window no longer exists, no event will be sent. */
8059 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8060 UNBLOCK_INPUT;
8064 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8065 in *IEVENT. */
8067 static void
8068 x_scroll_bar_to_input_event (event, ievent)
8069 XEvent *event;
8070 struct input_event *ievent;
8072 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8073 Lisp_Object window;
8074 struct frame *f;
8075 struct window *w;
8077 w = scroll_bar_windows[ev->data.l[0]];
8078 scroll_bar_windows[ev->data.l[0]] = NULL;
8080 XSETWINDOW (window, w);
8081 f = XFRAME (w->frame);
8083 ievent->kind = scroll_bar_click;
8084 ievent->frame_or_window = window;
8085 ievent->arg = Qnil;
8086 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8087 ievent->part = ev->data.l[1];
8088 ievent->code = ev->data.l[2];
8089 ievent->x = make_number ((int) ev->data.l[3]);
8090 ievent->y = make_number ((int) ev->data.l[4]);
8091 ievent->modifiers = 0;
8095 #ifdef USE_MOTIF
8097 /* Minimum and maximum values used for Motif scroll bars. */
8099 #define XM_SB_MIN 1
8100 #define XM_SB_MAX 10000000
8101 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8104 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8105 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8106 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8108 static void
8109 xm_scroll_callback (widget, client_data, call_data)
8110 Widget widget;
8111 XtPointer client_data, call_data;
8113 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8114 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8115 double percent;
8116 int part = -1, whole = 0, portion = 0;
8118 switch (cs->reason)
8120 case XmCR_DECREMENT:
8121 bar->dragging = Qnil;
8122 part = scroll_bar_up_arrow;
8123 break;
8125 case XmCR_INCREMENT:
8126 bar->dragging = Qnil;
8127 part = scroll_bar_down_arrow;
8128 break;
8130 case XmCR_PAGE_DECREMENT:
8131 bar->dragging = Qnil;
8132 part = scroll_bar_above_handle;
8133 break;
8135 case XmCR_PAGE_INCREMENT:
8136 bar->dragging = Qnil;
8137 part = scroll_bar_below_handle;
8138 break;
8140 case XmCR_TO_TOP:
8141 bar->dragging = Qnil;
8142 part = scroll_bar_to_top;
8143 break;
8145 case XmCR_TO_BOTTOM:
8146 bar->dragging = Qnil;
8147 part = scroll_bar_to_bottom;
8148 break;
8150 case XmCR_DRAG:
8152 int slider_size;
8153 int dragging_down_p = (INTEGERP (bar->dragging)
8154 && XINT (bar->dragging) <= cs->value);
8156 /* Get the slider size. */
8157 BLOCK_INPUT;
8158 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8159 UNBLOCK_INPUT;
8161 /* At the max position of the scroll bar, do a line-wise
8162 movement. Without doing anything, we would be called with
8163 the same cs->value again and again. If we want to make
8164 sure that we can reach the end of the buffer, we have to do
8165 something.
8167 Implementation note: setting bar->dragging always to
8168 cs->value gives a smoother movement at the max position.
8169 Setting it to nil when doing line-wise movement gives
8170 a better slider behavior. */
8172 if (cs->value + slider_size == XM_SB_MAX
8173 || (dragging_down_p
8174 && last_scroll_bar_part == scroll_bar_down_arrow))
8176 part = scroll_bar_down_arrow;
8177 bar->dragging = Qnil;
8179 else
8181 whole = XM_SB_RANGE;
8182 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8183 part = scroll_bar_handle;
8184 bar->dragging = make_number (cs->value);
8187 break;
8189 case XmCR_VALUE_CHANGED:
8190 break;
8193 if (part >= 0)
8195 window_being_scrolled = bar->window;
8196 last_scroll_bar_part = part;
8197 x_send_scroll_bar_event (bar->window, part, portion, whole);
8202 #else /* !USE_MOTIF, i.e. Xaw. */
8205 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8206 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8207 scroll bar struct. CALL_DATA is a pointer to a float saying where
8208 the thumb is. */
8210 static void
8211 xaw_jump_callback (widget, client_data, call_data)
8212 Widget widget;
8213 XtPointer client_data, call_data;
8215 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8216 float top = *(float *) call_data;
8217 float shown;
8218 int whole, portion, height;
8219 int part;
8221 /* Get the size of the thumb, a value between 0 and 1. */
8222 BLOCK_INPUT;
8223 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8224 UNBLOCK_INPUT;
8226 whole = 10000000;
8227 portion = shown < 1 ? top * whole : 0;
8229 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8230 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8231 the bottom, so we force the scrolling whenever we see that we're
8232 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8233 we try to ensure that we always stay two pixels away from the
8234 bottom). */
8235 part = scroll_bar_down_arrow;
8236 else
8237 part = scroll_bar_handle;
8239 window_being_scrolled = bar->window;
8240 bar->dragging = make_number (portion);
8241 last_scroll_bar_part = part;
8242 x_send_scroll_bar_event (bar->window, part, portion, whole);
8246 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8247 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8248 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8249 the scroll bar. CALL_DATA is an integer specifying the action that
8250 has taken place. It's magnitude is in the range 0..height of the
8251 scroll bar. Negative values mean scroll towards buffer start.
8252 Values < height of scroll bar mean line-wise movement. */
8254 static void
8255 xaw_scroll_callback (widget, client_data, call_data)
8256 Widget widget;
8257 XtPointer client_data, call_data;
8259 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8260 int position = (int) call_data;
8261 Dimension height;
8262 int part;
8264 /* Get the height of the scroll bar. */
8265 BLOCK_INPUT;
8266 XtVaGetValues (widget, XtNheight, &height, NULL);
8267 UNBLOCK_INPUT;
8269 if (abs (position) >= height)
8270 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8272 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8273 it maps line-movement to call_data = max(5, height/20). */
8274 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8275 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8276 else
8277 part = scroll_bar_move_ratio;
8279 window_being_scrolled = bar->window;
8280 bar->dragging = Qnil;
8281 last_scroll_bar_part = part;
8282 x_send_scroll_bar_event (bar->window, part, position, height);
8286 #endif /* not USE_MOTIF */
8289 /* Create the widget for scroll bar BAR on frame F. Record the widget
8290 and X window of the scroll bar in BAR. */
8292 static void
8293 x_create_toolkit_scroll_bar (f, bar)
8294 struct frame *f;
8295 struct scroll_bar *bar;
8297 Window xwindow;
8298 Widget widget;
8299 Arg av[20];
8300 int ac = 0;
8301 char *scroll_bar_name = "verticalScrollBar";
8302 unsigned long pixel;
8304 BLOCK_INPUT;
8306 #ifdef USE_MOTIF
8307 /* Set resources. Create the widget. */
8308 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8309 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8310 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8311 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8312 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8313 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8314 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8316 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8317 if (pixel != -1)
8319 XtSetArg (av[ac], XmNforeground, pixel);
8320 ++ac;
8323 pixel = f->output_data.x->scroll_bar_background_pixel;
8324 if (pixel != -1)
8326 XtSetArg (av[ac], XmNbackground, pixel);
8327 ++ac;
8330 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8331 scroll_bar_name, av, ac);
8333 /* Add one callback for everything that can happen. */
8334 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8335 (XtPointer) bar);
8336 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8337 (XtPointer) bar);
8338 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8339 (XtPointer) bar);
8340 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8341 (XtPointer) bar);
8342 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8343 (XtPointer) bar);
8344 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8345 (XtPointer) bar);
8346 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8347 (XtPointer) bar);
8349 /* Realize the widget. Only after that is the X window created. */
8350 XtRealizeWidget (widget);
8352 /* Set the cursor to an arrow. I didn't find a resource to do that.
8353 And I'm wondering why it hasn't an arrow cursor by default. */
8354 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8355 f->output_data.x->nontext_cursor);
8357 #else /* !USE_MOTIF i.e. use Xaw */
8359 /* Set resources. Create the widget. The background of the
8360 Xaw3d scroll bar widget is a little bit light for my taste.
8361 We don't alter it here to let users change it according
8362 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8363 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8364 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8365 /* For smoother scrolling with Xaw3d -sm */
8366 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8367 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8369 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8370 if (pixel != -1)
8372 XtSetArg (av[ac], XtNforeground, pixel);
8373 ++ac;
8376 pixel = f->output_data.x->scroll_bar_background_pixel;
8377 if (pixel != -1)
8379 XtSetArg (av[ac], XtNbackground, pixel);
8380 ++ac;
8383 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8384 f->output_data.x->edit_widget, av, ac);
8387 char *initial = "";
8388 char *val = initial;
8389 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8390 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8391 if (val == initial)
8392 { /* ARROW_SCROLL */
8393 xaw3d_arrow_scroll = True;
8394 /* Isn't that just a personal preference ? -sm */
8395 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8399 /* Define callbacks. */
8400 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8401 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8402 (XtPointer) bar);
8404 /* Realize the widget. Only after that is the X window created. */
8405 XtRealizeWidget (widget);
8407 #endif /* !USE_MOTIF */
8409 /* Install an action hook that let's us detect when the user
8410 finishes interacting with a scroll bar. */
8411 if (action_hook_id == 0)
8412 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8414 /* Remember X window and widget in the scroll bar vector. */
8415 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8416 xwindow = XtWindow (widget);
8417 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8419 UNBLOCK_INPUT;
8423 /* Set the thumb size and position of scroll bar BAR. We are currently
8424 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8426 static void
8427 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8428 struct scroll_bar *bar;
8429 int portion, position, whole;
8431 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8432 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8433 float top, shown;
8435 if (whole == 0)
8436 top = 0, shown = 1;
8437 else
8439 top = (float) position / whole;
8440 shown = (float) portion / whole;
8443 BLOCK_INPUT;
8445 #ifdef USE_MOTIF
8447 int size, value;
8448 XmScrollBarWidget sb;
8450 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8451 is the scroll bar's maximum and MIN is the scroll bar's minimum
8452 value. */
8453 size = shown * XM_SB_RANGE;
8454 size = min (size, XM_SB_RANGE);
8455 size = max (size, 1);
8457 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8458 value = top * XM_SB_RANGE;
8459 value = min (value, XM_SB_MAX - size);
8460 value = max (value, XM_SB_MIN);
8462 if (NILP (bar->dragging))
8463 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8464 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8465 /* This has the negative side effect that the slider value is
8466 not what it would be if we scrolled here using line-wise or
8467 page-wise movement. */
8468 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8469 else
8471 /* If currently dragging, only update the slider size.
8472 This reduces flicker effects. */
8473 int old_value, old_size, increment, page_increment;
8475 XmScrollBarGetValues (widget, &old_value, &old_size,
8476 &increment, &page_increment);
8477 XmScrollBarSetValues (widget, old_value,
8478 min (size, XM_SB_RANGE - old_value),
8479 0, 0, False);
8482 #else /* !USE_MOTIF i.e. use Xaw */
8484 float old_top, old_shown;
8485 Dimension height;
8486 XtVaGetValues (widget,
8487 XtNtopOfThumb, &old_top,
8488 XtNshown, &old_shown,
8489 XtNheight, &height,
8490 NULL);
8492 /* Massage the top+shown values. */
8493 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8494 top = max (0, min (1, top));
8495 else
8496 top = old_top;
8497 /* Keep two pixels available for moving the thumb down. */
8498 shown = max (0, min (1 - top - (2.0 / height), shown));
8500 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8501 check that your system's configuration file contains a define
8502 for `NARROWPROTO'. See s/freebsd.h for an example. */
8503 if (top != old_top || shown != old_shown)
8505 if (NILP (bar->dragging))
8506 XawScrollbarSetThumb (widget, top, shown);
8507 else
8509 #ifdef HAVE_XAW3D
8510 ScrollbarWidget sb = (ScrollbarWidget) widget;
8511 int scroll_mode = 0;
8513 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8514 if (xaw3d_arrow_scroll)
8516 /* Xaw3d stupidly ignores resize requests while dragging
8517 so we have to make it believe it's not in dragging mode. */
8518 scroll_mode = sb->scrollbar.scroll_mode;
8519 if (scroll_mode == 2)
8520 sb->scrollbar.scroll_mode = 0;
8522 #endif
8523 /* Try to make the scrolling a tad smoother. */
8524 if (!xaw3d_pick_top)
8525 shown = min (shown, old_shown);
8527 XawScrollbarSetThumb (widget, top, shown);
8529 #ifdef HAVE_XAW3D
8530 if (xaw3d_arrow_scroll && scroll_mode == 2)
8531 sb->scrollbar.scroll_mode = scroll_mode;
8532 #endif
8536 #endif /* !USE_MOTIF */
8538 UNBLOCK_INPUT;
8541 #endif /* USE_TOOLKIT_SCROLL_BARS */
8545 /************************************************************************
8546 Scroll bars, general
8547 ************************************************************************/
8549 /* Create a scroll bar and return the scroll bar vector for it. W is
8550 the Emacs window on which to create the scroll bar. TOP, LEFT,
8551 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8552 scroll bar. */
8554 static struct scroll_bar *
8555 x_scroll_bar_create (w, top, left, width, height)
8556 struct window *w;
8557 int top, left, width, height;
8559 struct frame *f = XFRAME (w->frame);
8560 struct scroll_bar *bar
8561 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8563 BLOCK_INPUT;
8565 #ifdef USE_TOOLKIT_SCROLL_BARS
8566 x_create_toolkit_scroll_bar (f, bar);
8567 #else /* not USE_TOOLKIT_SCROLL_BARS */
8569 XSetWindowAttributes a;
8570 unsigned long mask;
8571 Window window;
8573 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8574 if (a.background_pixel == -1)
8575 a.background_pixel = f->output_data.x->background_pixel;
8577 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8578 | ButtonMotionMask | PointerMotionHintMask
8579 | ExposureMask);
8580 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8582 mask = (CWBackPixel | CWEventMask | CWCursor);
8584 /* Clear the area of W that will serve as a scroll bar. This is
8585 for the case that a window has been split horizontally. In
8586 this case, no clear_frame is generated to reduce flickering. */
8587 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8588 left, top, width,
8589 window_box_height (w), False);
8591 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8592 /* Position and size of scroll bar. */
8593 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8594 top,
8595 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8596 height,
8597 /* Border width, depth, class, and visual. */
8599 CopyFromParent,
8600 CopyFromParent,
8601 CopyFromParent,
8602 /* Attributes. */
8603 mask, &a);
8604 SET_SCROLL_BAR_X_WINDOW (bar, window);
8606 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8608 XSETWINDOW (bar->window, w);
8609 XSETINT (bar->top, top);
8610 XSETINT (bar->left, left);
8611 XSETINT (bar->width, width);
8612 XSETINT (bar->height, height);
8613 XSETINT (bar->start, 0);
8614 XSETINT (bar->end, 0);
8615 bar->dragging = Qnil;
8617 /* Add bar to its frame's list of scroll bars. */
8618 bar->next = FRAME_SCROLL_BARS (f);
8619 bar->prev = Qnil;
8620 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8621 if (!NILP (bar->next))
8622 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8624 /* Map the window/widget. */
8625 #ifdef USE_TOOLKIT_SCROLL_BARS
8627 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8628 XtConfigureWidget (scroll_bar,
8629 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8630 top,
8631 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8632 max (height, 1), 0);
8633 XtMapWidget (scroll_bar);
8635 #else /* not USE_TOOLKIT_SCROLL_BARS */
8636 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8637 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8639 UNBLOCK_INPUT;
8640 return bar;
8644 /* Draw BAR's handle in the proper position.
8646 If the handle is already drawn from START to END, don't bother
8647 redrawing it, unless REBUILD is non-zero; in that case, always
8648 redraw it. (REBUILD is handy for drawing the handle after expose
8649 events.)
8651 Normally, we want to constrain the start and end of the handle to
8652 fit inside its rectangle, but if the user is dragging the scroll
8653 bar handle, we want to let them drag it down all the way, so that
8654 the bar's top is as far down as it goes; otherwise, there's no way
8655 to move to the very end of the buffer. */
8657 #ifndef USE_TOOLKIT_SCROLL_BARS
8659 static void
8660 x_scroll_bar_set_handle (bar, start, end, rebuild)
8661 struct scroll_bar *bar;
8662 int start, end;
8663 int rebuild;
8665 int dragging = ! NILP (bar->dragging);
8666 Window w = SCROLL_BAR_X_WINDOW (bar);
8667 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8668 GC gc = f->output_data.x->normal_gc;
8670 /* If the display is already accurate, do nothing. */
8671 if (! rebuild
8672 && start == XINT (bar->start)
8673 && end == XINT (bar->end))
8674 return;
8676 BLOCK_INPUT;
8679 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8680 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8681 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8683 /* Make sure the values are reasonable, and try to preserve
8684 the distance between start and end. */
8686 int length = end - start;
8688 if (start < 0)
8689 start = 0;
8690 else if (start > top_range)
8691 start = top_range;
8692 end = start + length;
8694 if (end < start)
8695 end = start;
8696 else if (end > top_range && ! dragging)
8697 end = top_range;
8700 /* Store the adjusted setting in the scroll bar. */
8701 XSETINT (bar->start, start);
8702 XSETINT (bar->end, end);
8704 /* Clip the end position, just for display. */
8705 if (end > top_range)
8706 end = top_range;
8708 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8709 below top positions, to make sure the handle is always at least
8710 that many pixels tall. */
8711 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8713 /* Draw the empty space above the handle. Note that we can't clear
8714 zero-height areas; that means "clear to end of window." */
8715 if (0 < start)
8716 x_clear_area (FRAME_X_DISPLAY (f), w,
8717 /* x, y, width, height, and exposures. */
8718 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8719 VERTICAL_SCROLL_BAR_TOP_BORDER,
8720 inside_width, start,
8721 False);
8723 /* Change to proper foreground color if one is specified. */
8724 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8725 XSetForeground (FRAME_X_DISPLAY (f), gc,
8726 f->output_data.x->scroll_bar_foreground_pixel);
8728 /* Draw the handle itself. */
8729 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8730 /* x, y, width, height */
8731 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8732 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8733 inside_width, end - start);
8735 /* Restore the foreground color of the GC if we changed it above. */
8736 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8737 XSetForeground (FRAME_X_DISPLAY (f), gc,
8738 f->output_data.x->foreground_pixel);
8740 /* Draw the empty space below the handle. Note that we can't
8741 clear zero-height areas; that means "clear to end of window." */
8742 if (end < inside_height)
8743 x_clear_area (FRAME_X_DISPLAY (f), w,
8744 /* x, y, width, height, and exposures. */
8745 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8746 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8747 inside_width, inside_height - end,
8748 False);
8752 UNBLOCK_INPUT;
8755 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8757 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8758 nil. */
8760 static void
8761 x_scroll_bar_remove (bar)
8762 struct scroll_bar *bar;
8764 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8765 BLOCK_INPUT;
8767 #ifdef USE_TOOLKIT_SCROLL_BARS
8768 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8769 #else
8770 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8771 #endif
8773 /* Disassociate this scroll bar from its window. */
8774 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8776 UNBLOCK_INPUT;
8780 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8781 that we are displaying PORTION characters out of a total of WHOLE
8782 characters, starting at POSITION. If WINDOW has no scroll bar,
8783 create one. */
8785 static void
8786 XTset_vertical_scroll_bar (w, portion, whole, position)
8787 struct window *w;
8788 int portion, whole, position;
8790 struct frame *f = XFRAME (w->frame);
8791 struct scroll_bar *bar;
8792 int top, height, left, sb_left, width, sb_width;
8793 int window_x, window_y, window_width, window_height;
8795 /* Get window dimensions. */
8796 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8797 top = window_y;
8798 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8799 height = window_height;
8801 /* Compute the left edge of the scroll bar area. */
8802 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8803 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8804 else
8805 left = XFASTINT (w->left);
8806 left *= CANON_X_UNIT (f);
8807 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8809 /* Compute the width of the scroll bar which might be less than
8810 the width of the area reserved for the scroll bar. */
8811 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8812 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8813 else
8814 sb_width = width;
8816 /* Compute the left edge of the scroll bar. */
8817 #ifdef USE_TOOLKIT_SCROLL_BARS
8818 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8819 sb_left = left + width - sb_width - (width - sb_width) / 2;
8820 else
8821 sb_left = left + (width - sb_width) / 2;
8822 #else
8823 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8824 sb_left = left + width - sb_width;
8825 else
8826 sb_left = left;
8827 #endif
8829 /* Does the scroll bar exist yet? */
8830 if (NILP (w->vertical_scroll_bar))
8832 BLOCK_INPUT;
8833 if (width && height)
8834 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8835 left, top, width, height, False);
8836 UNBLOCK_INPUT;
8837 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8839 else
8841 /* It may just need to be moved and resized. */
8842 unsigned int mask = 0;
8844 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8846 BLOCK_INPUT;
8848 if (sb_left != XINT (bar->left))
8849 mask |= CWX;
8850 if (top != XINT (bar->top))
8851 mask |= CWY;
8852 if (sb_width != XINT (bar->width))
8853 mask |= CWWidth;
8854 if (height != XINT (bar->height))
8855 mask |= CWHeight;
8857 #ifdef USE_TOOLKIT_SCROLL_BARS
8859 /* Since toolkit scroll bars are smaller than the space reserved
8860 for them on the frame, we have to clear "under" them. */
8861 if (width && height)
8862 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8863 left, top, width, height, False);
8865 /* Move/size the scroll bar widget. */
8866 if (mask)
8867 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
8868 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8869 top,
8870 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8871 max (height, 1), 0);
8873 #else /* not USE_TOOLKIT_SCROLL_BARS */
8875 /* Clear areas not covered by the scroll bar because of
8876 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
8877 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8879 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8880 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8881 height, False);
8882 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8883 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8884 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8885 height, False);
8888 /* Clear areas not covered by the scroll bar because it's not as
8889 wide as the area reserved for it . This makes sure a
8890 previous mode line display is cleared after C-x 2 C-x 1, for
8891 example. */
8893 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8894 int rest = area_width - sb_width;
8895 if (rest > 0)
8896 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8897 left + area_width - rest, 0,
8898 rest, max (height, 1), False);
8901 /* Move/size the scroll bar window. */
8902 if (mask)
8904 XWindowChanges wc;
8906 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8907 wc.y = top;
8908 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8909 wc.height = height;
8910 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8911 mask, &wc);
8914 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8916 /* Remember new settings. */
8917 XSETINT (bar->left, sb_left);
8918 XSETINT (bar->top, top);
8919 XSETINT (bar->width, sb_width);
8920 XSETINT (bar->height, height);
8922 UNBLOCK_INPUT;
8925 #ifdef USE_TOOLKIT_SCROLL_BARS
8926 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8927 #else /* not USE_TOOLKIT_SCROLL_BARS */
8928 /* Set the scroll bar's current state, unless we're currently being
8929 dragged. */
8930 if (NILP (bar->dragging))
8932 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8934 if (whole == 0)
8935 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8936 else
8938 int start = ((double) position * top_range) / whole;
8939 int end = ((double) (position + portion) * top_range) / whole;
8940 x_scroll_bar_set_handle (bar, start, end, 0);
8943 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8945 XSETVECTOR (w->vertical_scroll_bar, bar);
8949 /* The following three hooks are used when we're doing a thorough
8950 redisplay of the frame. We don't explicitly know which scroll bars
8951 are going to be deleted, because keeping track of when windows go
8952 away is a real pain - "Can you say set-window-configuration, boys
8953 and girls?" Instead, we just assert at the beginning of redisplay
8954 that *all* scroll bars are to be removed, and then save a scroll bar
8955 from the fiery pit when we actually redisplay its window. */
8957 /* Arrange for all scroll bars on FRAME to be removed at the next call
8958 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8959 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8961 static void
8962 XTcondemn_scroll_bars (frame)
8963 FRAME_PTR frame;
8965 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8966 while (! NILP (FRAME_SCROLL_BARS (frame)))
8968 Lisp_Object bar;
8969 bar = FRAME_SCROLL_BARS (frame);
8970 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8971 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8972 XSCROLL_BAR (bar)->prev = Qnil;
8973 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8974 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8975 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8980 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8981 Note that WINDOW isn't necessarily condemned at all. */
8983 static void
8984 XTredeem_scroll_bar (window)
8985 struct window *window;
8987 struct scroll_bar *bar;
8988 struct frame *f;
8990 /* We can't redeem this window's scroll bar if it doesn't have one. */
8991 if (NILP (window->vertical_scroll_bar))
8992 abort ();
8994 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8996 /* Unlink it from the condemned list. */
8997 f = XFRAME (WINDOW_FRAME (window));
8998 if (NILP (bar->prev))
9000 /* If the prev pointer is nil, it must be the first in one of
9001 the lists. */
9002 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9003 /* It's not condemned. Everything's fine. */
9004 return;
9005 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9006 window->vertical_scroll_bar))
9007 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9008 else
9009 /* If its prev pointer is nil, it must be at the front of
9010 one or the other! */
9011 abort ();
9013 else
9014 XSCROLL_BAR (bar->prev)->next = bar->next;
9016 if (! NILP (bar->next))
9017 XSCROLL_BAR (bar->next)->prev = bar->prev;
9019 bar->next = FRAME_SCROLL_BARS (f);
9020 bar->prev = Qnil;
9021 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9022 if (! NILP (bar->next))
9023 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9026 /* Remove all scroll bars on FRAME that haven't been saved since the
9027 last call to `*condemn_scroll_bars_hook'. */
9029 static void
9030 XTjudge_scroll_bars (f)
9031 FRAME_PTR f;
9033 Lisp_Object bar, next;
9035 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9037 /* Clear out the condemned list now so we won't try to process any
9038 more events on the hapless scroll bars. */
9039 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9041 for (; ! NILP (bar); bar = next)
9043 struct scroll_bar *b = XSCROLL_BAR (bar);
9045 x_scroll_bar_remove (b);
9047 next = b->next;
9048 b->next = b->prev = Qnil;
9051 /* Now there should be no references to the condemned scroll bars,
9052 and they should get garbage-collected. */
9056 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9057 is a no-op when using toolkit scroll bars.
9059 This may be called from a signal handler, so we have to ignore GC
9060 mark bits. */
9062 static void
9063 x_scroll_bar_expose (bar, event)
9064 struct scroll_bar *bar;
9065 XEvent *event;
9067 #ifndef USE_TOOLKIT_SCROLL_BARS
9069 Window w = SCROLL_BAR_X_WINDOW (bar);
9070 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9071 GC gc = f->output_data.x->normal_gc;
9072 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9074 BLOCK_INPUT;
9076 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9078 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9079 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9081 /* x, y, width, height */
9082 0, 0,
9083 XINT (bar->width) - 1 - width_trim - width_trim,
9084 XINT (bar->height) - 1);
9086 UNBLOCK_INPUT;
9088 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9091 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9092 is set to something other than no_event, it is enqueued.
9094 This may be called from a signal handler, so we have to ignore GC
9095 mark bits. */
9097 #ifndef USE_TOOLKIT_SCROLL_BARS
9099 static void
9100 x_scroll_bar_handle_click (bar, event, emacs_event)
9101 struct scroll_bar *bar;
9102 XEvent *event;
9103 struct input_event *emacs_event;
9105 if (! GC_WINDOWP (bar->window))
9106 abort ();
9108 emacs_event->kind = scroll_bar_click;
9109 emacs_event->code = event->xbutton.button - Button1;
9110 emacs_event->modifiers
9111 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9112 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9113 event->xbutton.state)
9114 | (event->type == ButtonRelease
9115 ? up_modifier
9116 : down_modifier));
9117 emacs_event->frame_or_window = bar->window;
9118 emacs_event->arg = Qnil;
9119 emacs_event->timestamp = event->xbutton.time;
9121 #if 0
9122 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9123 int internal_height
9124 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9125 #endif
9126 int top_range
9127 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9128 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9130 if (y < 0) y = 0;
9131 if (y > top_range) y = top_range;
9133 if (y < XINT (bar->start))
9134 emacs_event->part = scroll_bar_above_handle;
9135 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9136 emacs_event->part = scroll_bar_handle;
9137 else
9138 emacs_event->part = scroll_bar_below_handle;
9140 /* Just because the user has clicked on the handle doesn't mean
9141 they want to drag it. Lisp code needs to be able to decide
9142 whether or not we're dragging. */
9143 #if 0
9144 /* If the user has just clicked on the handle, record where they're
9145 holding it. */
9146 if (event->type == ButtonPress
9147 && emacs_event->part == scroll_bar_handle)
9148 XSETINT (bar->dragging, y - XINT (bar->start));
9149 #endif
9151 /* If the user has released the handle, set it to its final position. */
9152 if (event->type == ButtonRelease
9153 && ! NILP (bar->dragging))
9155 int new_start = y - XINT (bar->dragging);
9156 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9158 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9159 bar->dragging = Qnil;
9162 /* Same deal here as the other #if 0. */
9163 #if 0
9164 /* Clicks on the handle are always reported as occurring at the top of
9165 the handle. */
9166 if (emacs_event->part == scroll_bar_handle)
9167 emacs_event->x = bar->start;
9168 else
9169 XSETINT (emacs_event->x, y);
9170 #else
9171 XSETINT (emacs_event->x, y);
9172 #endif
9174 XSETINT (emacs_event->y, top_range);
9178 /* Handle some mouse motion while someone is dragging the scroll bar.
9180 This may be called from a signal handler, so we have to ignore GC
9181 mark bits. */
9183 static void
9184 x_scroll_bar_note_movement (bar, event)
9185 struct scroll_bar *bar;
9186 XEvent *event;
9188 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9190 last_mouse_movement_time = event->xmotion.time;
9192 f->mouse_moved = 1;
9193 XSETVECTOR (last_mouse_scroll_bar, bar);
9195 /* If we're dragging the bar, display it. */
9196 if (! GC_NILP (bar->dragging))
9198 /* Where should the handle be now? */
9199 int new_start = event->xmotion.y - XINT (bar->dragging);
9201 if (new_start != XINT (bar->start))
9203 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9205 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9210 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9212 /* Return information to the user about the current position of the mouse
9213 on the scroll bar. */
9215 static void
9216 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9217 FRAME_PTR *fp;
9218 Lisp_Object *bar_window;
9219 enum scroll_bar_part *part;
9220 Lisp_Object *x, *y;
9221 unsigned long *time;
9223 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9224 Window w = SCROLL_BAR_X_WINDOW (bar);
9225 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9226 int win_x, win_y;
9227 Window dummy_window;
9228 int dummy_coord;
9229 unsigned int dummy_mask;
9231 BLOCK_INPUT;
9233 /* Get the mouse's position relative to the scroll bar window, and
9234 report that. */
9235 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9237 /* Root, child, root x and root y. */
9238 &dummy_window, &dummy_window,
9239 &dummy_coord, &dummy_coord,
9241 /* Position relative to scroll bar. */
9242 &win_x, &win_y,
9244 /* Mouse buttons and modifier keys. */
9245 &dummy_mask))
9247 else
9249 #if 0
9250 int inside_height
9251 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9252 #endif
9253 int top_range
9254 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9256 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9258 if (! NILP (bar->dragging))
9259 win_y -= XINT (bar->dragging);
9261 if (win_y < 0)
9262 win_y = 0;
9263 if (win_y > top_range)
9264 win_y = top_range;
9266 *fp = f;
9267 *bar_window = bar->window;
9269 if (! NILP (bar->dragging))
9270 *part = scroll_bar_handle;
9271 else if (win_y < XINT (bar->start))
9272 *part = scroll_bar_above_handle;
9273 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9274 *part = scroll_bar_handle;
9275 else
9276 *part = scroll_bar_below_handle;
9278 XSETINT (*x, win_y);
9279 XSETINT (*y, top_range);
9281 f->mouse_moved = 0;
9282 last_mouse_scroll_bar = Qnil;
9285 *time = last_mouse_movement_time;
9287 UNBLOCK_INPUT;
9291 /* The screen has been cleared so we may have changed foreground or
9292 background colors, and the scroll bars may need to be redrawn.
9293 Clear out the scroll bars, and ask for expose events, so we can
9294 redraw them. */
9296 void
9297 x_scroll_bar_clear (f)
9298 FRAME_PTR f;
9300 #ifndef USE_TOOLKIT_SCROLL_BARS
9301 Lisp_Object bar;
9303 /* We can have scroll bars even if this is 0,
9304 if we just turned off scroll bar mode.
9305 But in that case we should not clear them. */
9306 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9307 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9308 bar = XSCROLL_BAR (bar)->next)
9309 XClearArea (FRAME_X_DISPLAY (f),
9310 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9311 0, 0, 0, 0, True);
9312 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9315 /* This processes Expose events from the menu-bar specific X event
9316 loop in xmenu.c. This allows to redisplay the frame if necessary
9317 when handling menu-bar or pop-up items. */
9320 process_expose_from_menu (event)
9321 XEvent event;
9323 FRAME_PTR f;
9324 struct x_display_info *dpyinfo;
9325 int frame_exposed_p = 0;
9327 BLOCK_INPUT;
9329 dpyinfo = x_display_info_for_display (event.xexpose.display);
9330 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9331 if (f)
9333 if (f->async_visible == 0)
9335 f->async_visible = 1;
9336 f->async_iconified = 0;
9337 f->output_data.x->has_been_visible = 1;
9338 SET_FRAME_GARBAGED (f);
9340 else
9342 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9343 event.xexpose.x, event.xexpose.y,
9344 event.xexpose.width, event.xexpose.height);
9345 frame_exposed_p = 1;
9348 else
9350 struct scroll_bar *bar
9351 = x_window_to_scroll_bar (event.xexpose.window);
9353 if (bar)
9354 x_scroll_bar_expose (bar, &event);
9357 UNBLOCK_INPUT;
9358 return frame_exposed_p;
9361 /* Define a queue to save up SelectionRequest events for later handling. */
9363 struct selection_event_queue
9365 XEvent event;
9366 struct selection_event_queue *next;
9369 static struct selection_event_queue *queue;
9371 /* Nonzero means queue up certain events--don't process them yet. */
9373 static int x_queue_selection_requests;
9375 /* Queue up an X event *EVENT, to be processed later. */
9377 static void
9378 x_queue_event (f, event)
9379 FRAME_PTR f;
9380 XEvent *event;
9382 struct selection_event_queue *queue_tmp
9383 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9385 if (queue_tmp != NULL)
9387 queue_tmp->event = *event;
9388 queue_tmp->next = queue;
9389 queue = queue_tmp;
9393 /* Take all the queued events and put them back
9394 so that they get processed afresh. */
9396 static void
9397 x_unqueue_events (display)
9398 Display *display;
9400 while (queue != NULL)
9402 struct selection_event_queue *queue_tmp = queue;
9403 XPutBackEvent (display, &queue_tmp->event);
9404 queue = queue_tmp->next;
9405 xfree ((char *)queue_tmp);
9409 /* Start queuing SelectionRequest events. */
9411 void
9412 x_start_queuing_selection_requests (display)
9413 Display *display;
9415 x_queue_selection_requests++;
9418 /* Stop queuing SelectionRequest events. */
9420 void
9421 x_stop_queuing_selection_requests (display)
9422 Display *display;
9424 x_queue_selection_requests--;
9425 x_unqueue_events (display);
9428 /* The main X event-reading loop - XTread_socket. */
9430 /* Time stamp of enter window event. This is only used by XTread_socket,
9431 but we have to put it out here, since static variables within functions
9432 sometimes don't work. */
9434 static Time enter_timestamp;
9436 /* This holds the state XLookupString needs to implement dead keys
9437 and other tricks known as "compose processing". _X Window System_
9438 says that a portable program can't use this, but Stephen Gildea assures
9439 me that letting the compiler initialize it to zeros will work okay.
9441 This must be defined outside of XTread_socket, for the same reasons
9442 given for enter_time stamp, above. */
9444 static XComposeStatus compose_status;
9446 /* Record the last 100 characters stored
9447 to help debug the loss-of-chars-during-GC problem. */
9449 static int temp_index;
9450 static short temp_buffer[100];
9452 /* Set this to nonzero to fake an "X I/O error"
9453 on a particular display. */
9455 struct x_display_info *XTread_socket_fake_io_error;
9457 /* When we find no input here, we occasionally do a no-op command
9458 to verify that the X server is still running and we can still talk with it.
9459 We try all the open displays, one by one.
9460 This variable is used for cycling thru the displays. */
9462 static struct x_display_info *next_noop_dpyinfo;
9464 #define SET_SAVED_MENU_EVENT(size) \
9465 do \
9467 if (f->output_data.x->saved_menu_event == 0) \
9468 f->output_data.x->saved_menu_event \
9469 = (XEvent *) xmalloc (sizeof (XEvent)); \
9470 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9471 if (numchars >= 1) \
9473 bufp->kind = menu_bar_activate_event; \
9474 XSETFRAME (bufp->frame_or_window, f); \
9475 bufp->arg = Qnil; \
9476 bufp++; \
9477 count++; \
9478 numchars--; \
9481 while (0)
9483 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9484 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9486 /* Read events coming from the X server.
9487 This routine is called by the SIGIO handler.
9488 We return as soon as there are no more events to be read.
9490 Events representing keys are stored in buffer BUFP,
9491 which can hold up to NUMCHARS characters.
9492 We return the number of characters stored into the buffer,
9493 thus pretending to be `read'.
9495 EXPECTED is nonzero if the caller knows input is available. */
9498 XTread_socket (sd, bufp, numchars, expected)
9499 register int sd;
9500 /* register */ struct input_event *bufp;
9501 /* register */ int numchars;
9502 int expected;
9504 int count = 0;
9505 int nbytes = 0;
9506 XEvent event;
9507 struct frame *f;
9508 int event_found = 0;
9509 struct x_display_info *dpyinfo;
9510 struct coding_system coding;
9512 if (interrupt_input_blocked)
9514 interrupt_input_pending = 1;
9515 return -1;
9518 interrupt_input_pending = 0;
9519 BLOCK_INPUT;
9521 /* So people can tell when we have read the available input. */
9522 input_signal_count++;
9524 if (numchars <= 0)
9525 abort (); /* Don't think this happens. */
9527 ++handling_signal;
9529 /* The input should be decoded if it is from XIM. Currently the
9530 locale of XIM is the same as that of the system. So, we can use
9531 Vlocale_coding_system which is initialized properly at Emacs
9532 startup time. */
9533 setup_coding_system (Vlocale_coding_system, &coding);
9534 coding.src_multibyte = 0;
9535 coding.dst_multibyte = 1;
9536 /* The input is converted to events, thus we can't handle
9537 composition. Anyway, there's no XIM that gives us composition
9538 information. */
9539 coding.composing = COMPOSITION_DISABLED;
9541 /* Find the display we are supposed to read input for.
9542 It's the one communicating on descriptor SD. */
9543 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9545 #if 0 /* This ought to be unnecessary; let's verify it. */
9546 #ifdef FIOSNBIO
9547 /* If available, Xlib uses FIOSNBIO to make the socket
9548 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9549 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9550 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9551 fcntl (dpyinfo->connection, F_SETFL, 0);
9552 #endif /* ! defined (FIOSNBIO) */
9553 #endif
9555 #if 0 /* This code can't be made to work, with multiple displays,
9556 and appears not to be used on any system any more.
9557 Also keyboard.c doesn't turn O_NDELAY on and off
9558 for X connections. */
9559 #ifndef SIGIO
9560 #ifndef HAVE_SELECT
9561 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9563 extern int read_alarm_should_throw;
9564 read_alarm_should_throw = 1;
9565 XPeekEvent (dpyinfo->display, &event);
9566 read_alarm_should_throw = 0;
9568 #endif /* HAVE_SELECT */
9569 #endif /* SIGIO */
9570 #endif
9572 /* For debugging, this gives a way to fake an I/O error. */
9573 if (dpyinfo == XTread_socket_fake_io_error)
9575 XTread_socket_fake_io_error = 0;
9576 x_io_error_quitter (dpyinfo->display);
9579 while (XPending (dpyinfo->display))
9581 XNextEvent (dpyinfo->display, &event);
9583 #ifdef HAVE_X_I18N
9585 /* Filter events for the current X input method.
9586 XFilterEvent returns non-zero if the input method has
9587 consumed the event. We pass the frame's X window to
9588 XFilterEvent because that's the one for which the IC
9589 was created. */
9590 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9591 event.xclient.window);
9592 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9593 break;
9595 #endif
9596 event_found = 1;
9598 switch (event.type)
9600 case ClientMessage:
9602 if (event.xclient.message_type
9603 == dpyinfo->Xatom_wm_protocols
9604 && event.xclient.format == 32)
9606 if (event.xclient.data.l[0]
9607 == dpyinfo->Xatom_wm_take_focus)
9609 /* Use x_any_window_to_frame because this
9610 could be the shell widget window
9611 if the frame has no title bar. */
9612 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9613 #ifdef HAVE_X_I18N
9614 /* Not quite sure this is needed -pd */
9615 if (f && FRAME_XIC (f))
9616 XSetICFocus (FRAME_XIC (f));
9617 #endif
9618 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9619 instructs the WM to set the input focus automatically for
9620 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9621 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9622 it has set the focus. So, XSetInputFocus below is not
9623 needed.
9625 The call to XSetInputFocus below has also caused trouble. In
9626 cases where the XSetInputFocus done by the WM and the one
9627 below are temporally close (on a fast machine), the call
9628 below can generate additional FocusIn events which confuse
9629 Emacs. */
9631 /* Since we set WM_TAKE_FOCUS, we must call
9632 XSetInputFocus explicitly. But not if f is null,
9633 since that might be an event for a deleted frame. */
9634 if (f)
9636 Display *d = event.xclient.display;
9637 /* Catch and ignore errors, in case window has been
9638 iconified by a window manager such as GWM. */
9639 int count = x_catch_errors (d);
9640 XSetInputFocus (d, event.xclient.window,
9641 /* The ICCCM says this is
9642 the only valid choice. */
9643 RevertToParent,
9644 event.xclient.data.l[1]);
9645 /* This is needed to detect the error
9646 if there is an error. */
9647 XSync (d, False);
9648 x_uncatch_errors (d, count);
9650 /* Not certain about handling scroll bars here */
9651 #endif /* 0 */
9653 else if (event.xclient.data.l[0]
9654 == dpyinfo->Xatom_wm_save_yourself)
9656 /* Save state modify the WM_COMMAND property to
9657 something which can reinstate us. This notifies
9658 the session manager, who's looking for such a
9659 PropertyNotify. Can restart processing when
9660 a keyboard or mouse event arrives. */
9661 if (numchars > 0)
9663 f = x_top_window_to_frame (dpyinfo,
9664 event.xclient.window);
9666 /* This is just so we only give real data once
9667 for a single Emacs process. */
9668 if (f == SELECTED_FRAME ())
9669 XSetCommand (FRAME_X_DISPLAY (f),
9670 event.xclient.window,
9671 initial_argv, initial_argc);
9672 else if (f)
9673 XSetCommand (FRAME_X_DISPLAY (f),
9674 event.xclient.window,
9675 0, 0);
9678 else if (event.xclient.data.l[0]
9679 == dpyinfo->Xatom_wm_delete_window)
9681 struct frame *f
9682 = x_any_window_to_frame (dpyinfo,
9683 event.xclient.window);
9685 if (f)
9687 if (numchars == 0)
9688 abort ();
9690 bufp->kind = delete_window_event;
9691 XSETFRAME (bufp->frame_or_window, f);
9692 bufp->arg = Qnil;
9693 bufp++;
9695 count += 1;
9696 numchars -= 1;
9700 else if (event.xclient.message_type
9701 == dpyinfo->Xatom_wm_configure_denied)
9704 else if (event.xclient.message_type
9705 == dpyinfo->Xatom_wm_window_moved)
9707 int new_x, new_y;
9708 struct frame *f
9709 = x_window_to_frame (dpyinfo, event.xclient.window);
9711 new_x = event.xclient.data.s[0];
9712 new_y = event.xclient.data.s[1];
9714 if (f)
9716 f->output_data.x->left_pos = new_x;
9717 f->output_data.x->top_pos = new_y;
9720 #ifdef HACK_EDITRES
9721 else if (event.xclient.message_type
9722 == dpyinfo->Xatom_editres)
9724 struct frame *f
9725 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9726 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9727 &event, NULL);
9729 #endif /* HACK_EDITRES */
9730 else if ((event.xclient.message_type
9731 == dpyinfo->Xatom_DONE)
9732 || (event.xclient.message_type
9733 == dpyinfo->Xatom_PAGE))
9735 /* Ghostview job completed. Kill it. We could
9736 reply with "Next" if we received "Page", but we
9737 currently never do because we are interested in
9738 images, only, which should have 1 page. */
9739 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9740 struct frame *f
9741 = x_window_to_frame (dpyinfo, event.xclient.window);
9742 x_kill_gs_process (pixmap, f);
9743 expose_frame (f, 0, 0, 0, 0);
9745 #ifdef USE_TOOLKIT_SCROLL_BARS
9746 /* Scroll bar callbacks send a ClientMessage from which
9747 we construct an input_event. */
9748 else if (event.xclient.message_type
9749 == dpyinfo->Xatom_Scrollbar)
9751 x_scroll_bar_to_input_event (&event, bufp);
9752 ++bufp, ++count, --numchars;
9753 goto out;
9755 #endif /* USE_TOOLKIT_SCROLL_BARS */
9756 else
9757 goto OTHER;
9759 break;
9761 case SelectionNotify:
9762 #ifdef USE_X_TOOLKIT
9763 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9764 goto OTHER;
9765 #endif /* not USE_X_TOOLKIT */
9766 x_handle_selection_notify (&event.xselection);
9767 break;
9769 case SelectionClear: /* Someone has grabbed ownership. */
9770 #ifdef USE_X_TOOLKIT
9771 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9772 goto OTHER;
9773 #endif /* USE_X_TOOLKIT */
9775 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9777 if (numchars == 0)
9778 abort ();
9780 bufp->kind = selection_clear_event;
9781 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9782 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9783 SELECTION_EVENT_TIME (bufp) = eventp->time;
9784 bufp->frame_or_window = Qnil;
9785 bufp->arg = Qnil;
9786 bufp++;
9788 count += 1;
9789 numchars -= 1;
9791 break;
9793 case SelectionRequest: /* Someone wants our selection. */
9794 #ifdef USE_X_TOOLKIT
9795 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9796 goto OTHER;
9797 #endif /* USE_X_TOOLKIT */
9798 if (x_queue_selection_requests)
9799 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9800 &event);
9801 else
9803 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9805 if (numchars == 0)
9806 abort ();
9808 bufp->kind = selection_request_event;
9809 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9810 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9811 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9812 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9813 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9814 SELECTION_EVENT_TIME (bufp) = eventp->time;
9815 bufp->frame_or_window = Qnil;
9816 bufp->arg = Qnil;
9817 bufp++;
9819 count += 1;
9820 numchars -= 1;
9822 break;
9824 case PropertyNotify:
9825 #ifdef USE_X_TOOLKIT
9826 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9827 goto OTHER;
9828 #endif /* not USE_X_TOOLKIT */
9829 x_handle_property_notify (&event.xproperty);
9830 break;
9832 case ReparentNotify:
9833 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9834 if (f)
9836 int x, y;
9837 f->output_data.x->parent_desc = event.xreparent.parent;
9838 x_real_positions (f, &x, &y);
9839 f->output_data.x->left_pos = x;
9840 f->output_data.x->top_pos = y;
9842 break;
9844 case Expose:
9845 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9846 if (f)
9848 if (f->async_visible == 0)
9850 f->async_visible = 1;
9851 f->async_iconified = 0;
9852 f->output_data.x->has_been_visible = 1;
9853 SET_FRAME_GARBAGED (f);
9855 else
9856 expose_frame (x_window_to_frame (dpyinfo,
9857 event.xexpose.window),
9858 event.xexpose.x, event.xexpose.y,
9859 event.xexpose.width, event.xexpose.height);
9861 else
9863 #ifdef USE_TOOLKIT_SCROLL_BARS
9864 /* Dispatch event to the widget. */
9865 goto OTHER;
9866 #else /* not USE_TOOLKIT_SCROLL_BARS */
9867 struct scroll_bar *bar
9868 = x_window_to_scroll_bar (event.xexpose.window);
9870 if (bar)
9871 x_scroll_bar_expose (bar, &event);
9872 #ifdef USE_X_TOOLKIT
9873 else
9874 goto OTHER;
9875 #endif /* USE_X_TOOLKIT */
9876 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9878 break;
9880 case GraphicsExpose: /* This occurs when an XCopyArea's
9881 source area was obscured or not
9882 available.*/
9883 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9884 if (f)
9886 expose_frame (f,
9887 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9888 event.xgraphicsexpose.width,
9889 event.xgraphicsexpose.height);
9891 #ifdef USE_X_TOOLKIT
9892 else
9893 goto OTHER;
9894 #endif /* USE_X_TOOLKIT */
9895 break;
9897 case NoExpose: /* This occurs when an XCopyArea's
9898 source area was completely
9899 available */
9900 break;
9902 case UnmapNotify:
9903 /* Redo the mouse-highlight after the tooltip has gone. */
9904 if (event.xmap.window == tip_window)
9906 tip_window = 0;
9907 redo_mouse_highlight ();
9910 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9911 if (f) /* F may no longer exist if
9912 the frame was deleted. */
9914 /* While a frame is unmapped, display generation is
9915 disabled; you don't want to spend time updating a
9916 display that won't ever be seen. */
9917 f->async_visible = 0;
9918 /* We can't distinguish, from the event, whether the window
9919 has become iconified or invisible. So assume, if it
9920 was previously visible, than now it is iconified.
9921 But x_make_frame_invisible clears both
9922 the visible flag and the iconified flag;
9923 and that way, we know the window is not iconified now. */
9924 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9926 f->async_iconified = 1;
9928 bufp->kind = iconify_event;
9929 XSETFRAME (bufp->frame_or_window, f);
9930 bufp->arg = Qnil;
9931 bufp++;
9932 count++;
9933 numchars--;
9936 goto OTHER;
9938 case MapNotify:
9939 if (event.xmap.window == tip_window)
9940 /* The tooltip has been drawn already. Avoid
9941 the SET_FRAME_GARBAGED below. */
9942 goto OTHER;
9944 /* We use x_top_window_to_frame because map events can
9945 come for sub-windows and they don't mean that the
9946 frame is visible. */
9947 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9948 if (f)
9950 f->async_visible = 1;
9951 f->async_iconified = 0;
9952 f->output_data.x->has_been_visible = 1;
9954 /* wait_reading_process_input will notice this and update
9955 the frame's display structures. */
9956 SET_FRAME_GARBAGED (f);
9958 if (f->iconified)
9960 bufp->kind = deiconify_event;
9961 XSETFRAME (bufp->frame_or_window, f);
9962 bufp->arg = Qnil;
9963 bufp++;
9964 count++;
9965 numchars--;
9967 else if (! NILP (Vframe_list)
9968 && ! NILP (XCDR (Vframe_list)))
9969 /* Force a redisplay sooner or later
9970 to update the frame titles
9971 in case this is the second frame. */
9972 record_asynch_buffer_change ();
9974 goto OTHER;
9976 case KeyPress:
9977 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9979 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
9980 if (f == 0)
9982 /* Scroll bars consume key events, but we want
9983 the keys to go to the scroll bar's frame. */
9984 Widget widget = XtWindowToWidget (dpyinfo->display,
9985 event.xkey.window);
9986 if (widget && XmIsScrollBar (widget))
9988 widget = XtParent (widget);
9989 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9992 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
9994 if (f != 0)
9996 KeySym keysym, orig_keysym;
9997 /* al%imercury@uunet.uu.net says that making this 81
9998 instead of 80 fixed a bug whereby meta chars made
9999 his Emacs hang.
10001 It seems that some version of XmbLookupString has
10002 a bug of not returning XBufferOverflow in
10003 status_return even if the input is too long to
10004 fit in 81 bytes. So, we must prepare sufficient
10005 bytes for copy_buffer. 513 bytes (256 chars for
10006 two-byte character set) seems to be a faily good
10007 approximation. -- 2000.8.10 handa@etl.go.jp */
10008 unsigned char copy_buffer[513];
10009 unsigned char *copy_bufptr = copy_buffer;
10010 int copy_bufsiz = sizeof (copy_buffer);
10011 int modifiers;
10013 event.xkey.state
10014 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10015 extra_keyboard_modifiers);
10016 modifiers = event.xkey.state;
10018 /* This will have to go some day... */
10020 /* make_lispy_event turns chars into control chars.
10021 Don't do it here because XLookupString is too eager. */
10022 event.xkey.state &= ~ControlMask;
10023 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10024 | dpyinfo->super_mod_mask
10025 | dpyinfo->hyper_mod_mask
10026 | dpyinfo->alt_mod_mask);
10028 /* In case Meta is ComposeCharacter,
10029 clear its status. According to Markus Ehrnsperger
10030 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10031 this enables ComposeCharacter to work whether or
10032 not it is combined with Meta. */
10033 if (modifiers & dpyinfo->meta_mod_mask)
10034 bzero (&compose_status, sizeof (compose_status));
10036 #ifdef HAVE_X_I18N
10037 if (FRAME_XIC (f))
10039 Status status_return;
10041 nbytes = XmbLookupString (FRAME_XIC (f),
10042 &event.xkey, copy_bufptr,
10043 copy_bufsiz, &keysym,
10044 &status_return);
10045 if (status_return == XBufferOverflow)
10047 copy_bufsiz = nbytes + 1;
10048 copy_bufptr = (char *) alloca (copy_bufsiz);
10049 nbytes = XmbLookupString (FRAME_XIC (f),
10050 &event.xkey, copy_bufptr,
10051 copy_bufsiz, &keysym,
10052 &status_return);
10055 if (status_return == XLookupNone)
10056 break;
10057 else if (status_return == XLookupChars)
10059 keysym = NoSymbol;
10060 modifiers = 0;
10062 else if (status_return != XLookupKeySym
10063 && status_return != XLookupBoth)
10064 abort ();
10066 else
10067 nbytes = XLookupString (&event.xkey, copy_bufptr,
10068 copy_bufsiz, &keysym,
10069 &compose_status);
10070 #else
10071 nbytes = XLookupString (&event.xkey, copy_bufptr,
10072 copy_bufsiz, &keysym,
10073 &compose_status);
10074 #endif
10076 orig_keysym = keysym;
10078 if (numchars > 1)
10080 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10081 || keysym == XK_Delete
10082 #ifdef XK_ISO_Left_Tab
10083 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10084 #endif
10085 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10086 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10087 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10088 #ifdef HPUX
10089 /* This recognizes the "extended function keys".
10090 It seems there's no cleaner way.
10091 Test IsModifierKey to avoid handling mode_switch
10092 incorrectly. */
10093 || ((unsigned) (keysym) >= XK_Select
10094 && (unsigned)(keysym) < XK_KP_Space)
10095 #endif
10096 #ifdef XK_dead_circumflex
10097 || orig_keysym == XK_dead_circumflex
10098 #endif
10099 #ifdef XK_dead_grave
10100 || orig_keysym == XK_dead_grave
10101 #endif
10102 #ifdef XK_dead_tilde
10103 || orig_keysym == XK_dead_tilde
10104 #endif
10105 #ifdef XK_dead_diaeresis
10106 || orig_keysym == XK_dead_diaeresis
10107 #endif
10108 #ifdef XK_dead_macron
10109 || orig_keysym == XK_dead_macron
10110 #endif
10111 #ifdef XK_dead_degree
10112 || orig_keysym == XK_dead_degree
10113 #endif
10114 #ifdef XK_dead_acute
10115 || orig_keysym == XK_dead_acute
10116 #endif
10117 #ifdef XK_dead_cedilla
10118 || orig_keysym == XK_dead_cedilla
10119 #endif
10120 #ifdef XK_dead_breve
10121 || orig_keysym == XK_dead_breve
10122 #endif
10123 #ifdef XK_dead_ogonek
10124 || orig_keysym == XK_dead_ogonek
10125 #endif
10126 #ifdef XK_dead_caron
10127 || orig_keysym == XK_dead_caron
10128 #endif
10129 #ifdef XK_dead_doubleacute
10130 || orig_keysym == XK_dead_doubleacute
10131 #endif
10132 #ifdef XK_dead_abovedot
10133 || orig_keysym == XK_dead_abovedot
10134 #endif
10135 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10136 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10137 /* Any "vendor-specific" key is ok. */
10138 || (orig_keysym & (1 << 28)))
10139 && ! (IsModifierKey (orig_keysym)
10140 #ifndef HAVE_X11R5
10141 #ifdef XK_Mode_switch
10142 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10143 #endif
10144 #ifdef XK_Num_Lock
10145 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10146 #endif
10147 #endif /* not HAVE_X11R5 */
10150 if (temp_index == sizeof temp_buffer / sizeof (short))
10151 temp_index = 0;
10152 temp_buffer[temp_index++] = keysym;
10153 bufp->kind = non_ascii_keystroke;
10154 bufp->code = keysym;
10155 XSETFRAME (bufp->frame_or_window, f);
10156 bufp->arg = Qnil;
10157 bufp->modifiers
10158 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10159 modifiers);
10160 bufp->timestamp = event.xkey.time;
10161 bufp++;
10162 count++;
10163 numchars--;
10165 else if (numchars > nbytes)
10167 register int i;
10168 register int c;
10169 int nchars, len;
10171 for (i = 0; i < nbytes; i++)
10173 if (temp_index == (sizeof temp_buffer
10174 / sizeof (short)))
10175 temp_index = 0;
10176 temp_buffer[temp_index++] = copy_bufptr[i];
10179 if (/* If the event is not from XIM, */
10180 event.xkey.keycode != 0
10181 /* or the current locale doesn't request
10182 decoding of the intup data, ... */
10183 || coding.type == coding_type_raw_text
10184 || coding.type == coding_type_no_conversion)
10186 /* ... we can use the input data as is. */
10187 nchars = nbytes;
10189 else
10191 /* We have to decode the input data. */
10192 int require;
10193 unsigned char *p;
10195 require = decoding_buffer_size (&coding, nbytes);
10196 p = (unsigned char *) alloca (require);
10197 coding.mode |= CODING_MODE_LAST_BLOCK;
10198 decode_coding (&coding, copy_bufptr, p,
10199 nbytes, require);
10200 nbytes = coding.produced;
10201 nchars = coding.produced_char;
10202 copy_bufptr = p;
10205 /* Convert the input data to a sequence of
10206 character events. */
10207 for (i = 0; i < nbytes; i += len)
10209 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10210 nbytes - i, len);
10211 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10212 ? ascii_keystroke
10213 : multibyte_char_keystroke);
10214 bufp->code = c;
10215 XSETFRAME (bufp->frame_or_window, f);
10216 bufp->arg = Qnil;
10217 bufp->modifiers
10218 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10219 modifiers);
10220 bufp->timestamp = event.xkey.time;
10221 bufp++;
10224 count += nchars;
10225 numchars -= nchars;
10227 if (keysym == NoSymbol)
10228 break;
10230 else
10231 abort ();
10233 else
10234 abort ();
10236 #ifdef HAVE_X_I18N
10237 /* Don't dispatch this event since XtDispatchEvent calls
10238 XFilterEvent, and two calls in a row may freeze the
10239 client. */
10240 break;
10241 #else
10242 goto OTHER;
10243 #endif
10245 case KeyRelease:
10246 #ifdef HAVE_X_I18N
10247 /* Don't dispatch this event since XtDispatchEvent calls
10248 XFilterEvent, and two calls in a row may freeze the
10249 client. */
10250 break;
10251 #else
10252 goto OTHER;
10253 #endif
10255 /* Here's a possible interpretation of the whole
10256 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10257 you get a FocusIn event, you have to get a FocusOut
10258 event before you relinquish the focus. If you
10259 haven't received a FocusIn event, then a mere
10260 LeaveNotify is enough to free you. */
10262 case EnterNotify:
10264 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10266 if (event.xcrossing.focus)
10268 /* Avoid nasty pop/raise loops. */
10269 if (f && (!(f->auto_raise)
10270 || !(f->auto_lower)
10271 || (event.xcrossing.time - enter_timestamp) > 500))
10273 x_new_focus_frame (dpyinfo, f);
10274 enter_timestamp = event.xcrossing.time;
10277 else if (f == dpyinfo->x_focus_frame)
10278 x_new_focus_frame (dpyinfo, 0);
10280 /* EnterNotify counts as mouse movement,
10281 so update things that depend on mouse position. */
10282 if (f && !f->output_data.x->hourglass_p)
10283 note_mouse_movement (f, &event.xmotion);
10284 goto OTHER;
10287 case FocusIn:
10288 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10289 if (event.xfocus.detail != NotifyPointer)
10290 dpyinfo->x_focus_event_frame = f;
10291 if (f)
10293 x_new_focus_frame (dpyinfo, f);
10295 /* Don't stop displaying the initial startup message
10296 for a switch-frame event we don't need. */
10297 if (GC_NILP (Vterminal_frame)
10298 && GC_CONSP (Vframe_list)
10299 && !GC_NILP (XCDR (Vframe_list)))
10301 bufp->kind = FOCUS_IN_EVENT;
10302 XSETFRAME (bufp->frame_or_window, f);
10303 bufp->arg = Qnil;
10304 ++bufp, ++count, --numchars;
10308 #ifdef HAVE_X_I18N
10309 if (f && FRAME_XIC (f))
10310 XSetICFocus (FRAME_XIC (f));
10311 #endif
10313 goto OTHER;
10315 case LeaveNotify:
10316 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10317 if (f)
10319 if (f == dpyinfo->mouse_face_mouse_frame)
10321 /* If we move outside the frame, then we're
10322 certainly no longer on any text in the frame. */
10323 clear_mouse_face (dpyinfo);
10324 dpyinfo->mouse_face_mouse_frame = 0;
10327 /* Generate a nil HELP_EVENT to cancel a help-echo.
10328 Do it only if there's something to cancel.
10329 Otherwise, the startup message is cleared when
10330 the mouse leaves the frame. */
10331 if (any_help_event_p)
10333 Lisp_Object frame;
10334 int n;
10336 XSETFRAME (frame, f);
10337 help_echo = Qnil;
10338 n = gen_help_event (bufp, numchars,
10339 Qnil, frame, Qnil, Qnil, 0);
10340 bufp += n, count += n, numchars -= n;
10343 if (event.xcrossing.focus)
10344 x_mouse_leave (dpyinfo);
10345 else
10347 if (f == dpyinfo->x_focus_event_frame)
10348 dpyinfo->x_focus_event_frame = 0;
10349 if (f == dpyinfo->x_focus_frame)
10350 x_new_focus_frame (dpyinfo, 0);
10353 goto OTHER;
10355 case FocusOut:
10356 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10357 if (event.xfocus.detail != NotifyPointer
10358 && f == dpyinfo->x_focus_event_frame)
10359 dpyinfo->x_focus_event_frame = 0;
10360 if (f && f == dpyinfo->x_focus_frame)
10361 x_new_focus_frame (dpyinfo, 0);
10363 #ifdef HAVE_X_I18N
10364 if (f && FRAME_XIC (f))
10365 XUnsetICFocus (FRAME_XIC (f));
10366 #endif
10368 goto OTHER;
10370 case MotionNotify:
10372 previous_help_echo = help_echo;
10373 help_echo = help_echo_object = help_echo_window = Qnil;
10374 help_echo_pos = -1;
10376 if (dpyinfo->grabbed && last_mouse_frame
10377 && FRAME_LIVE_P (last_mouse_frame))
10378 f = last_mouse_frame;
10379 else
10380 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10382 if (f)
10383 note_mouse_movement (f, &event.xmotion);
10384 else
10386 #ifndef USE_TOOLKIT_SCROLL_BARS
10387 struct scroll_bar *bar
10388 = x_window_to_scroll_bar (event.xmotion.window);
10390 if (bar)
10391 x_scroll_bar_note_movement (bar, &event);
10392 #endif /* USE_TOOLKIT_SCROLL_BARS */
10394 /* If we move outside the frame, then we're
10395 certainly no longer on any text in the frame. */
10396 clear_mouse_face (dpyinfo);
10399 /* If the contents of the global variable help_echo
10400 has changed, generate a HELP_EVENT. */
10401 if (!NILP (help_echo)
10402 || !NILP (previous_help_echo))
10404 Lisp_Object frame;
10405 int n;
10407 if (f)
10408 XSETFRAME (frame, f);
10409 else
10410 frame = Qnil;
10412 any_help_event_p = 1;
10413 n = gen_help_event (bufp, numchars, help_echo, frame,
10414 help_echo_window, help_echo_object,
10415 help_echo_pos);
10416 bufp += n, count += n, numchars -= n;
10419 goto OTHER;
10422 case ConfigureNotify:
10423 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10424 if (f)
10426 #ifndef USE_X_TOOLKIT
10427 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10428 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10430 /* In the toolkit version, change_frame_size
10431 is called by the code that handles resizing
10432 of the EmacsFrame widget. */
10434 /* Even if the number of character rows and columns has
10435 not changed, the font size may have changed, so we need
10436 to check the pixel dimensions as well. */
10437 if (columns != f->width
10438 || rows != f->height
10439 || event.xconfigure.width != f->output_data.x->pixel_width
10440 || event.xconfigure.height != f->output_data.x->pixel_height)
10442 change_frame_size (f, rows, columns, 0, 1, 0);
10443 SET_FRAME_GARBAGED (f);
10444 cancel_mouse_face (f);
10446 #endif
10448 f->output_data.x->pixel_width = event.xconfigure.width;
10449 f->output_data.x->pixel_height = event.xconfigure.height;
10451 /* What we have now is the position of Emacs's own window.
10452 Convert that to the position of the window manager window. */
10453 x_real_positions (f, &f->output_data.x->left_pos,
10454 &f->output_data.x->top_pos);
10456 #ifdef HAVE_X_I18N
10457 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10458 xic_set_statusarea (f);
10459 #endif
10461 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10463 /* Since the WM decorations come below top_pos now,
10464 we must put them below top_pos in the future. */
10465 f->output_data.x->win_gravity = NorthWestGravity;
10466 x_wm_set_size_hint (f, (long) 0, 0);
10468 #ifdef USE_MOTIF
10469 /* Some window managers pass (0,0) as the location of
10470 the window, and the Motif event handler stores it
10471 in the emacs widget, which messes up Motif menus. */
10472 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10474 event.xconfigure.x = f->output_data.x->widget->core.x;
10475 event.xconfigure.y = f->output_data.x->widget->core.y;
10477 #endif /* USE_MOTIF */
10479 goto OTHER;
10481 case ButtonPress:
10482 case ButtonRelease:
10484 /* If we decide we want to generate an event to be seen
10485 by the rest of Emacs, we put it here. */
10486 struct input_event emacs_event;
10487 int tool_bar_p = 0;
10489 emacs_event.kind = no_event;
10490 bzero (&compose_status, sizeof (compose_status));
10492 if (dpyinfo->grabbed
10493 && last_mouse_frame
10494 && FRAME_LIVE_P (last_mouse_frame))
10495 f = last_mouse_frame;
10496 else
10497 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10499 if (f)
10501 /* Is this in the tool-bar? */
10502 if (WINDOWP (f->tool_bar_window)
10503 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10505 Lisp_Object window;
10506 int p, x, y;
10508 x = event.xbutton.x;
10509 y = event.xbutton.y;
10511 /* Set x and y. */
10512 window = window_from_coordinates (f, x, y, &p, 1);
10513 if (EQ (window, f->tool_bar_window))
10515 x_handle_tool_bar_click (f, &event.xbutton);
10516 tool_bar_p = 1;
10520 if (!tool_bar_p)
10521 if (!dpyinfo->x_focus_frame
10522 || f == dpyinfo->x_focus_frame)
10523 construct_mouse_click (&emacs_event, &event, f);
10525 else
10527 #ifndef USE_TOOLKIT_SCROLL_BARS
10528 struct scroll_bar *bar
10529 = x_window_to_scroll_bar (event.xbutton.window);
10531 if (bar)
10532 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10533 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10536 if (event.type == ButtonPress)
10538 dpyinfo->grabbed |= (1 << event.xbutton.button);
10539 last_mouse_frame = f;
10540 /* Ignore any mouse motion that happened
10541 before this event; any subsequent mouse-movement
10542 Emacs events should reflect only motion after
10543 the ButtonPress. */
10544 if (f != 0)
10545 f->mouse_moved = 0;
10547 if (!tool_bar_p)
10548 last_tool_bar_item = -1;
10550 else
10552 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10555 if (numchars >= 1 && emacs_event.kind != no_event)
10557 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10558 bufp++;
10559 count++;
10560 numchars--;
10563 #ifdef USE_X_TOOLKIT
10564 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10565 /* For a down-event in the menu bar,
10566 don't pass it to Xt right now.
10567 Instead, save it away
10568 and we will pass it to Xt from kbd_buffer_get_event.
10569 That way, we can run some Lisp code first. */
10570 if (f && event.type == ButtonPress
10571 /* Verify the event is really within the menu bar
10572 and not just sent to it due to grabbing. */
10573 && event.xbutton.x >= 0
10574 && event.xbutton.x < f->output_data.x->pixel_width
10575 && event.xbutton.y >= 0
10576 && event.xbutton.y < f->output_data.x->menubar_height
10577 && event.xbutton.same_screen)
10579 SET_SAVED_BUTTON_EVENT;
10580 XSETFRAME (last_mouse_press_frame, f);
10582 else if (event.type == ButtonPress)
10584 last_mouse_press_frame = Qnil;
10585 goto OTHER;
10588 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10589 but I am trying to be cautious. */
10590 else if (event.type == ButtonRelease)
10592 if (!NILP (last_mouse_press_frame))
10594 f = XFRAME (last_mouse_press_frame);
10595 if (f->output_data.x)
10596 SET_SAVED_BUTTON_EVENT;
10598 else
10599 goto OTHER;
10601 #endif /* USE_MOTIF */
10602 else
10603 goto OTHER;
10604 #endif /* USE_X_TOOLKIT */
10606 break;
10608 case CirculateNotify:
10609 goto OTHER;
10611 case CirculateRequest:
10612 goto OTHER;
10614 case VisibilityNotify:
10615 goto OTHER;
10617 case MappingNotify:
10618 /* Someone has changed the keyboard mapping - update the
10619 local cache. */
10620 switch (event.xmapping.request)
10622 case MappingModifier:
10623 x_find_modifier_meanings (dpyinfo);
10624 /* This is meant to fall through. */
10625 case MappingKeyboard:
10626 XRefreshKeyboardMapping (&event.xmapping);
10628 goto OTHER;
10630 default:
10631 OTHER:
10632 #ifdef USE_X_TOOLKIT
10633 BLOCK_INPUT;
10634 XtDispatchEvent (&event);
10635 UNBLOCK_INPUT;
10636 #endif /* USE_X_TOOLKIT */
10637 break;
10642 out:;
10644 /* On some systems, an X bug causes Emacs to get no more events
10645 when the window is destroyed. Detect that. (1994.) */
10646 if (! event_found)
10648 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10649 One XNOOP in 100 loops will make Emacs terminate.
10650 B. Bretthauer, 1994 */
10651 x_noop_count++;
10652 if (x_noop_count >= 100)
10654 x_noop_count=0;
10656 if (next_noop_dpyinfo == 0)
10657 next_noop_dpyinfo = x_display_list;
10659 XNoOp (next_noop_dpyinfo->display);
10661 /* Each time we get here, cycle through the displays now open. */
10662 next_noop_dpyinfo = next_noop_dpyinfo->next;
10666 /* If the focus was just given to an auto-raising frame,
10667 raise it now. */
10668 /* ??? This ought to be able to handle more than one such frame. */
10669 if (pending_autoraise_frame)
10671 x_raise_frame (pending_autoraise_frame);
10672 pending_autoraise_frame = 0;
10675 UNBLOCK_INPUT;
10676 --handling_signal;
10677 return count;
10683 /***********************************************************************
10684 Text Cursor
10685 ***********************************************************************/
10687 /* Note if the text cursor of window W has been overwritten by a
10688 drawing operation that outputs N glyphs starting at HPOS in the
10689 line given by output_cursor.vpos. N < 0 means all the rest of the
10690 line after HPOS has been written. */
10692 static void
10693 note_overwritten_text_cursor (w, hpos, n)
10694 struct window *w;
10695 int hpos, n;
10697 if (updated_area == TEXT_AREA
10698 && output_cursor.vpos == w->phys_cursor.vpos
10699 && hpos <= w->phys_cursor.hpos
10700 && (n < 0
10701 || hpos + n > w->phys_cursor.hpos))
10702 w->phys_cursor_on_p = 0;
10706 /* Set clipping for output in glyph row ROW. W is the window in which
10707 we operate. GC is the graphics context to set clipping in.
10708 WHOLE_LINE_P non-zero means include the areas used for truncation
10709 mark display and alike in the clipping rectangle.
10711 ROW may be a text row or, e.g., a mode line. Text rows must be
10712 clipped to the interior of the window dedicated to text display,
10713 mode lines must be clipped to the whole window. */
10715 static void
10716 x_clip_to_row (w, row, gc, whole_line_p)
10717 struct window *w;
10718 struct glyph_row *row;
10719 GC gc;
10720 int whole_line_p;
10722 struct frame *f = XFRAME (WINDOW_FRAME (w));
10723 XRectangle clip_rect;
10724 int window_x, window_y, window_width, window_height;
10726 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10728 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10729 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10730 clip_rect.y = max (clip_rect.y, window_y);
10731 clip_rect.width = window_width;
10732 clip_rect.height = row->visible_height;
10734 /* If clipping to the whole line, including trunc marks, extend
10735 the rectangle to the left and increase its width. */
10736 if (whole_line_p)
10738 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10739 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10742 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10746 /* Draw a hollow box cursor on window W in glyph row ROW. */
10748 static void
10749 x_draw_hollow_cursor (w, row)
10750 struct window *w;
10751 struct glyph_row *row;
10753 struct frame *f = XFRAME (WINDOW_FRAME (w));
10754 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10755 Display *dpy = FRAME_X_DISPLAY (f);
10756 int x, y, wd, h;
10757 XGCValues xgcv;
10758 struct glyph *cursor_glyph;
10759 GC gc;
10761 /* Compute frame-relative coordinates from window-relative
10762 coordinates. */
10763 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10764 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10765 + row->ascent - w->phys_cursor_ascent);
10766 h = row->height - 1;
10768 /* Get the glyph the cursor is on. If we can't tell because
10769 the current matrix is invalid or such, give up. */
10770 cursor_glyph = get_phys_cursor_glyph (w);
10771 if (cursor_glyph == NULL)
10772 return;
10774 /* Compute the width of the rectangle to draw. If on a stretch
10775 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10776 rectangle as wide as the glyph, but use a canonical character
10777 width instead. */
10778 wd = cursor_glyph->pixel_width - 1;
10779 if (cursor_glyph->type == STRETCH_GLYPH
10780 && !x_stretch_cursor_p)
10781 wd = min (CANON_X_UNIT (f), wd);
10783 /* The foreground of cursor_gc is typically the same as the normal
10784 background color, which can cause the cursor box to be invisible. */
10785 xgcv.foreground = f->output_data.x->cursor_pixel;
10786 if (dpyinfo->scratch_cursor_gc)
10787 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10788 else
10789 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10790 GCForeground, &xgcv);
10791 gc = dpyinfo->scratch_cursor_gc;
10793 /* Set clipping, draw the rectangle, and reset clipping again. */
10794 x_clip_to_row (w, row, gc, 0);
10795 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10796 XSetClipMask (dpy, gc, None);
10800 /* Draw a bar cursor on window W in glyph row ROW.
10802 Implementation note: One would like to draw a bar cursor with an
10803 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10804 Unfortunately, I didn't find a font yet that has this property set.
10805 --gerd. */
10807 static void
10808 x_draw_bar_cursor (w, row, width)
10809 struct window *w;
10810 struct glyph_row *row;
10811 int width;
10813 struct frame *f = XFRAME (w->frame);
10814 struct glyph *cursor_glyph;
10815 GC gc;
10816 int x;
10817 unsigned long mask;
10818 XGCValues xgcv;
10819 Display *dpy;
10820 Window window;
10822 /* If cursor is out of bounds, don't draw garbage. This can happen
10823 in mini-buffer windows when switching between echo area glyphs
10824 and mini-buffer. */
10825 cursor_glyph = get_phys_cursor_glyph (w);
10826 if (cursor_glyph == NULL)
10827 return;
10829 /* If on an image, draw like a normal cursor. That's usually better
10830 visible than drawing a bar, esp. if the image is large so that
10831 the bar might not be in the window. */
10832 if (cursor_glyph->type == IMAGE_GLYPH)
10834 struct glyph_row *row;
10835 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10836 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10838 else
10840 xgcv.background = f->output_data.x->cursor_pixel;
10841 xgcv.foreground = f->output_data.x->cursor_pixel;
10842 xgcv.graphics_exposures = 0;
10843 mask = GCForeground | GCBackground | GCGraphicsExposures;
10844 dpy = FRAME_X_DISPLAY (f);
10845 window = FRAME_X_WINDOW (f);
10846 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10848 if (gc)
10849 XChangeGC (dpy, gc, mask, &xgcv);
10850 else
10852 gc = XCreateGC (dpy, window, mask, &xgcv);
10853 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10856 if (width < 0)
10857 width = f->output_data.x->cursor_width;
10859 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10860 x_clip_to_row (w, row, gc, 0);
10861 XFillRectangle (dpy, window, gc,
10863 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10864 min (cursor_glyph->pixel_width, width),
10865 row->height);
10866 XSetClipMask (dpy, gc, None);
10871 /* Clear the cursor of window W to background color, and mark the
10872 cursor as not shown. This is used when the text where the cursor
10873 is is about to be rewritten. */
10875 static void
10876 x_clear_cursor (w)
10877 struct window *w;
10879 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10880 x_update_window_cursor (w, 0);
10884 /* Draw the cursor glyph of window W in glyph row ROW. See the
10885 comment of x_draw_glyphs for the meaning of HL. */
10887 static void
10888 x_draw_phys_cursor_glyph (w, row, hl)
10889 struct window *w;
10890 struct glyph_row *row;
10891 enum draw_glyphs_face hl;
10893 /* If cursor hpos is out of bounds, don't draw garbage. This can
10894 happen in mini-buffer windows when switching between echo area
10895 glyphs and mini-buffer. */
10896 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10898 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10899 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10900 hl, 0, 0, 0);
10902 /* When we erase the cursor, and ROW is overlapped by other
10903 rows, make sure that these overlapping parts of other rows
10904 are redrawn. */
10905 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10907 if (row > w->current_matrix->rows
10908 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10909 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10911 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10912 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10913 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10919 /* Erase the image of a cursor of window W from the screen. */
10921 static void
10922 x_erase_phys_cursor (w)
10923 struct window *w;
10925 struct frame *f = XFRAME (w->frame);
10926 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10927 int hpos = w->phys_cursor.hpos;
10928 int vpos = w->phys_cursor.vpos;
10929 int mouse_face_here_p = 0;
10930 struct glyph_matrix *active_glyphs = w->current_matrix;
10931 struct glyph_row *cursor_row;
10932 struct glyph *cursor_glyph;
10933 enum draw_glyphs_face hl;
10935 /* No cursor displayed or row invalidated => nothing to do on the
10936 screen. */
10937 if (w->phys_cursor_type == NO_CURSOR)
10938 goto mark_cursor_off;
10940 /* VPOS >= active_glyphs->nrows means that window has been resized.
10941 Don't bother to erase the cursor. */
10942 if (vpos >= active_glyphs->nrows)
10943 goto mark_cursor_off;
10945 /* If row containing cursor is marked invalid, there is nothing we
10946 can do. */
10947 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10948 if (!cursor_row->enabled_p)
10949 goto mark_cursor_off;
10951 /* This can happen when the new row is shorter than the old one.
10952 In this case, either x_draw_glyphs or clear_end_of_line
10953 should have cleared the cursor. Note that we wouldn't be
10954 able to erase the cursor in this case because we don't have a
10955 cursor glyph at hand. */
10956 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10957 goto mark_cursor_off;
10959 /* If the cursor is in the mouse face area, redisplay that when
10960 we clear the cursor. */
10961 if (! NILP (dpyinfo->mouse_face_window)
10962 && w == XWINDOW (dpyinfo->mouse_face_window)
10963 && (vpos > dpyinfo->mouse_face_beg_row
10964 || (vpos == dpyinfo->mouse_face_beg_row
10965 && hpos >= dpyinfo->mouse_face_beg_col))
10966 && (vpos < dpyinfo->mouse_face_end_row
10967 || (vpos == dpyinfo->mouse_face_end_row
10968 && hpos < dpyinfo->mouse_face_end_col))
10969 /* Don't redraw the cursor's spot in mouse face if it is at the
10970 end of a line (on a newline). The cursor appears there, but
10971 mouse highlighting does not. */
10972 && cursor_row->used[TEXT_AREA] > hpos)
10973 mouse_face_here_p = 1;
10975 /* Maybe clear the display under the cursor. */
10976 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10978 int x;
10979 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10981 cursor_glyph = get_phys_cursor_glyph (w);
10982 if (cursor_glyph == NULL)
10983 goto mark_cursor_off;
10985 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10987 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10989 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10990 cursor_row->y)),
10991 cursor_glyph->pixel_width,
10992 cursor_row->visible_height,
10993 False);
10996 /* Erase the cursor by redrawing the character underneath it. */
10997 if (mouse_face_here_p)
10998 hl = DRAW_MOUSE_FACE;
10999 else if (cursor_row->inverse_p)
11000 hl = DRAW_INVERSE_VIDEO;
11001 else
11002 hl = DRAW_NORMAL_TEXT;
11003 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11005 mark_cursor_off:
11006 w->phys_cursor_on_p = 0;
11007 w->phys_cursor_type = NO_CURSOR;
11011 /* Display or clear cursor of window W. If ON is zero, clear the
11012 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11013 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11015 void
11016 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11017 struct window *w;
11018 int on, hpos, vpos, x, y;
11020 struct frame *f = XFRAME (w->frame);
11021 int new_cursor_type;
11022 int new_cursor_width;
11023 struct glyph_matrix *current_glyphs;
11024 struct glyph_row *glyph_row;
11025 struct glyph *glyph;
11027 /* This is pointless on invisible frames, and dangerous on garbaged
11028 windows and frames; in the latter case, the frame or window may
11029 be in the midst of changing its size, and x and y may be off the
11030 window. */
11031 if (! FRAME_VISIBLE_P (f)
11032 || FRAME_GARBAGED_P (f)
11033 || vpos >= w->current_matrix->nrows
11034 || hpos >= w->current_matrix->matrix_w)
11035 return;
11037 /* If cursor is off and we want it off, return quickly. */
11038 if (!on && !w->phys_cursor_on_p)
11039 return;
11041 current_glyphs = w->current_matrix;
11042 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11043 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11045 /* If cursor row is not enabled, we don't really know where to
11046 display the cursor. */
11047 if (!glyph_row->enabled_p)
11049 w->phys_cursor_on_p = 0;
11050 return;
11053 xassert (interrupt_input_blocked);
11055 /* Set new_cursor_type to the cursor we want to be displayed. In a
11056 mini-buffer window, we want the cursor only to appear if we are
11057 reading input from this window. For the selected window, we want
11058 the cursor type given by the frame parameter. If explicitly
11059 marked off, draw no cursor. In all other cases, we want a hollow
11060 box cursor. */
11061 new_cursor_width = -1;
11062 if (cursor_in_echo_area
11063 && FRAME_HAS_MINIBUF_P (f)
11064 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11066 if (w == XWINDOW (echo_area_window))
11067 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11068 else
11069 new_cursor_type = HOLLOW_BOX_CURSOR;
11071 else
11073 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11074 || w != XWINDOW (f->selected_window))
11076 extern int cursor_in_non_selected_windows;
11078 if (MINI_WINDOW_P (w)
11079 || !cursor_in_non_selected_windows
11080 || NILP (XBUFFER (w->buffer)->cursor_type))
11081 new_cursor_type = NO_CURSOR;
11082 else
11083 new_cursor_type = HOLLOW_BOX_CURSOR;
11085 else if (w->cursor_off_p)
11086 new_cursor_type = NO_CURSOR;
11087 else
11089 struct buffer *b = XBUFFER (w->buffer);
11091 if (EQ (b->cursor_type, Qt))
11092 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11093 else
11094 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11095 &new_cursor_width);
11099 /* If cursor is currently being shown and we don't want it to be or
11100 it is in the wrong place, or the cursor type is not what we want,
11101 erase it. */
11102 if (w->phys_cursor_on_p
11103 && (!on
11104 || w->phys_cursor.x != x
11105 || w->phys_cursor.y != y
11106 || new_cursor_type != w->phys_cursor_type))
11107 x_erase_phys_cursor (w);
11109 /* If the cursor is now invisible and we want it to be visible,
11110 display it. */
11111 if (on && !w->phys_cursor_on_p)
11113 w->phys_cursor_ascent = glyph_row->ascent;
11114 w->phys_cursor_height = glyph_row->height;
11116 /* Set phys_cursor_.* before x_draw_.* is called because some
11117 of them may need the information. */
11118 w->phys_cursor.x = x;
11119 w->phys_cursor.y = glyph_row->y;
11120 w->phys_cursor.hpos = hpos;
11121 w->phys_cursor.vpos = vpos;
11122 w->phys_cursor_type = new_cursor_type;
11123 w->phys_cursor_on_p = 1;
11125 switch (new_cursor_type)
11127 case HOLLOW_BOX_CURSOR:
11128 x_draw_hollow_cursor (w, glyph_row);
11129 break;
11131 case FILLED_BOX_CURSOR:
11132 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11133 break;
11135 case BAR_CURSOR:
11136 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11137 break;
11139 case NO_CURSOR:
11140 break;
11142 default:
11143 abort ();
11146 #ifdef HAVE_X_I18N
11147 if (w == XWINDOW (f->selected_window))
11148 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11149 xic_set_preeditarea (w, x, y);
11150 #endif
11153 #ifndef XFlush
11154 if (updating_frame != f)
11155 XFlush (FRAME_X_DISPLAY (f));
11156 #endif
11160 /* Display the cursor on window W, or clear it. X and Y are window
11161 relative pixel coordinates. HPOS and VPOS are glyph matrix
11162 positions. If W is not the selected window, display a hollow
11163 cursor. ON non-zero means display the cursor at X, Y which
11164 correspond to HPOS, VPOS, otherwise it is cleared. */
11166 void
11167 x_display_cursor (w, on, hpos, vpos, x, y)
11168 struct window *w;
11169 int on, hpos, vpos, x, y;
11171 BLOCK_INPUT;
11172 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11173 UNBLOCK_INPUT;
11177 /* Display the cursor on window W, or clear it, according to ON_P.
11178 Don't change the cursor's position. */
11180 void
11181 x_update_cursor (f, on_p)
11182 struct frame *f;
11184 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11188 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11189 in the window tree rooted at W. */
11191 static void
11192 x_update_cursor_in_window_tree (w, on_p)
11193 struct window *w;
11194 int on_p;
11196 while (w)
11198 if (!NILP (w->hchild))
11199 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11200 else if (!NILP (w->vchild))
11201 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11202 else
11203 x_update_window_cursor (w, on_p);
11205 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11210 /* Switch the display of W's cursor on or off, according to the value
11211 of ON. */
11213 static void
11214 x_update_window_cursor (w, on)
11215 struct window *w;
11216 int on;
11218 /* Don't update cursor in windows whose frame is in the process
11219 of being deleted. */
11220 if (w->current_matrix)
11222 BLOCK_INPUT;
11223 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11224 w->phys_cursor.x, w->phys_cursor.y);
11225 UNBLOCK_INPUT;
11232 /* Icons. */
11234 /* Refresh bitmap kitchen sink icon for frame F
11235 when we get an expose event for it. */
11237 void
11238 refreshicon (f)
11239 struct frame *f;
11241 /* Normally, the window manager handles this function. */
11244 /* Make the x-window of frame F use the gnu icon bitmap. */
11247 x_bitmap_icon (f, file)
11248 struct frame *f;
11249 Lisp_Object file;
11251 int bitmap_id;
11253 if (FRAME_X_WINDOW (f) == 0)
11254 return 1;
11256 /* Free up our existing icon bitmap if any. */
11257 if (f->output_data.x->icon_bitmap > 0)
11258 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11259 f->output_data.x->icon_bitmap = 0;
11261 if (STRINGP (file))
11262 bitmap_id = x_create_bitmap_from_file (f, file);
11263 else
11265 /* Create the GNU bitmap if necessary. */
11266 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11267 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11268 = x_create_bitmap_from_data (f, gnu_bits,
11269 gnu_width, gnu_height);
11271 /* The first time we create the GNU bitmap,
11272 this increments the ref-count one extra time.
11273 As a result, the GNU bitmap is never freed.
11274 That way, we don't have to worry about allocating it again. */
11275 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11277 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11280 x_wm_set_icon_pixmap (f, bitmap_id);
11281 f->output_data.x->icon_bitmap = bitmap_id;
11283 return 0;
11287 /* Make the x-window of frame F use a rectangle with text.
11288 Use ICON_NAME as the text. */
11291 x_text_icon (f, icon_name)
11292 struct frame *f;
11293 char *icon_name;
11295 if (FRAME_X_WINDOW (f) == 0)
11296 return 1;
11298 #ifdef HAVE_X11R4
11300 XTextProperty text;
11301 text.value = (unsigned char *) icon_name;
11302 text.encoding = XA_STRING;
11303 text.format = 8;
11304 text.nitems = strlen (icon_name);
11305 #ifdef USE_X_TOOLKIT
11306 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11307 &text);
11308 #else /* not USE_X_TOOLKIT */
11309 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11310 #endif /* not USE_X_TOOLKIT */
11312 #else /* not HAVE_X11R4 */
11313 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11314 #endif /* not HAVE_X11R4 */
11316 if (f->output_data.x->icon_bitmap > 0)
11317 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11318 f->output_data.x->icon_bitmap = 0;
11319 x_wm_set_icon_pixmap (f, 0);
11321 return 0;
11324 #define X_ERROR_MESSAGE_SIZE 200
11326 /* If non-nil, this should be a string.
11327 It means catch X errors and store the error message in this string. */
11329 static Lisp_Object x_error_message_string;
11331 /* An X error handler which stores the error message in
11332 x_error_message_string. This is called from x_error_handler if
11333 x_catch_errors is in effect. */
11335 static void
11336 x_error_catcher (display, error)
11337 Display *display;
11338 XErrorEvent *error;
11340 XGetErrorText (display, error->error_code,
11341 XSTRING (x_error_message_string)->data,
11342 X_ERROR_MESSAGE_SIZE);
11345 /* Begin trapping X errors for display DPY. Actually we trap X errors
11346 for all displays, but DPY should be the display you are actually
11347 operating on.
11349 After calling this function, X protocol errors no longer cause
11350 Emacs to exit; instead, they are recorded in the string
11351 stored in x_error_message_string.
11353 Calling x_check_errors signals an Emacs error if an X error has
11354 occurred since the last call to x_catch_errors or x_check_errors.
11356 Calling x_uncatch_errors resumes the normal error handling. */
11358 void x_check_errors ();
11359 static Lisp_Object x_catch_errors_unwind ();
11362 x_catch_errors (dpy)
11363 Display *dpy;
11365 int count = specpdl_ptr - specpdl;
11367 /* Make sure any errors from previous requests have been dealt with. */
11368 XSync (dpy, False);
11370 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11372 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11373 XSTRING (x_error_message_string)->data[0] = 0;
11375 return count;
11378 /* Unbind the binding that we made to check for X errors. */
11380 static Lisp_Object
11381 x_catch_errors_unwind (old_val)
11382 Lisp_Object old_val;
11384 x_error_message_string = old_val;
11385 return Qnil;
11388 /* If any X protocol errors have arrived since the last call to
11389 x_catch_errors or x_check_errors, signal an Emacs error using
11390 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11392 void
11393 x_check_errors (dpy, format)
11394 Display *dpy;
11395 char *format;
11397 /* Make sure to catch any errors incurred so far. */
11398 XSync (dpy, False);
11400 if (XSTRING (x_error_message_string)->data[0])
11401 error (format, XSTRING (x_error_message_string)->data);
11404 /* Nonzero if we had any X protocol errors
11405 since we did x_catch_errors on DPY. */
11408 x_had_errors_p (dpy)
11409 Display *dpy;
11411 /* Make sure to catch any errors incurred so far. */
11412 XSync (dpy, False);
11414 return XSTRING (x_error_message_string)->data[0] != 0;
11417 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11419 void
11420 x_clear_errors (dpy)
11421 Display *dpy;
11423 XSTRING (x_error_message_string)->data[0] = 0;
11426 /* Stop catching X protocol errors and let them make Emacs die.
11427 DPY should be the display that was passed to x_catch_errors.
11428 COUNT should be the value that was returned by
11429 the corresponding call to x_catch_errors. */
11431 void
11432 x_uncatch_errors (dpy, count)
11433 Display *dpy;
11434 int count;
11436 unbind_to (count, Qnil);
11439 #if 0
11440 static unsigned int x_wire_count;
11441 x_trace_wire ()
11443 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11445 #endif /* ! 0 */
11448 /* Handle SIGPIPE, which can happen when the connection to a server
11449 simply goes away. SIGPIPE is handled by x_connection_signal.
11450 Don't need to do anything, because the write which caused the
11451 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11452 which will do the appropriate cleanup for us. */
11454 static SIGTYPE
11455 x_connection_signal (signalnum) /* If we don't have an argument, */
11456 int signalnum; /* some compilers complain in signal calls. */
11458 #ifdef USG
11459 /* USG systems forget handlers when they are used;
11460 must reestablish each time */
11461 signal (signalnum, x_connection_signal);
11462 #endif /* USG */
11466 /************************************************************************
11467 Handling X errors
11468 ************************************************************************/
11470 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11471 the text of an error message that lead to the connection loss. */
11473 static SIGTYPE
11474 x_connection_closed (dpy, error_message)
11475 Display *dpy;
11476 char *error_message;
11478 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11479 Lisp_Object frame, tail;
11480 int count;
11481 char *msg;
11483 msg = (char *) alloca (strlen (error_message) + 1);
11484 strcpy (msg, error_message);
11485 handling_signal = 0;
11487 /* Prevent being called recursively because of an error condition
11488 below. Otherwise, we might end up with printing ``can't find per
11489 display information'' in the recursive call instead of printing
11490 the original message here. */
11491 count = x_catch_errors (dpy);
11493 /* We have to close the display to inform Xt that it doesn't
11494 exist anymore. If we don't, Xt will continue to wait for
11495 events from the display. As a consequence, a sequence of
11497 M-x make-frame-on-display RET :1 RET
11498 ...kill the new frame, so that we get an IO error...
11499 M-x make-frame-on-display RET :1 RET
11501 will indefinitely wait in Xt for events for display `:1', opened
11502 in the first class to make-frame-on-display.
11504 Closing the display is reported to lead to a bus error on
11505 OpenWindows in certain situations. I suspect that is a bug
11506 in OpenWindows. I don't know how to cicumvent it here. */
11508 #ifdef USE_X_TOOLKIT
11509 /* If DPYINFO is null, this means we didn't open the display
11510 in the first place, so don't try to close it. */
11511 if (dpyinfo)
11512 XtCloseDisplay (dpy);
11513 #endif
11515 /* Indicate that this display is dead. */
11516 if (dpyinfo)
11517 dpyinfo->display = 0;
11519 /* First delete frames whose mini-buffers are on frames
11520 that are on the dead display. */
11521 FOR_EACH_FRAME (tail, frame)
11523 Lisp_Object minibuf_frame;
11524 minibuf_frame
11525 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11526 if (FRAME_X_P (XFRAME (frame))
11527 && FRAME_X_P (XFRAME (minibuf_frame))
11528 && ! EQ (frame, minibuf_frame)
11529 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11530 Fdelete_frame (frame, Qt);
11533 /* Now delete all remaining frames on the dead display.
11534 We are now sure none of these is used as the mini-buffer
11535 for another frame that we need to delete. */
11536 FOR_EACH_FRAME (tail, frame)
11537 if (FRAME_X_P (XFRAME (frame))
11538 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11540 /* Set this to t so that Fdelete_frame won't get confused
11541 trying to find a replacement. */
11542 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11543 Fdelete_frame (frame, Qt);
11546 if (dpyinfo)
11547 x_delete_display (dpyinfo);
11549 x_uncatch_errors (dpy, count);
11551 if (x_display_list == 0)
11553 fprintf (stderr, "%s\n", msg);
11554 shut_down_emacs (0, 0, Qnil);
11555 exit (70);
11558 /* Ordinary stack unwind doesn't deal with these. */
11559 #ifdef SIGIO
11560 sigunblock (sigmask (SIGIO));
11561 #endif
11562 sigunblock (sigmask (SIGALRM));
11563 TOTALLY_UNBLOCK_INPUT;
11565 clear_waiting_for_input ();
11566 error ("%s", msg);
11570 /* This is the usual handler for X protocol errors.
11571 It kills all frames on the display that we got the error for.
11572 If that was the only one, it prints an error message and kills Emacs. */
11574 static void
11575 x_error_quitter (display, error)
11576 Display *display;
11577 XErrorEvent *error;
11579 char buf[256], buf1[356];
11581 /* Note that there is no real way portable across R3/R4 to get the
11582 original error handler. */
11584 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11585 sprintf (buf1, "X protocol error: %s on protocol request %d",
11586 buf, error->request_code);
11587 x_connection_closed (display, buf1);
11591 /* This is the first-level handler for X protocol errors.
11592 It calls x_error_quitter or x_error_catcher. */
11594 static int
11595 x_error_handler (display, error)
11596 Display *display;
11597 XErrorEvent *error;
11599 if (! NILP (x_error_message_string))
11600 x_error_catcher (display, error);
11601 else
11602 x_error_quitter (display, error);
11603 return 0;
11606 /* This is the handler for X IO errors, always.
11607 It kills all frames on the display that we lost touch with.
11608 If that was the only one, it prints an error message and kills Emacs. */
11610 static int
11611 x_io_error_quitter (display)
11612 Display *display;
11614 char buf[256];
11616 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11617 x_connection_closed (display, buf);
11618 return 0;
11621 /* Changing the font of the frame. */
11623 /* Give frame F the font named FONTNAME as its default font, and
11624 return the full name of that font. FONTNAME may be a wildcard
11625 pattern; in that case, we choose some font that fits the pattern.
11626 The return value shows which font we chose. */
11628 Lisp_Object
11629 x_new_font (f, fontname)
11630 struct frame *f;
11631 register char *fontname;
11633 struct font_info *fontp
11634 = FS_LOAD_FONT (f, 0, fontname, -1);
11636 if (!fontp)
11637 return Qnil;
11639 f->output_data.x->font = (XFontStruct *) (fontp->font);
11640 f->output_data.x->baseline_offset = fontp->baseline_offset;
11641 f->output_data.x->fontset = -1;
11643 /* Compute the scroll bar width in character columns. */
11644 if (f->scroll_bar_pixel_width > 0)
11646 int wid = FONT_WIDTH (f->output_data.x->font);
11647 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11649 else
11651 int wid = FONT_WIDTH (f->output_data.x->font);
11652 f->scroll_bar_cols = (14 + wid - 1) / wid;
11655 /* Now make the frame display the given font. */
11656 if (FRAME_X_WINDOW (f) != 0)
11658 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11659 f->output_data.x->font->fid);
11660 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11661 f->output_data.x->font->fid);
11662 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11663 f->output_data.x->font->fid);
11665 frame_update_line_height (f);
11667 /* Don't change the size of a tip frame; there's no point in
11668 doing it because it's done in Fx_show_tip, and it leads to
11669 problems because the tip frame has no widget. */
11670 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11671 x_set_window_size (f, 0, f->width, f->height);
11673 else
11674 /* If we are setting a new frame's font for the first time,
11675 there are no faces yet, so this font's height is the line height. */
11676 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11678 return build_string (fontp->full_name);
11681 /* Give frame F the fontset named FONTSETNAME as its default font, and
11682 return the full name of that fontset. FONTSETNAME may be a wildcard
11683 pattern; in that case, we choose some fontset that fits the pattern.
11684 The return value shows which fontset we chose. */
11686 Lisp_Object
11687 x_new_fontset (f, fontsetname)
11688 struct frame *f;
11689 char *fontsetname;
11691 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11692 Lisp_Object result;
11694 if (fontset < 0)
11695 return Qnil;
11697 if (f->output_data.x->fontset == fontset)
11698 /* This fontset is already set in frame F. There's nothing more
11699 to do. */
11700 return fontset_name (fontset);
11702 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11704 if (!STRINGP (result))
11705 /* Can't load ASCII font. */
11706 return Qnil;
11708 /* Since x_new_font doesn't update any fontset information, do it now. */
11709 f->output_data.x->fontset = fontset;
11711 #ifdef HAVE_X_I18N
11712 if (FRAME_XIC (f)
11713 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11714 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11715 #endif
11717 return build_string (fontsetname);
11721 /***********************************************************************
11722 X Input Methods
11723 ***********************************************************************/
11725 #ifdef HAVE_X_I18N
11727 #ifdef HAVE_X11R6
11729 /* XIM destroy callback function, which is called whenever the
11730 connection to input method XIM dies. CLIENT_DATA contains a
11731 pointer to the x_display_info structure corresponding to XIM. */
11733 static void
11734 xim_destroy_callback (xim, client_data, call_data)
11735 XIM xim;
11736 XPointer client_data;
11737 XPointer call_data;
11739 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11740 Lisp_Object frame, tail;
11742 BLOCK_INPUT;
11744 /* No need to call XDestroyIC.. */
11745 FOR_EACH_FRAME (tail, frame)
11747 struct frame *f = XFRAME (frame);
11748 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11750 FRAME_XIC (f) = NULL;
11751 if (FRAME_XIC_FONTSET (f))
11753 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11754 FRAME_XIC_FONTSET (f) = NULL;
11759 /* No need to call XCloseIM. */
11760 dpyinfo->xim = NULL;
11761 XFree (dpyinfo->xim_styles);
11762 UNBLOCK_INPUT;
11765 #endif /* HAVE_X11R6 */
11767 /* Open the connection to the XIM server on display DPYINFO.
11768 RESOURCE_NAME is the resource name Emacs uses. */
11770 static void
11771 xim_open_dpy (dpyinfo, resource_name)
11772 struct x_display_info *dpyinfo;
11773 char *resource_name;
11775 #ifdef USE_XIM
11776 XIM xim;
11778 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11779 dpyinfo->xim = xim;
11781 if (xim)
11783 #ifdef HAVE_X11R6
11784 XIMCallback destroy;
11785 #endif
11787 /* Get supported styles and XIM values. */
11788 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11790 #ifdef HAVE_X11R6
11791 destroy.callback = xim_destroy_callback;
11792 destroy.client_data = (XPointer)dpyinfo;
11793 /* This isn't prptotyped in OSF 5.0. */
11794 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11795 #endif
11798 #else /* not USE_XIM */
11799 dpyinfo->xim = NULL;
11800 #endif /* not USE_XIM */
11804 #ifdef HAVE_X11R6_XIM
11806 struct xim_inst_t
11808 struct x_display_info *dpyinfo;
11809 char *resource_name;
11812 /* XIM instantiate callback function, which is called whenever an XIM
11813 server is available. DISPLAY is teh display of the XIM.
11814 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11815 when the callback was registered. */
11817 static void
11818 xim_instantiate_callback (display, client_data, call_data)
11819 Display *display;
11820 XPointer client_data;
11821 XPointer call_data;
11823 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11824 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11826 /* We don't support multiple XIM connections. */
11827 if (dpyinfo->xim)
11828 return;
11830 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11832 /* Create XIC for the existing frames on the same display, as long
11833 as they have no XIC. */
11834 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11836 Lisp_Object tail, frame;
11838 BLOCK_INPUT;
11839 FOR_EACH_FRAME (tail, frame)
11841 struct frame *f = XFRAME (frame);
11843 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11844 if (FRAME_XIC (f) == NULL)
11846 create_frame_xic (f);
11847 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11848 xic_set_statusarea (f);
11849 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11851 struct window *w = XWINDOW (f->selected_window);
11852 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11857 UNBLOCK_INPUT;
11861 #endif /* HAVE_X11R6_XIM */
11864 /* Open a connection to the XIM server on display DPYINFO.
11865 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11866 connection only at the first time. On X11R6, open the connection
11867 in the XIM instantiate callback function. */
11869 static void
11870 xim_initialize (dpyinfo, resource_name)
11871 struct x_display_info *dpyinfo;
11872 char *resource_name;
11874 #ifdef USE_XIM
11875 #ifdef HAVE_X11R6_XIM
11876 struct xim_inst_t *xim_inst;
11877 int len;
11879 dpyinfo->xim = NULL;
11880 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11881 xim_inst->dpyinfo = dpyinfo;
11882 len = strlen (resource_name);
11883 xim_inst->resource_name = (char *) xmalloc (len + 1);
11884 bcopy (resource_name, xim_inst->resource_name, len + 1);
11885 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11886 resource_name, EMACS_CLASS,
11887 xim_instantiate_callback,
11888 /* Fixme: This is XPointer in
11889 XFree86 but (XPointer *) on
11890 Tru64, at least. */
11891 (XPointer) xim_inst);
11892 #else /* not HAVE_X11R6_XIM */
11893 dpyinfo->xim = NULL;
11894 xim_open_dpy (dpyinfo, resource_name);
11895 #endif /* not HAVE_X11R6_XIM */
11897 #else /* not USE_XIM */
11898 dpyinfo->xim = NULL;
11899 #endif /* not USE_XIM */
11903 /* Close the connection to the XIM server on display DPYINFO. */
11905 static void
11906 xim_close_dpy (dpyinfo)
11907 struct x_display_info *dpyinfo;
11909 #ifdef USE_XIM
11910 #ifdef HAVE_X11R6_XIM
11911 if (dpyinfo->display)
11912 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11913 NULL, EMACS_CLASS,
11914 xim_instantiate_callback, NULL);
11915 #endif /* not HAVE_X11R6_XIM */
11916 if (dpyinfo->display)
11917 XCloseIM (dpyinfo->xim);
11918 dpyinfo->xim = NULL;
11919 XFree (dpyinfo->xim_styles);
11920 #endif /* USE_XIM */
11923 #endif /* not HAVE_X11R6_XIM */
11927 /* Calculate the absolute position in frame F
11928 from its current recorded position values and gravity. */
11930 void
11931 x_calc_absolute_position (f)
11932 struct frame *f;
11934 Window child;
11935 int win_x = 0, win_y = 0;
11936 int flags = f->output_data.x->size_hint_flags;
11937 int this_window;
11939 /* We have nothing to do if the current position
11940 is already for the top-left corner. */
11941 if (! ((flags & XNegative) || (flags & YNegative)))
11942 return;
11944 #ifdef USE_X_TOOLKIT
11945 this_window = XtWindow (f->output_data.x->widget);
11946 #else
11947 this_window = FRAME_X_WINDOW (f);
11948 #endif
11950 /* Find the position of the outside upper-left corner of
11951 the inner window, with respect to the outer window.
11952 But do this only if we will need the results. */
11953 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11955 int count;
11957 BLOCK_INPUT;
11958 count = x_catch_errors (FRAME_X_DISPLAY (f));
11959 while (1)
11961 x_clear_errors (FRAME_X_DISPLAY (f));
11962 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11964 /* From-window, to-window. */
11965 this_window,
11966 f->output_data.x->parent_desc,
11968 /* From-position, to-position. */
11969 0, 0, &win_x, &win_y,
11971 /* Child of win. */
11972 &child);
11973 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11975 Window newroot, newparent = 0xdeadbeef;
11976 Window *newchildren;
11977 unsigned int nchildren;
11979 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11980 &newparent, &newchildren, &nchildren))
11981 break;
11983 XFree ((char *) newchildren);
11985 f->output_data.x->parent_desc = newparent;
11987 else
11988 break;
11991 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11992 UNBLOCK_INPUT;
11995 /* Treat negative positions as relative to the leftmost bottommost
11996 position that fits on the screen. */
11997 if (flags & XNegative)
11998 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11999 - 2 * f->output_data.x->border_width - win_x
12000 - PIXEL_WIDTH (f)
12001 + f->output_data.x->left_pos);
12004 int height = PIXEL_HEIGHT (f);
12006 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12007 /* Something is fishy here. When using Motif, starting Emacs with
12008 `-g -0-0', the frame appears too low by a few pixels.
12010 This seems to be so because initially, while Emacs is starting,
12011 the column widget's height and the frame's pixel height are
12012 different. The column widget's height is the right one. In
12013 later invocations, when Emacs is up, the frame's pixel height
12014 is right, though.
12016 It's not obvious where the initial small difference comes from.
12017 2000-12-01, gerd. */
12019 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12020 #endif
12022 if (flags & YNegative)
12023 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12024 - 2 * f->output_data.x->border_width
12025 - win_y
12026 - height
12027 + f->output_data.x->top_pos);
12030 /* The left_pos and top_pos
12031 are now relative to the top and left screen edges,
12032 so the flags should correspond. */
12033 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12036 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12037 to really change the position, and 0 when calling from
12038 x_make_frame_visible (in that case, XOFF and YOFF are the current
12039 position values). It is -1 when calling from x_set_frame_parameters,
12040 which means, do adjust for borders but don't change the gravity. */
12042 void
12043 x_set_offset (f, xoff, yoff, change_gravity)
12044 struct frame *f;
12045 register int xoff, yoff;
12046 int change_gravity;
12048 int modified_top, modified_left;
12050 if (change_gravity > 0)
12052 f->output_data.x->top_pos = yoff;
12053 f->output_data.x->left_pos = xoff;
12054 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12055 if (xoff < 0)
12056 f->output_data.x->size_hint_flags |= XNegative;
12057 if (yoff < 0)
12058 f->output_data.x->size_hint_flags |= YNegative;
12059 f->output_data.x->win_gravity = NorthWestGravity;
12061 x_calc_absolute_position (f);
12063 BLOCK_INPUT;
12064 x_wm_set_size_hint (f, (long) 0, 0);
12066 modified_left = f->output_data.x->left_pos;
12067 modified_top = f->output_data.x->top_pos;
12068 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12069 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12070 /* It is a mystery why we need to add the border_width here
12071 when the frame is already visible, but experiment says we do. */
12072 if (change_gravity != 0)
12074 modified_left += f->output_data.x->border_width;
12075 modified_top += f->output_data.x->border_width;
12077 #endif
12079 #ifdef USE_X_TOOLKIT
12080 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12081 modified_left, modified_top);
12082 #else /* not USE_X_TOOLKIT */
12083 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12084 modified_left, modified_top);
12085 #endif /* not USE_X_TOOLKIT */
12086 UNBLOCK_INPUT;
12090 /* Change the size of frame F's X window to COLS/ROWS in the case F
12091 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12092 top-left-corner window gravity for this size change and subsequent
12093 size changes. Otherwise we leave the window gravity unchanged. */
12095 static void
12096 x_set_window_size_1 (f, change_gravity, cols, rows)
12097 struct frame *f;
12098 int change_gravity;
12099 int cols, rows;
12101 int pixelwidth, pixelheight;
12103 check_frame_size (f, &rows, &cols);
12104 f->output_data.x->vertical_scroll_bar_extra
12105 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12107 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12108 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12109 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12110 f->output_data.x->flags_areas_extra
12111 = FRAME_FLAGS_AREA_WIDTH (f);
12112 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12113 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12115 f->output_data.x->win_gravity = NorthWestGravity;
12116 x_wm_set_size_hint (f, (long) 0, 0);
12118 XSync (FRAME_X_DISPLAY (f), False);
12119 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12120 pixelwidth, pixelheight);
12122 /* Now, strictly speaking, we can't be sure that this is accurate,
12123 but the window manager will get around to dealing with the size
12124 change request eventually, and we'll hear how it went when the
12125 ConfigureNotify event gets here.
12127 We could just not bother storing any of this information here,
12128 and let the ConfigureNotify event set everything up, but that
12129 might be kind of confusing to the Lisp code, since size changes
12130 wouldn't be reported in the frame parameters until some random
12131 point in the future when the ConfigureNotify event arrives.
12133 We pass 1 for DELAY since we can't run Lisp code inside of
12134 a BLOCK_INPUT. */
12135 change_frame_size (f, rows, cols, 0, 1, 0);
12136 PIXEL_WIDTH (f) = pixelwidth;
12137 PIXEL_HEIGHT (f) = pixelheight;
12139 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12140 receive in the ConfigureNotify event; if we get what we asked
12141 for, then the event won't cause the screen to become garbaged, so
12142 we have to make sure to do it here. */
12143 SET_FRAME_GARBAGED (f);
12145 XFlush (FRAME_X_DISPLAY (f));
12149 /* Call this to change the size of frame F's x-window.
12150 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12151 for this size change and subsequent size changes.
12152 Otherwise we leave the window gravity unchanged. */
12154 void
12155 x_set_window_size (f, change_gravity, cols, rows)
12156 struct frame *f;
12157 int change_gravity;
12158 int cols, rows;
12160 BLOCK_INPUT;
12162 #ifdef USE_X_TOOLKIT
12164 if (f->output_data.x->widget != NULL)
12166 /* The x and y position of the widget is clobbered by the
12167 call to XtSetValues within EmacsFrameSetCharSize.
12168 This is a real kludge, but I don't understand Xt so I can't
12169 figure out a correct fix. Can anyone else tell me? -- rms. */
12170 int xpos = f->output_data.x->widget->core.x;
12171 int ypos = f->output_data.x->widget->core.y;
12172 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12173 f->output_data.x->widget->core.x = xpos;
12174 f->output_data.x->widget->core.y = ypos;
12176 else
12177 x_set_window_size_1 (f, change_gravity, cols, rows);
12179 #else /* not USE_X_TOOLKIT */
12181 x_set_window_size_1 (f, change_gravity, cols, rows);
12183 #endif /* not USE_X_TOOLKIT */
12185 /* If cursor was outside the new size, mark it as off. */
12186 mark_window_cursors_off (XWINDOW (f->root_window));
12188 /* Clear out any recollection of where the mouse highlighting was,
12189 since it might be in a place that's outside the new frame size.
12190 Actually checking whether it is outside is a pain in the neck,
12191 so don't try--just let the highlighting be done afresh with new size. */
12192 cancel_mouse_face (f);
12194 UNBLOCK_INPUT;
12197 /* Mouse warping. */
12199 void
12200 x_set_mouse_position (f, x, y)
12201 struct frame *f;
12202 int x, y;
12204 int pix_x, pix_y;
12206 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12207 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12209 if (pix_x < 0) pix_x = 0;
12210 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12212 if (pix_y < 0) pix_y = 0;
12213 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12215 BLOCK_INPUT;
12217 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12218 0, 0, 0, 0, pix_x, pix_y);
12219 UNBLOCK_INPUT;
12222 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12224 void
12225 x_set_mouse_pixel_position (f, pix_x, pix_y)
12226 struct frame *f;
12227 int pix_x, pix_y;
12229 BLOCK_INPUT;
12231 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12232 0, 0, 0, 0, pix_x, pix_y);
12233 UNBLOCK_INPUT;
12236 /* focus shifting, raising and lowering. */
12238 void
12239 x_focus_on_frame (f)
12240 struct frame *f;
12242 #if 0 /* This proves to be unpleasant. */
12243 x_raise_frame (f);
12244 #endif
12245 #if 0
12246 /* I don't think that the ICCCM allows programs to do things like this
12247 without the interaction of the window manager. Whatever you end up
12248 doing with this code, do it to x_unfocus_frame too. */
12249 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12250 RevertToPointerRoot, CurrentTime);
12251 #endif /* ! 0 */
12254 void
12255 x_unfocus_frame (f)
12256 struct frame *f;
12258 #if 0
12259 /* Look at the remarks in x_focus_on_frame. */
12260 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12261 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12262 RevertToPointerRoot, CurrentTime);
12263 #endif /* ! 0 */
12266 /* Raise frame F. */
12268 void
12269 x_raise_frame (f)
12270 struct frame *f;
12272 if (f->async_visible)
12274 BLOCK_INPUT;
12275 #ifdef USE_X_TOOLKIT
12276 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12277 #else /* not USE_X_TOOLKIT */
12278 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12279 #endif /* not USE_X_TOOLKIT */
12280 XFlush (FRAME_X_DISPLAY (f));
12281 UNBLOCK_INPUT;
12285 /* Lower frame F. */
12287 void
12288 x_lower_frame (f)
12289 struct frame *f;
12291 if (f->async_visible)
12293 BLOCK_INPUT;
12294 #ifdef USE_X_TOOLKIT
12295 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12296 #else /* not USE_X_TOOLKIT */
12297 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12298 #endif /* not USE_X_TOOLKIT */
12299 XFlush (FRAME_X_DISPLAY (f));
12300 UNBLOCK_INPUT;
12304 static void
12305 XTframe_raise_lower (f, raise_flag)
12306 FRAME_PTR f;
12307 int raise_flag;
12309 if (raise_flag)
12310 x_raise_frame (f);
12311 else
12312 x_lower_frame (f);
12315 /* Change of visibility. */
12317 /* This tries to wait until the frame is really visible.
12318 However, if the window manager asks the user where to position
12319 the frame, this will return before the user finishes doing that.
12320 The frame will not actually be visible at that time,
12321 but it will become visible later when the window manager
12322 finishes with it. */
12324 void
12325 x_make_frame_visible (f)
12326 struct frame *f;
12328 Lisp_Object type;
12329 int original_top, original_left;
12330 int retry_count = 2;
12332 retry:
12334 BLOCK_INPUT;
12336 type = x_icon_type (f);
12337 if (!NILP (type))
12338 x_bitmap_icon (f, type);
12340 if (! FRAME_VISIBLE_P (f))
12342 /* We test FRAME_GARBAGED_P here to make sure we don't
12343 call x_set_offset a second time
12344 if we get to x_make_frame_visible a second time
12345 before the window gets really visible. */
12346 if (! FRAME_ICONIFIED_P (f)
12347 && ! f->output_data.x->asked_for_visible)
12348 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12350 f->output_data.x->asked_for_visible = 1;
12352 if (! EQ (Vx_no_window_manager, Qt))
12353 x_wm_set_window_state (f, NormalState);
12354 #ifdef USE_X_TOOLKIT
12355 /* This was XtPopup, but that did nothing for an iconified frame. */
12356 XtMapWidget (f->output_data.x->widget);
12357 #else /* not USE_X_TOOLKIT */
12358 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12359 #endif /* not USE_X_TOOLKIT */
12360 #if 0 /* This seems to bring back scroll bars in the wrong places
12361 if the window configuration has changed. They seem
12362 to come back ok without this. */
12363 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12364 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12365 #endif
12368 XFlush (FRAME_X_DISPLAY (f));
12370 /* Synchronize to ensure Emacs knows the frame is visible
12371 before we do anything else. We do this loop with input not blocked
12372 so that incoming events are handled. */
12374 Lisp_Object frame;
12375 int count;
12376 /* This must be before UNBLOCK_INPUT
12377 since events that arrive in response to the actions above
12378 will set it when they are handled. */
12379 int previously_visible = f->output_data.x->has_been_visible;
12381 original_left = f->output_data.x->left_pos;
12382 original_top = f->output_data.x->top_pos;
12384 /* This must come after we set COUNT. */
12385 UNBLOCK_INPUT;
12387 /* We unblock here so that arriving X events are processed. */
12389 /* Now move the window back to where it was "supposed to be".
12390 But don't do it if the gravity is negative.
12391 When the gravity is negative, this uses a position
12392 that is 3 pixels too low. Perhaps that's really the border width.
12394 Don't do this if the window has never been visible before,
12395 because the window manager may choose the position
12396 and we don't want to override it. */
12398 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12399 && f->output_data.x->win_gravity == NorthWestGravity
12400 && previously_visible)
12402 Drawable rootw;
12403 int x, y;
12404 unsigned int width, height, border, depth;
12406 BLOCK_INPUT;
12408 /* On some window managers (such as FVWM) moving an existing
12409 window, even to the same place, causes the window manager
12410 to introduce an offset. This can cause the window to move
12411 to an unexpected location. Check the geometry (a little
12412 slow here) and then verify that the window is in the right
12413 place. If the window is not in the right place, move it
12414 there, and take the potential window manager hit. */
12415 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12416 &rootw, &x, &y, &width, &height, &border, &depth);
12418 if (original_left != x || original_top != y)
12419 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12420 original_left, original_top);
12422 UNBLOCK_INPUT;
12425 XSETFRAME (frame, f);
12427 /* Wait until the frame is visible. Process X events until a
12428 MapNotify event has been seen, or until we think we won't get a
12429 MapNotify at all.. */
12430 for (count = input_signal_count + 10;
12431 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12433 /* Force processing of queued events. */
12434 x_sync (f);
12436 /* Machines that do polling rather than SIGIO have been
12437 observed to go into a busy-wait here. So we'll fake an
12438 alarm signal to let the handler know that there's something
12439 to be read. We used to raise a real alarm, but it seems
12440 that the handler isn't always enabled here. This is
12441 probably a bug. */
12442 if (input_polling_used ())
12444 /* It could be confusing if a real alarm arrives while
12445 processing the fake one. Turn it off and let the
12446 handler reset it. */
12447 extern void poll_for_input_1 P_ ((void));
12448 int old_poll_suppress_count = poll_suppress_count;
12449 poll_suppress_count = 1;
12450 poll_for_input_1 ();
12451 poll_suppress_count = old_poll_suppress_count;
12454 /* See if a MapNotify event has been processed. */
12455 FRAME_SAMPLE_VISIBILITY (f);
12458 /* 2000-09-28: In
12460 (let ((f (selected-frame)))
12461 (iconify-frame f)
12462 (raise-frame f))
12464 the frame is not raised with various window managers on
12465 FreeBSD, Linux and Solaris. It turns out that, for some
12466 unknown reason, the call to XtMapWidget is completely ignored.
12467 Mapping the widget a second time works. */
12469 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12470 goto retry;
12474 /* Change from mapped state to withdrawn state. */
12476 /* Make the frame visible (mapped and not iconified). */
12478 void
12479 x_make_frame_invisible (f)
12480 struct frame *f;
12482 Window window;
12484 #ifdef USE_X_TOOLKIT
12485 /* Use the frame's outermost window, not the one we normally draw on. */
12486 window = XtWindow (f->output_data.x->widget);
12487 #else /* not USE_X_TOOLKIT */
12488 window = FRAME_X_WINDOW (f);
12489 #endif /* not USE_X_TOOLKIT */
12491 /* Don't keep the highlight on an invisible frame. */
12492 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12493 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12495 #if 0/* This might add unreliability; I don't trust it -- rms. */
12496 if (! f->async_visible && ! f->async_iconified)
12497 return;
12498 #endif
12500 BLOCK_INPUT;
12502 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12503 that the current position of the window is user-specified, rather than
12504 program-specified, so that when the window is mapped again, it will be
12505 placed at the same location, without forcing the user to position it
12506 by hand again (they have already done that once for this window.) */
12507 x_wm_set_size_hint (f, (long) 0, 1);
12509 #ifdef HAVE_X11R4
12511 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12512 DefaultScreen (FRAME_X_DISPLAY (f))))
12514 UNBLOCK_INPUT_RESIGNAL;
12515 error ("Can't notify window manager of window withdrawal");
12517 #else /* ! defined (HAVE_X11R4) */
12519 /* Tell the window manager what we're going to do. */
12520 if (! EQ (Vx_no_window_manager, Qt))
12522 XEvent unmap;
12524 unmap.xunmap.type = UnmapNotify;
12525 unmap.xunmap.window = window;
12526 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12527 unmap.xunmap.from_configure = False;
12528 if (! XSendEvent (FRAME_X_DISPLAY (f),
12529 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12530 False,
12531 SubstructureRedirectMaskSubstructureNotifyMask,
12532 &unmap))
12534 UNBLOCK_INPUT_RESIGNAL;
12535 error ("Can't notify window manager of withdrawal");
12539 /* Unmap the window ourselves. Cheeky! */
12540 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12541 #endif /* ! defined (HAVE_X11R4) */
12543 /* We can't distinguish this from iconification
12544 just by the event that we get from the server.
12545 So we can't win using the usual strategy of letting
12546 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12547 and synchronize with the server to make sure we agree. */
12548 f->visible = 0;
12549 FRAME_ICONIFIED_P (f) = 0;
12550 f->async_visible = 0;
12551 f->async_iconified = 0;
12553 x_sync (f);
12555 UNBLOCK_INPUT;
12558 /* Change window state from mapped to iconified. */
12560 void
12561 x_iconify_frame (f)
12562 struct frame *f;
12564 int result;
12565 Lisp_Object type;
12567 /* Don't keep the highlight on an invisible frame. */
12568 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12569 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12571 if (f->async_iconified)
12572 return;
12574 BLOCK_INPUT;
12576 FRAME_SAMPLE_VISIBILITY (f);
12578 type = x_icon_type (f);
12579 if (!NILP (type))
12580 x_bitmap_icon (f, type);
12582 #ifdef USE_X_TOOLKIT
12584 if (! FRAME_VISIBLE_P (f))
12586 if (! EQ (Vx_no_window_manager, Qt))
12587 x_wm_set_window_state (f, IconicState);
12588 /* This was XtPopup, but that did nothing for an iconified frame. */
12589 XtMapWidget (f->output_data.x->widget);
12590 /* The server won't give us any event to indicate
12591 that an invisible frame was changed to an icon,
12592 so we have to record it here. */
12593 f->iconified = 1;
12594 f->visible = 1;
12595 f->async_iconified = 1;
12596 f->async_visible = 0;
12597 UNBLOCK_INPUT;
12598 return;
12601 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12602 XtWindow (f->output_data.x->widget),
12603 DefaultScreen (FRAME_X_DISPLAY (f)));
12604 UNBLOCK_INPUT;
12606 if (!result)
12607 error ("Can't notify window manager of iconification");
12609 f->async_iconified = 1;
12610 f->async_visible = 0;
12613 BLOCK_INPUT;
12614 XFlush (FRAME_X_DISPLAY (f));
12615 UNBLOCK_INPUT;
12616 #else /* not USE_X_TOOLKIT */
12618 /* Make sure the X server knows where the window should be positioned,
12619 in case the user deiconifies with the window manager. */
12620 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12621 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12623 /* Since we don't know which revision of X we're running, we'll use both
12624 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12626 /* X11R4: send a ClientMessage to the window manager using the
12627 WM_CHANGE_STATE type. */
12629 XEvent message;
12631 message.xclient.window = FRAME_X_WINDOW (f);
12632 message.xclient.type = ClientMessage;
12633 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12634 message.xclient.format = 32;
12635 message.xclient.data.l[0] = IconicState;
12637 if (! XSendEvent (FRAME_X_DISPLAY (f),
12638 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12639 False,
12640 SubstructureRedirectMask | SubstructureNotifyMask,
12641 &message))
12643 UNBLOCK_INPUT_RESIGNAL;
12644 error ("Can't notify window manager of iconification");
12648 /* X11R3: set the initial_state field of the window manager hints to
12649 IconicState. */
12650 x_wm_set_window_state (f, IconicState);
12652 if (!FRAME_VISIBLE_P (f))
12654 /* If the frame was withdrawn, before, we must map it. */
12655 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12658 f->async_iconified = 1;
12659 f->async_visible = 0;
12661 XFlush (FRAME_X_DISPLAY (f));
12662 UNBLOCK_INPUT;
12663 #endif /* not USE_X_TOOLKIT */
12667 /* Free X resources of frame F. */
12669 void
12670 x_free_frame_resources (f)
12671 struct frame *f;
12673 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12675 BLOCK_INPUT;
12677 /* If a display connection is dead, don't try sending more
12678 commands to the X server. */
12679 if (dpyinfo->display)
12681 if (f->output_data.x->icon_desc)
12682 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12684 #ifdef HAVE_X_I18N
12685 if (FRAME_XIC (f))
12686 free_frame_xic (f);
12687 #endif
12689 if (FRAME_X_WINDOW (f))
12690 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12692 #ifdef USE_X_TOOLKIT
12693 if (f->output_data.x->widget)
12694 XtDestroyWidget (f->output_data.x->widget);
12695 free_frame_menubar (f);
12696 #endif /* USE_X_TOOLKIT */
12698 unload_color (f, f->output_data.x->foreground_pixel);
12699 unload_color (f, f->output_data.x->background_pixel);
12700 unload_color (f, f->output_data.x->cursor_pixel);
12701 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12702 unload_color (f, f->output_data.x->border_pixel);
12703 unload_color (f, f->output_data.x->mouse_pixel);
12705 if (f->output_data.x->scroll_bar_background_pixel != -1)
12706 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12707 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12708 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12709 if (f->output_data.x->white_relief.allocated_p)
12710 unload_color (f, f->output_data.x->white_relief.pixel);
12711 if (f->output_data.x->black_relief.allocated_p)
12712 unload_color (f, f->output_data.x->black_relief.pixel);
12714 if (FRAME_FACE_CACHE (f))
12715 free_frame_faces (f);
12717 x_free_gcs (f);
12718 XFlush (FRAME_X_DISPLAY (f));
12721 if (f->output_data.x->saved_menu_event)
12722 xfree (f->output_data.x->saved_menu_event);
12724 xfree (f->output_data.x);
12725 f->output_data.x = NULL;
12727 if (f == dpyinfo->x_focus_frame)
12728 dpyinfo->x_focus_frame = 0;
12729 if (f == dpyinfo->x_focus_event_frame)
12730 dpyinfo->x_focus_event_frame = 0;
12731 if (f == dpyinfo->x_highlight_frame)
12732 dpyinfo->x_highlight_frame = 0;
12734 if (f == dpyinfo->mouse_face_mouse_frame)
12736 dpyinfo->mouse_face_beg_row
12737 = dpyinfo->mouse_face_beg_col = -1;
12738 dpyinfo->mouse_face_end_row
12739 = dpyinfo->mouse_face_end_col = -1;
12740 dpyinfo->mouse_face_window = Qnil;
12741 dpyinfo->mouse_face_deferred_gc = 0;
12742 dpyinfo->mouse_face_mouse_frame = 0;
12745 UNBLOCK_INPUT;
12749 /* Destroy the X window of frame F. */
12751 void
12752 x_destroy_window (f)
12753 struct frame *f;
12755 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12757 /* If a display connection is dead, don't try sending more
12758 commands to the X server. */
12759 if (dpyinfo->display != 0)
12760 x_free_frame_resources (f);
12762 dpyinfo->reference_count--;
12766 /* Setting window manager hints. */
12768 /* Set the normal size hints for the window manager, for frame F.
12769 FLAGS is the flags word to use--or 0 meaning preserve the flags
12770 that the window now has.
12771 If USER_POSITION is nonzero, we set the USPosition
12772 flag (this is useful when FLAGS is 0). */
12774 void
12775 x_wm_set_size_hint (f, flags, user_position)
12776 struct frame *f;
12777 long flags;
12778 int user_position;
12780 XSizeHints size_hints;
12782 #ifdef USE_X_TOOLKIT
12783 Arg al[2];
12784 int ac = 0;
12785 Dimension widget_width, widget_height;
12786 Window window = XtWindow (f->output_data.x->widget);
12787 #else /* not USE_X_TOOLKIT */
12788 Window window = FRAME_X_WINDOW (f);
12789 #endif /* not USE_X_TOOLKIT */
12791 /* Setting PMaxSize caused various problems. */
12792 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12794 size_hints.x = f->output_data.x->left_pos;
12795 size_hints.y = f->output_data.x->top_pos;
12797 #ifdef USE_X_TOOLKIT
12798 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12799 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12800 XtGetValues (f->output_data.x->widget, al, ac);
12801 size_hints.height = widget_height;
12802 size_hints.width = widget_width;
12803 #else /* not USE_X_TOOLKIT */
12804 size_hints.height = PIXEL_HEIGHT (f);
12805 size_hints.width = PIXEL_WIDTH (f);
12806 #endif /* not USE_X_TOOLKIT */
12808 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12809 size_hints.height_inc = f->output_data.x->line_height;
12810 size_hints.max_width
12811 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12812 size_hints.max_height
12813 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12815 /* Calculate the base and minimum sizes.
12817 (When we use the X toolkit, we don't do it here.
12818 Instead we copy the values that the widgets are using, below.) */
12819 #ifndef USE_X_TOOLKIT
12821 int base_width, base_height;
12822 int min_rows = 0, min_cols = 0;
12824 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12825 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12827 check_frame_size (f, &min_rows, &min_cols);
12829 /* The window manager uses the base width hints to calculate the
12830 current number of rows and columns in the frame while
12831 resizing; min_width and min_height aren't useful for this
12832 purpose, since they might not give the dimensions for a
12833 zero-row, zero-column frame.
12835 We use the base_width and base_height members if we have
12836 them; otherwise, we set the min_width and min_height members
12837 to the size for a zero x zero frame. */
12839 #ifdef HAVE_X11R4
12840 size_hints.flags |= PBaseSize;
12841 size_hints.base_width = base_width;
12842 size_hints.base_height = base_height;
12843 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12844 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12845 #else
12846 size_hints.min_width = base_width;
12847 size_hints.min_height = base_height;
12848 #endif
12851 /* If we don't need the old flags, we don't need the old hint at all. */
12852 if (flags)
12854 size_hints.flags |= flags;
12855 goto no_read;
12857 #endif /* not USE_X_TOOLKIT */
12860 XSizeHints hints; /* Sometimes I hate X Windows... */
12861 long supplied_return;
12862 int value;
12864 #ifdef HAVE_X11R4
12865 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12866 &supplied_return);
12867 #else
12868 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12869 #endif
12871 #ifdef USE_X_TOOLKIT
12872 size_hints.base_height = hints.base_height;
12873 size_hints.base_width = hints.base_width;
12874 size_hints.min_height = hints.min_height;
12875 size_hints.min_width = hints.min_width;
12876 #endif
12878 if (flags)
12879 size_hints.flags |= flags;
12880 else
12882 if (value == 0)
12883 hints.flags = 0;
12884 if (hints.flags & PSize)
12885 size_hints.flags |= PSize;
12886 if (hints.flags & PPosition)
12887 size_hints.flags |= PPosition;
12888 if (hints.flags & USPosition)
12889 size_hints.flags |= USPosition;
12890 if (hints.flags & USSize)
12891 size_hints.flags |= USSize;
12895 #ifndef USE_X_TOOLKIT
12896 no_read:
12897 #endif
12899 #ifdef PWinGravity
12900 size_hints.win_gravity = f->output_data.x->win_gravity;
12901 size_hints.flags |= PWinGravity;
12903 if (user_position)
12905 size_hints.flags &= ~ PPosition;
12906 size_hints.flags |= USPosition;
12908 #endif /* PWinGravity */
12910 #ifdef HAVE_X11R4
12911 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12912 #else
12913 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12914 #endif
12917 /* Used for IconicState or NormalState */
12919 void
12920 x_wm_set_window_state (f, state)
12921 struct frame *f;
12922 int state;
12924 #ifdef USE_X_TOOLKIT
12925 Arg al[1];
12927 XtSetArg (al[0], XtNinitialState, state);
12928 XtSetValues (f->output_data.x->widget, al, 1);
12929 #else /* not USE_X_TOOLKIT */
12930 Window window = FRAME_X_WINDOW (f);
12932 f->output_data.x->wm_hints.flags |= StateHint;
12933 f->output_data.x->wm_hints.initial_state = state;
12935 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12936 #endif /* not USE_X_TOOLKIT */
12939 void
12940 x_wm_set_icon_pixmap (f, pixmap_id)
12941 struct frame *f;
12942 int pixmap_id;
12944 Pixmap icon_pixmap;
12946 #ifndef USE_X_TOOLKIT
12947 Window window = FRAME_X_WINDOW (f);
12948 #endif
12950 if (pixmap_id > 0)
12952 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12953 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12955 else
12957 /* It seems there is no way to turn off use of an icon pixmap.
12958 The following line does it, only if no icon has yet been created,
12959 for some window managers. But with mwm it crashes.
12960 Some people say it should clear the IconPixmapHint bit in this case,
12961 but that doesn't work, and the X consortium said it isn't the
12962 right thing at all. Since there is no way to win,
12963 best to explicitly give up. */
12964 #if 0
12965 f->output_data.x->wm_hints.icon_pixmap = None;
12966 #else
12967 return;
12968 #endif
12971 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12974 Arg al[1];
12975 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12976 XtSetValues (f->output_data.x->widget, al, 1);
12979 #else /* not USE_X_TOOLKIT */
12981 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12982 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12984 #endif /* not USE_X_TOOLKIT */
12987 void
12988 x_wm_set_icon_position (f, icon_x, icon_y)
12989 struct frame *f;
12990 int icon_x, icon_y;
12992 #ifdef USE_X_TOOLKIT
12993 Window window = XtWindow (f->output_data.x->widget);
12994 #else
12995 Window window = FRAME_X_WINDOW (f);
12996 #endif
12998 f->output_data.x->wm_hints.flags |= IconPositionHint;
12999 f->output_data.x->wm_hints.icon_x = icon_x;
13000 f->output_data.x->wm_hints.icon_y = icon_y;
13002 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13006 /***********************************************************************
13007 Fonts
13008 ***********************************************************************/
13010 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13012 struct font_info *
13013 x_get_font_info (f, font_idx)
13014 FRAME_PTR f;
13015 int font_idx;
13017 return (FRAME_X_FONT_TABLE (f) + font_idx);
13021 /* Return a list of names of available fonts matching PATTERN on frame F.
13023 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13024 to be listed.
13026 SIZE < 0 means include scalable fonts.
13028 Frame F null means we have not yet created any frame on X, and
13029 consult the first display in x_display_list. MAXNAMES sets a limit
13030 on how many fonts to match. */
13032 Lisp_Object
13033 x_list_fonts (f, pattern, size, maxnames)
13034 struct frame *f;
13035 Lisp_Object pattern;
13036 int size;
13037 int maxnames;
13039 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13040 Lisp_Object tem, second_best;
13041 struct x_display_info *dpyinfo
13042 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13043 Display *dpy = dpyinfo->display;
13044 int try_XLoadQueryFont = 0;
13045 int count;
13046 int allow_scalable_fonts_p = 0;
13048 if (size < 0)
13050 allow_scalable_fonts_p = 1;
13051 size = 0;
13054 patterns = Fassoc (pattern, Valternate_fontname_alist);
13055 if (NILP (patterns))
13056 patterns = Fcons (pattern, Qnil);
13058 if (maxnames == 1 && !size)
13059 /* We can return any single font matching PATTERN. */
13060 try_XLoadQueryFont = 1;
13062 for (; CONSP (patterns); patterns = XCDR (patterns))
13064 int num_fonts;
13065 char **names = NULL;
13067 pattern = XCAR (patterns);
13068 /* See if we cached the result for this particular query.
13069 The cache is an alist of the form:
13070 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13071 tem = XCDR (dpyinfo->name_list_element);
13072 key = Fcons (Fcons (pattern, make_number (maxnames)),
13073 allow_scalable_fonts_p ? Qt : Qnil);
13074 list = Fassoc (key, tem);
13075 if (!NILP (list))
13077 list = Fcdr_safe (list);
13078 /* We have a cashed list. Don't have to get the list again. */
13079 goto label_cached;
13082 /* At first, put PATTERN in the cache. */
13084 BLOCK_INPUT;
13085 count = x_catch_errors (dpy);
13087 if (try_XLoadQueryFont)
13089 XFontStruct *font;
13090 unsigned long value;
13092 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13093 if (x_had_errors_p (dpy))
13095 /* This error is perhaps due to insufficient memory on X
13096 server. Let's just ignore it. */
13097 font = NULL;
13098 x_clear_errors (dpy);
13101 if (font
13102 && XGetFontProperty (font, XA_FONT, &value))
13104 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13105 int len = strlen (name);
13106 char *tmp;
13108 /* If DXPC (a Differential X Protocol Compressor)
13109 Ver.3.7 is running, XGetAtomName will return null
13110 string. We must avoid such a name. */
13111 if (len == 0)
13112 try_XLoadQueryFont = 0;
13113 else
13115 num_fonts = 1;
13116 names = (char **) alloca (sizeof (char *));
13117 /* Some systems only allow alloca assigned to a
13118 simple var. */
13119 tmp = (char *) alloca (len + 1); names[0] = tmp;
13120 bcopy (name, names[0], len + 1);
13121 XFree (name);
13124 else
13125 try_XLoadQueryFont = 0;
13127 if (font)
13128 XFreeFont (dpy, font);
13131 if (!try_XLoadQueryFont)
13133 /* We try at least 10 fonts because XListFonts will return
13134 auto-scaled fonts at the head. */
13135 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13136 &num_fonts);
13137 if (x_had_errors_p (dpy))
13139 /* This error is perhaps due to insufficient memory on X
13140 server. Let's just ignore it. */
13141 names = NULL;
13142 x_clear_errors (dpy);
13146 x_uncatch_errors (dpy, count);
13147 UNBLOCK_INPUT;
13149 if (names)
13151 int i;
13153 /* Make a list of all the fonts we got back.
13154 Store that in the font cache for the display. */
13155 for (i = 0; i < num_fonts; i++)
13157 int width = 0;
13158 char *p = names[i];
13159 int average_width = -1, dashes = 0;
13161 /* Count the number of dashes in NAMES[I]. If there are
13162 14 dashes, and the field value following 12th dash
13163 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13164 is usually too ugly to be used for editing. Let's
13165 ignore it. */
13166 while (*p)
13167 if (*p++ == '-')
13169 dashes++;
13170 if (dashes == 7) /* PIXEL_SIZE field */
13171 width = atoi (p);
13172 else if (dashes == 12) /* AVERAGE_WIDTH field */
13173 average_width = atoi (p);
13176 if (allow_scalable_fonts_p
13177 || dashes < 14 || average_width != 0)
13179 tem = build_string (names[i]);
13180 if (NILP (Fassoc (tem, list)))
13182 if (STRINGP (Vx_pixel_size_width_font_regexp)
13183 && ((fast_c_string_match_ignore_case
13184 (Vx_pixel_size_width_font_regexp, names[i]))
13185 >= 0))
13186 /* We can set the value of PIXEL_SIZE to the
13187 width of this font. */
13188 list = Fcons (Fcons (tem, make_number (width)), list);
13189 else
13190 /* For the moment, width is not known. */
13191 list = Fcons (Fcons (tem, Qnil), list);
13195 if (!try_XLoadQueryFont)
13196 XFreeFontNames (names);
13199 /* Now store the result in the cache. */
13200 XCDR (dpyinfo->name_list_element)
13201 = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
13203 label_cached:
13204 if (NILP (list)) continue; /* Try the remaining alternatives. */
13206 newlist = second_best = Qnil;
13207 /* Make a list of the fonts that have the right width. */
13208 for (; CONSP (list); list = XCDR (list))
13210 int found_size;
13212 tem = XCAR (list);
13214 if (!CONSP (tem) || NILP (XCAR (tem)))
13215 continue;
13216 if (!size)
13218 newlist = Fcons (XCAR (tem), newlist);
13219 continue;
13222 if (!INTEGERP (XCDR (tem)))
13224 /* Since we have not yet known the size of this font, we
13225 must try slow function call XLoadQueryFont. */
13226 XFontStruct *thisinfo;
13228 BLOCK_INPUT;
13229 count = x_catch_errors (dpy);
13230 thisinfo = XLoadQueryFont (dpy,
13231 XSTRING (XCAR (tem))->data);
13232 if (x_had_errors_p (dpy))
13234 /* This error is perhaps due to insufficient memory on X
13235 server. Let's just ignore it. */
13236 thisinfo = NULL;
13237 x_clear_errors (dpy);
13239 x_uncatch_errors (dpy, count);
13240 UNBLOCK_INPUT;
13242 if (thisinfo)
13244 XCDR (tem)
13245 = (thisinfo->min_bounds.width == 0
13246 ? make_number (0)
13247 : make_number (thisinfo->max_bounds.width));
13248 XFreeFont (dpy, thisinfo);
13250 else
13251 /* For unknown reason, the previous call of XListFont had
13252 returned a font which can't be opened. Record the size
13253 as 0 not to try to open it again. */
13254 XCDR (tem) = make_number (0);
13257 found_size = XINT (XCDR (tem));
13258 if (found_size == size)
13259 newlist = Fcons (XCAR (tem), newlist);
13260 else if (found_size > 0)
13262 if (NILP (second_best))
13263 second_best = tem;
13264 else if (found_size < size)
13266 if (XINT (XCDR (second_best)) > size
13267 || XINT (XCDR (second_best)) < found_size)
13268 second_best = tem;
13270 else
13272 if (XINT (XCDR (second_best)) > size
13273 && XINT (XCDR (second_best)) > found_size)
13274 second_best = tem;
13278 if (!NILP (newlist))
13279 break;
13280 else if (!NILP (second_best))
13282 newlist = Fcons (XCAR (second_best), Qnil);
13283 break;
13287 return newlist;
13291 #if GLYPH_DEBUG
13293 /* Check that FONT is valid on frame F. It is if it can be found in F's
13294 font table. */
13296 static void
13297 x_check_font (f, font)
13298 struct frame *f;
13299 XFontStruct *font;
13301 int i;
13302 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13304 xassert (font != NULL);
13306 for (i = 0; i < dpyinfo->n_fonts; i++)
13307 if (dpyinfo->font_table[i].name
13308 && font == dpyinfo->font_table[i].font)
13309 break;
13311 xassert (i < dpyinfo->n_fonts);
13314 #endif /* GLYPH_DEBUG != 0 */
13316 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13317 Note: There are (broken) X fonts out there with invalid XFontStruct
13318 min_bounds contents. For example, handa@etl.go.jp reports that
13319 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13320 have font->min_bounds.width == 0. */
13322 static INLINE void
13323 x_font_min_bounds (font, w, h)
13324 XFontStruct *font;
13325 int *w, *h;
13327 *h = FONT_HEIGHT (font);
13328 *w = font->min_bounds.width;
13330 /* Try to handle the case where FONT->min_bounds has invalid
13331 contents. Since the only font known to have invalid min_bounds
13332 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13333 if (*w <= 0)
13334 *w = font->max_bounds.width;
13338 /* Compute the smallest character width and smallest font height over
13339 all fonts available on frame F. Set the members smallest_char_width
13340 and smallest_font_height in F's x_display_info structure to
13341 the values computed. Value is non-zero if smallest_font_height or
13342 smallest_char_width become smaller than they were before. */
13344 static int
13345 x_compute_min_glyph_bounds (f)
13346 struct frame *f;
13348 int i;
13349 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13350 XFontStruct *font;
13351 int old_width = dpyinfo->smallest_char_width;
13352 int old_height = dpyinfo->smallest_font_height;
13354 dpyinfo->smallest_font_height = 100000;
13355 dpyinfo->smallest_char_width = 100000;
13357 for (i = 0; i < dpyinfo->n_fonts; ++i)
13358 if (dpyinfo->font_table[i].name)
13360 struct font_info *fontp = dpyinfo->font_table + i;
13361 int w, h;
13363 font = (XFontStruct *) fontp->font;
13364 xassert (font != (XFontStruct *) ~0);
13365 x_font_min_bounds (font, &w, &h);
13367 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13368 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13371 xassert (dpyinfo->smallest_char_width > 0
13372 && dpyinfo->smallest_font_height > 0);
13374 return (dpyinfo->n_fonts == 1
13375 || dpyinfo->smallest_char_width < old_width
13376 || dpyinfo->smallest_font_height < old_height);
13380 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13381 pointer to the structure font_info while allocating it dynamically.
13382 If SIZE is 0, load any size of font.
13383 If loading is failed, return NULL. */
13385 struct font_info *
13386 x_load_font (f, fontname, size)
13387 struct frame *f;
13388 register char *fontname;
13389 int size;
13391 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13392 Lisp_Object font_names;
13393 int count;
13395 /* Get a list of all the fonts that match this name. Once we
13396 have a list of matching fonts, we compare them against the fonts
13397 we already have by comparing names. */
13398 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13400 if (!NILP (font_names))
13402 Lisp_Object tail;
13403 int i;
13405 for (i = 0; i < dpyinfo->n_fonts; i++)
13406 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13407 if (dpyinfo->font_table[i].name
13408 && (!strcmp (dpyinfo->font_table[i].name,
13409 XSTRING (XCAR (tail))->data)
13410 || !strcmp (dpyinfo->font_table[i].full_name,
13411 XSTRING (XCAR (tail))->data)))
13412 return (dpyinfo->font_table + i);
13415 /* Load the font and add it to the table. */
13417 char *full_name;
13418 XFontStruct *font;
13419 struct font_info *fontp;
13420 unsigned long value;
13421 int i;
13423 /* If we have found fonts by x_list_font, load one of them. If
13424 not, we still try to load a font by the name given as FONTNAME
13425 because XListFonts (called in x_list_font) of some X server has
13426 a bug of not finding a font even if the font surely exists and
13427 is loadable by XLoadQueryFont. */
13428 if (size > 0 && !NILP (font_names))
13429 fontname = (char *) XSTRING (XCAR (font_names))->data;
13431 BLOCK_INPUT;
13432 count = x_catch_errors (FRAME_X_DISPLAY (f));
13433 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13434 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13436 /* This error is perhaps due to insufficient memory on X
13437 server. Let's just ignore it. */
13438 font = NULL;
13439 x_clear_errors (FRAME_X_DISPLAY (f));
13441 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13442 UNBLOCK_INPUT;
13443 if (!font)
13444 return NULL;
13446 /* Find a free slot in the font table. */
13447 for (i = 0; i < dpyinfo->n_fonts; ++i)
13448 if (dpyinfo->font_table[i].name == NULL)
13449 break;
13451 /* If no free slot found, maybe enlarge the font table. */
13452 if (i == dpyinfo->n_fonts
13453 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13455 int sz;
13456 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13457 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13458 dpyinfo->font_table
13459 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13462 fontp = dpyinfo->font_table + i;
13463 if (i == dpyinfo->n_fonts)
13464 ++dpyinfo->n_fonts;
13466 /* Now fill in the slots of *FONTP. */
13467 BLOCK_INPUT;
13468 fontp->font = font;
13469 fontp->font_idx = i;
13470 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13471 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13473 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13474 full_name = 0;
13475 if (XGetFontProperty (font, XA_FONT, &value))
13477 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13478 char *p = name;
13479 int dashes = 0;
13481 /* Count the number of dashes in the "full name".
13482 If it is too few, this isn't really the font's full name,
13483 so don't use it.
13484 In X11R4, the fonts did not come with their canonical names
13485 stored in them. */
13486 while (*p)
13488 if (*p == '-')
13489 dashes++;
13490 p++;
13493 if (dashes >= 13)
13495 full_name = (char *) xmalloc (p - name + 1);
13496 bcopy (name, full_name, p - name + 1);
13499 XFree (name);
13502 if (full_name != 0)
13503 fontp->full_name = full_name;
13504 else
13505 fontp->full_name = fontp->name;
13507 fontp->size = font->max_bounds.width;
13508 fontp->height = FONT_HEIGHT (font);
13510 if (NILP (font_names))
13512 /* We come here because of a bug of XListFonts mentioned at
13513 the head of this block. Let's store this information in
13514 the cache for x_list_fonts. */
13515 Lisp_Object lispy_name = build_string (fontname);
13516 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13517 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13518 Qnil);
13520 XCDR (dpyinfo->name_list_element)
13521 = Fcons (Fcons (key,
13522 Fcons (Fcons (lispy_full_name,
13523 make_number (fontp->size)),
13524 Qnil)),
13525 XCDR (dpyinfo->name_list_element));
13526 if (full_name)
13528 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13529 Qnil);
13530 XCDR (dpyinfo->name_list_element)
13531 = Fcons (Fcons (key,
13532 Fcons (Fcons (lispy_full_name,
13533 make_number (fontp->size)),
13534 Qnil)),
13535 XCDR (dpyinfo->name_list_element));
13539 /* The slot `encoding' specifies how to map a character
13540 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13541 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13542 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13543 2:0xA020..0xFF7F). For the moment, we don't know which charset
13544 uses this font. So, we set information in fontp->encoding[1]
13545 which is never used by any charset. If mapping can't be
13546 decided, set FONT_ENCODING_NOT_DECIDED. */
13547 fontp->encoding[1]
13548 = (font->max_byte1 == 0
13549 /* 1-byte font */
13550 ? (font->min_char_or_byte2 < 0x80
13551 ? (font->max_char_or_byte2 < 0x80
13552 ? 0 /* 0x20..0x7F */
13553 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13554 : 1) /* 0xA0..0xFF */
13555 /* 2-byte font */
13556 : (font->min_byte1 < 0x80
13557 ? (font->max_byte1 < 0x80
13558 ? (font->min_char_or_byte2 < 0x80
13559 ? (font->max_char_or_byte2 < 0x80
13560 ? 0 /* 0x2020..0x7F7F */
13561 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13562 : 3) /* 0x20A0..0x7FFF */
13563 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13564 : (font->min_char_or_byte2 < 0x80
13565 ? (font->max_char_or_byte2 < 0x80
13566 ? 2 /* 0xA020..0xFF7F */
13567 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13568 : 1))); /* 0xA0A0..0xFFFF */
13570 fontp->baseline_offset
13571 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13572 ? (long) value : 0);
13573 fontp->relative_compose
13574 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13575 ? (long) value : 0);
13576 fontp->default_ascent
13577 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13578 ? (long) value : 0);
13580 /* Set global flag fonts_changed_p to non-zero if the font loaded
13581 has a character with a smaller width than any other character
13582 before, or if the font loaded has a smalle>r height than any
13583 other font loaded before. If this happens, it will make a
13584 glyph matrix reallocation necessary. */
13585 fonts_changed_p = x_compute_min_glyph_bounds (f);
13586 UNBLOCK_INPUT;
13587 return fontp;
13592 /* Return a pointer to struct font_info of a font named FONTNAME for
13593 frame F. If no such font is loaded, return NULL. */
13595 struct font_info *
13596 x_query_font (f, fontname)
13597 struct frame *f;
13598 register char *fontname;
13600 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13601 int i;
13603 for (i = 0; i < dpyinfo->n_fonts; i++)
13604 if (dpyinfo->font_table[i].name
13605 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13606 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13607 return (dpyinfo->font_table + i);
13608 return NULL;
13612 /* Find a CCL program for a font specified by FONTP, and set the member
13613 `encoder' of the structure. */
13615 void
13616 x_find_ccl_program (fontp)
13617 struct font_info *fontp;
13619 Lisp_Object list, elt;
13621 elt = Qnil;
13622 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13624 elt = XCAR (list);
13625 if (CONSP (elt)
13626 && STRINGP (XCAR (elt))
13627 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13628 >= 0)
13629 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13630 >= 0)))
13631 break;
13634 if (! NILP (list))
13636 struct ccl_program *ccl
13637 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13639 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13640 xfree (ccl);
13641 else
13642 fontp->font_encoder = ccl;
13648 /***********************************************************************
13649 Initialization
13650 ***********************************************************************/
13652 #ifdef USE_X_TOOLKIT
13653 static XrmOptionDescRec emacs_options[] = {
13654 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13655 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13657 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13658 XrmoptionSepArg, NULL},
13659 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13661 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13662 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13663 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13664 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13665 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13666 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13667 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13669 #endif /* USE_X_TOOLKIT */
13671 static int x_initialized;
13673 #ifdef MULTI_KBOARD
13674 /* Test whether two display-name strings agree up to the dot that separates
13675 the screen number from the server number. */
13676 static int
13677 same_x_server (name1, name2)
13678 char *name1, *name2;
13680 int seen_colon = 0;
13681 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13682 int system_name_length = strlen (system_name);
13683 int length_until_period = 0;
13685 while (system_name[length_until_period] != 0
13686 && system_name[length_until_period] != '.')
13687 length_until_period++;
13689 /* Treat `unix' like an empty host name. */
13690 if (! strncmp (name1, "unix:", 5))
13691 name1 += 4;
13692 if (! strncmp (name2, "unix:", 5))
13693 name2 += 4;
13694 /* Treat this host's name like an empty host name. */
13695 if (! strncmp (name1, system_name, system_name_length)
13696 && name1[system_name_length] == ':')
13697 name1 += system_name_length;
13698 if (! strncmp (name2, system_name, system_name_length)
13699 && name2[system_name_length] == ':')
13700 name2 += system_name_length;
13701 /* Treat this host's domainless name like an empty host name. */
13702 if (! strncmp (name1, system_name, length_until_period)
13703 && name1[length_until_period] == ':')
13704 name1 += length_until_period;
13705 if (! strncmp (name2, system_name, length_until_period)
13706 && name2[length_until_period] == ':')
13707 name2 += length_until_period;
13709 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13711 if (*name1 == ':')
13712 seen_colon++;
13713 if (seen_colon && *name1 == '.')
13714 return 1;
13716 return (seen_colon
13717 && (*name1 == '.' || *name1 == '\0')
13718 && (*name2 == '.' || *name2 == '\0'));
13720 #endif
13722 struct x_display_info *
13723 x_term_init (display_name, xrm_option, resource_name)
13724 Lisp_Object display_name;
13725 char *xrm_option;
13726 char *resource_name;
13728 int connection;
13729 Display *dpy;
13730 struct x_display_info *dpyinfo;
13731 XrmDatabase xrdb;
13733 BLOCK_INPUT;
13735 if (!x_initialized)
13737 x_initialize ();
13738 x_initialized = 1;
13741 #ifdef USE_X_TOOLKIT
13742 /* weiner@footloose.sps.mot.com reports that this causes
13743 errors with X11R5:
13744 X protocol error: BadAtom (invalid Atom parameter)
13745 on protocol request 18skiloaf.
13746 So let's not use it until R6. */
13747 #ifdef HAVE_X11XTR6
13748 XtSetLanguageProc (NULL, NULL, NULL);
13749 #endif
13752 int argc = 0;
13753 char *argv[3];
13755 argv[0] = "";
13756 argc = 1;
13757 if (xrm_option)
13759 argv[argc++] = "-xrm";
13760 argv[argc++] = xrm_option;
13762 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13763 resource_name, EMACS_CLASS,
13764 emacs_options, XtNumber (emacs_options),
13765 &argc, argv);
13767 #ifdef HAVE_X11XTR6
13768 /* I think this is to compensate for XtSetLanguageProc. */
13769 fixup_locale ();
13770 #endif
13773 #else /* not USE_X_TOOLKIT */
13774 #ifdef HAVE_X11R5
13775 XSetLocaleModifiers ("");
13776 #endif
13777 dpy = XOpenDisplay (XSTRING (display_name)->data);
13778 #endif /* not USE_X_TOOLKIT */
13780 /* Detect failure. */
13781 if (dpy == 0)
13783 UNBLOCK_INPUT;
13784 return 0;
13787 /* We have definitely succeeded. Record the new connection. */
13789 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13790 bzero (dpyinfo, sizeof *dpyinfo);
13792 #ifdef MULTI_KBOARD
13794 struct x_display_info *share;
13795 Lisp_Object tail;
13797 for (share = x_display_list, tail = x_display_name_list; share;
13798 share = share->next, tail = XCDR (tail))
13799 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13800 XSTRING (display_name)->data))
13801 break;
13802 if (share)
13803 dpyinfo->kboard = share->kboard;
13804 else
13806 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13807 init_kboard (dpyinfo->kboard);
13808 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13810 char *vendor = ServerVendor (dpy);
13811 UNBLOCK_INPUT;
13812 dpyinfo->kboard->Vsystem_key_alist
13813 = call1 (Qvendor_specific_keysyms,
13814 build_string (vendor ? vendor : ""));
13815 BLOCK_INPUT;
13818 dpyinfo->kboard->next_kboard = all_kboards;
13819 all_kboards = dpyinfo->kboard;
13820 /* Don't let the initial kboard remain current longer than necessary.
13821 That would cause problems if a file loaded on startup tries to
13822 prompt in the mini-buffer. */
13823 if (current_kboard == initial_kboard)
13824 current_kboard = dpyinfo->kboard;
13826 dpyinfo->kboard->reference_count++;
13828 #endif
13830 /* Put this display on the chain. */
13831 dpyinfo->next = x_display_list;
13832 x_display_list = dpyinfo;
13834 /* Put it on x_display_name_list as well, to keep them parallel. */
13835 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13836 x_display_name_list);
13837 dpyinfo->name_list_element = XCAR (x_display_name_list);
13839 dpyinfo->display = dpy;
13841 #if 0
13842 XSetAfterFunction (x_current_display, x_trace_wire);
13843 #endif /* ! 0 */
13845 dpyinfo->x_id_name
13846 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13847 + STRING_BYTES (XSTRING (Vsystem_name))
13848 + 2);
13849 sprintf (dpyinfo->x_id_name, "%s@%s",
13850 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13852 /* Figure out which modifier bits mean what. */
13853 x_find_modifier_meanings (dpyinfo);
13855 /* Get the scroll bar cursor. */
13856 dpyinfo->vertical_scroll_bar_cursor
13857 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13859 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13860 resource_name, EMACS_CLASS);
13861 #ifdef HAVE_XRMSETDATABASE
13862 XrmSetDatabase (dpyinfo->display, xrdb);
13863 #else
13864 dpyinfo->display->db = xrdb;
13865 #endif
13866 /* Put the rdb where we can find it in a way that works on
13867 all versions. */
13868 dpyinfo->xrdb = xrdb;
13870 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13871 DefaultScreen (dpyinfo->display));
13872 select_visual (dpyinfo);
13873 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13874 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13875 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13876 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13877 dpyinfo->grabbed = 0;
13878 dpyinfo->reference_count = 0;
13879 dpyinfo->icon_bitmap_id = -1;
13880 dpyinfo->font_table = NULL;
13881 dpyinfo->n_fonts = 0;
13882 dpyinfo->font_table_size = 0;
13883 dpyinfo->bitmaps = 0;
13884 dpyinfo->bitmaps_size = 0;
13885 dpyinfo->bitmaps_last = 0;
13886 dpyinfo->scratch_cursor_gc = 0;
13887 dpyinfo->mouse_face_mouse_frame = 0;
13888 dpyinfo->mouse_face_deferred_gc = 0;
13889 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13890 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13891 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13892 dpyinfo->mouse_face_window = Qnil;
13893 dpyinfo->mouse_face_overlay = Qnil;
13894 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13895 dpyinfo->mouse_face_defer = 0;
13896 dpyinfo->x_focus_frame = 0;
13897 dpyinfo->x_focus_event_frame = 0;
13898 dpyinfo->x_highlight_frame = 0;
13899 dpyinfo->image_cache = make_image_cache ();
13901 /* See if a private colormap is requested. */
13902 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13904 if (dpyinfo->visual->class == PseudoColor)
13906 Lisp_Object value;
13907 value = display_x_get_resource (dpyinfo,
13908 build_string ("privateColormap"),
13909 build_string ("PrivateColormap"),
13910 Qnil, Qnil);
13911 if (STRINGP (value)
13912 && (!strcmp (XSTRING (value)->data, "true")
13913 || !strcmp (XSTRING (value)->data, "on")))
13914 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13917 else
13918 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13919 dpyinfo->visual, AllocNone);
13922 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13923 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13924 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13925 dpyinfo->resy = pixels * 25.4 / mm;
13926 pixels = DisplayWidth (dpyinfo->display, screen_number);
13927 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13928 dpyinfo->resx = pixels * 25.4 / mm;
13931 dpyinfo->Xatom_wm_protocols
13932 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13933 dpyinfo->Xatom_wm_take_focus
13934 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13935 dpyinfo->Xatom_wm_save_yourself
13936 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13937 dpyinfo->Xatom_wm_delete_window
13938 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13939 dpyinfo->Xatom_wm_change_state
13940 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13941 dpyinfo->Xatom_wm_configure_denied
13942 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13943 dpyinfo->Xatom_wm_window_moved
13944 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13945 dpyinfo->Xatom_editres
13946 = XInternAtom (dpyinfo->display, "Editres", False);
13947 dpyinfo->Xatom_CLIPBOARD
13948 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13949 dpyinfo->Xatom_TIMESTAMP
13950 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13951 dpyinfo->Xatom_TEXT
13952 = XInternAtom (dpyinfo->display, "TEXT", False);
13953 dpyinfo->Xatom_COMPOUND_TEXT
13954 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13955 dpyinfo->Xatom_DELETE
13956 = XInternAtom (dpyinfo->display, "DELETE", False);
13957 dpyinfo->Xatom_MULTIPLE
13958 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13959 dpyinfo->Xatom_INCR
13960 = XInternAtom (dpyinfo->display, "INCR", False);
13961 dpyinfo->Xatom_EMACS_TMP
13962 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13963 dpyinfo->Xatom_TARGETS
13964 = XInternAtom (dpyinfo->display, "TARGETS", False);
13965 dpyinfo->Xatom_NULL
13966 = XInternAtom (dpyinfo->display, "NULL", False);
13967 dpyinfo->Xatom_ATOM_PAIR
13968 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13969 /* For properties of font. */
13970 dpyinfo->Xatom_PIXEL_SIZE
13971 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13972 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13973 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13974 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13975 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13976 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13977 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13979 /* Ghostscript support. */
13980 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13981 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13983 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13984 False);
13986 dpyinfo->cut_buffers_initialized = 0;
13988 connection = ConnectionNumber (dpyinfo->display);
13989 dpyinfo->connection = connection;
13992 char null_bits[1];
13994 null_bits[0] = 0x00;
13996 dpyinfo->null_pixel
13997 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13998 null_bits, 1, 1, (long) 0, (long) 0,
14003 extern int gray_bitmap_width, gray_bitmap_height;
14004 extern char *gray_bitmap_bits;
14005 dpyinfo->gray
14006 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14007 gray_bitmap_bits,
14008 gray_bitmap_width, gray_bitmap_height,
14009 (unsigned long) 1, (unsigned long) 0, 1);
14012 #ifdef HAVE_X_I18N
14013 xim_initialize (dpyinfo, resource_name);
14014 #endif
14016 #ifdef subprocesses
14017 /* This is only needed for distinguishing keyboard and process input. */
14018 if (connection != 0)
14019 add_keyboard_wait_descriptor (connection);
14020 #endif
14022 #ifndef F_SETOWN_BUG
14023 #ifdef F_SETOWN
14024 #ifdef F_SETOWN_SOCK_NEG
14025 /* stdin is a socket here */
14026 fcntl (connection, F_SETOWN, -getpid ());
14027 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14028 fcntl (connection, F_SETOWN, getpid ());
14029 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14030 #endif /* ! defined (F_SETOWN) */
14031 #endif /* F_SETOWN_BUG */
14033 #ifdef SIGIO
14034 if (interrupt_input)
14035 init_sigio (connection);
14036 #endif /* ! defined (SIGIO) */
14038 #ifdef USE_LUCID
14039 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14040 /* Make sure that we have a valid font for dialog boxes
14041 so that Xt does not crash. */
14043 Display *dpy = dpyinfo->display;
14044 XrmValue d, fr, to;
14045 Font font;
14046 int count;
14048 d.addr = (XPointer)&dpy;
14049 d.size = sizeof (Display *);
14050 fr.addr = XtDefaultFont;
14051 fr.size = sizeof (XtDefaultFont);
14052 to.size = sizeof (Font *);
14053 to.addr = (XPointer)&font;
14054 count = x_catch_errors (dpy);
14055 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14056 abort ();
14057 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14058 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14059 x_uncatch_errors (dpy, count);
14061 #endif
14062 #endif
14064 /* See if we should run in synchronous mode. This is useful
14065 for debugging X code. */
14067 Lisp_Object value;
14068 value = display_x_get_resource (dpyinfo,
14069 build_string ("synchronous"),
14070 build_string ("Synchronous"),
14071 Qnil, Qnil);
14072 if (STRINGP (value)
14073 && (!strcmp (XSTRING (value)->data, "true")
14074 || !strcmp (XSTRING (value)->data, "on")))
14075 XSynchronize (dpyinfo->display, True);
14078 UNBLOCK_INPUT;
14080 return dpyinfo;
14083 /* Get rid of display DPYINFO, assuming all frames are already gone,
14084 and without sending any more commands to the X server. */
14086 void
14087 x_delete_display (dpyinfo)
14088 struct x_display_info *dpyinfo;
14090 delete_keyboard_wait_descriptor (dpyinfo->connection);
14092 /* Discard this display from x_display_name_list and x_display_list.
14093 We can't use Fdelq because that can quit. */
14094 if (! NILP (x_display_name_list)
14095 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14096 x_display_name_list = XCDR (x_display_name_list);
14097 else
14099 Lisp_Object tail;
14101 tail = x_display_name_list;
14102 while (CONSP (tail) && CONSP (XCDR (tail)))
14104 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14106 XCDR (tail) = XCDR (XCDR (tail));
14107 break;
14109 tail = XCDR (tail);
14113 if (next_noop_dpyinfo == dpyinfo)
14114 next_noop_dpyinfo = dpyinfo->next;
14116 if (x_display_list == dpyinfo)
14117 x_display_list = dpyinfo->next;
14118 else
14120 struct x_display_info *tail;
14122 for (tail = x_display_list; tail; tail = tail->next)
14123 if (tail->next == dpyinfo)
14124 tail->next = tail->next->next;
14127 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14128 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14129 XrmDestroyDatabase (dpyinfo->xrdb);
14130 #endif
14131 #endif
14132 #ifdef MULTI_KBOARD
14133 if (--dpyinfo->kboard->reference_count == 0)
14134 delete_kboard (dpyinfo->kboard);
14135 #endif
14136 #ifdef HAVE_X_I18N
14137 if (dpyinfo->xim)
14138 xim_close_dpy (dpyinfo);
14139 #endif
14141 xfree (dpyinfo->font_table);
14142 xfree (dpyinfo->x_id_name);
14143 xfree (dpyinfo->color_cells);
14144 xfree (dpyinfo);
14148 /* Set up use of X before we make the first connection. */
14150 static struct redisplay_interface x_redisplay_interface =
14152 x_produce_glyphs,
14153 x_write_glyphs,
14154 x_insert_glyphs,
14155 x_clear_end_of_line,
14156 x_scroll_run,
14157 x_after_update_window_line,
14158 x_update_window_begin,
14159 x_update_window_end,
14160 XTcursor_to,
14161 x_flush,
14162 x_clear_mouse_face,
14163 x_get_glyph_overhangs,
14164 x_fix_overlapping_area
14167 void
14168 x_initialize ()
14170 rif = &x_redisplay_interface;
14172 clear_frame_hook = x_clear_frame;
14173 ins_del_lines_hook = x_ins_del_lines;
14174 change_line_highlight_hook = x_change_line_highlight;
14175 delete_glyphs_hook = x_delete_glyphs;
14176 ring_bell_hook = XTring_bell;
14177 reset_terminal_modes_hook = XTreset_terminal_modes;
14178 set_terminal_modes_hook = XTset_terminal_modes;
14179 update_begin_hook = x_update_begin;
14180 update_end_hook = x_update_end;
14181 set_terminal_window_hook = XTset_terminal_window;
14182 read_socket_hook = XTread_socket;
14183 frame_up_to_date_hook = XTframe_up_to_date;
14184 reassert_line_highlight_hook = XTreassert_line_highlight;
14185 mouse_position_hook = XTmouse_position;
14186 frame_rehighlight_hook = XTframe_rehighlight;
14187 frame_raise_lower_hook = XTframe_raise_lower;
14188 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14189 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14190 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14191 judge_scroll_bars_hook = XTjudge_scroll_bars;
14192 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14194 scroll_region_ok = 1; /* we'll scroll partial frames */
14195 char_ins_del_ok = 1;
14196 line_ins_del_ok = 1; /* we'll just blt 'em */
14197 fast_clear_end_of_line = 1; /* X does this well */
14198 memory_below_frame = 0; /* we don't remember what scrolls
14199 off the bottom */
14200 baud_rate = 19200;
14202 x_noop_count = 0;
14203 last_tool_bar_item = -1;
14204 any_help_event_p = 0;
14206 /* Try to use interrupt input; if we can't, then start polling. */
14207 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14209 #ifdef USE_X_TOOLKIT
14210 XtToolkitInitialize ();
14211 Xt_app_con = XtCreateApplicationContext ();
14212 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14214 /* Install an asynchronous timer that processes Xt timeout events
14215 every 0.1s. This is necessary because some widget sets use
14216 timeouts internally, for example the LessTif menu bar, or the
14217 Xaw3d scroll bar. When Xt timouts aren't processed, these
14218 widgets don't behave normally. */
14220 EMACS_TIME interval;
14221 EMACS_SET_SECS_USECS (interval, 0, 100000);
14222 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14224 #endif
14226 #ifdef USE_TOOLKIT_SCROLL_BARS
14227 xaw3d_arrow_scroll = False;
14228 xaw3d_pick_top = True;
14229 #endif
14231 /* Note that there is no real way portable across R3/R4 to get the
14232 original error handler. */
14233 XSetErrorHandler (x_error_handler);
14234 XSetIOErrorHandler (x_io_error_quitter);
14236 /* Disable Window Change signals; they are handled by X events. */
14237 #ifdef SIGWINCH
14238 signal (SIGWINCH, SIG_DFL);
14239 #endif /* ! defined (SIGWINCH) */
14241 signal (SIGPIPE, x_connection_signal);
14245 void
14246 syms_of_xterm ()
14248 staticpro (&x_error_message_string);
14249 x_error_message_string = Qnil;
14251 staticpro (&x_display_name_list);
14252 x_display_name_list = Qnil;
14254 staticpro (&last_mouse_scroll_bar);
14255 last_mouse_scroll_bar = Qnil;
14257 staticpro (&Qvendor_specific_keysyms);
14258 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14260 staticpro (&last_mouse_press_frame);
14261 last_mouse_press_frame = Qnil;
14263 help_echo = Qnil;
14264 staticpro (&help_echo);
14265 help_echo_object = Qnil;
14266 staticpro (&help_echo_object);
14267 help_echo_window = Qnil;
14268 staticpro (&help_echo_window);
14269 previous_help_echo = Qnil;
14270 staticpro (&previous_help_echo);
14271 help_echo_pos = -1;
14273 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14274 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
14275 For example, if a block cursor is over a tab, it will be drawn as\n\
14276 wide as that tab on the display.");
14277 x_stretch_cursor_p = 0;
14279 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14280 "What X toolkit scroll bars Emacs uses.\n\
14281 A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
14282 Otherwise, value is a symbol describing the X toolkit.");
14283 #ifdef USE_TOOLKIT_SCROLL_BARS
14284 #ifdef USE_MOTIF
14285 Vx_toolkit_scroll_bars = intern ("motif");
14286 #elif defined HAVE_XAW3D
14287 Vx_toolkit_scroll_bars = intern ("xaw3d");
14288 #else
14289 Vx_toolkit_scroll_bars = intern ("xaw");
14290 #endif
14291 #else
14292 Vx_toolkit_scroll_bars = Qnil;
14293 #endif
14295 staticpro (&last_mouse_motion_frame);
14296 last_mouse_motion_frame = Qnil;
14299 #endif /* not HAVE_X_WINDOWS */