*** empty log message ***
[emacs/old-mirror.git] / src / xterm.c
blobdadc6405d2c31eb791a964d6635119b4e7fae64c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
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 #include <Xm/ScrollBarP.h>
121 #else /* !USE_MOTIF i.e. use Xaw */
123 #ifdef HAVE_XAW3D
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
132 #ifndef XtNpickTop
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
138 #endif /* USE_X_TOOLKIT */
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
143 #endif
145 #ifdef USE_X_TOOLKIT
146 #include "widget.h"
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
149 #endif
150 #endif
152 #ifndef min
153 #define min(a,b) ((a) < (b) ? (a) : (b))
154 #endif
155 #ifndef max
156 #define max(a,b) ((a) > (b) ? (a) : (b))
157 #endif
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
164 /* Bitmaps for truncated lines. */
166 enum bitmap_type
168 NO_BITMAP,
169 LEFT_TRUNCATION_BITMAP,
170 RIGHT_TRUNCATION_BITMAP,
171 OVERLAY_ARROW_BITMAP,
172 CONTINUED_LINE_BITMAP,
173 CONTINUATION_LINE_BITMAP,
174 ZV_LINE_BITMAP
177 /* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
180 #define zv_width 8
181 #define zv_height 8
182 static unsigned char zv_bits[] = {
183 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
185 /* An arrow like this: `<-'. */
187 #define left_width 8
188 #define left_height 8
189 static unsigned char left_bits[] = {
190 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
192 /* Right truncation arrow bitmap `->'. */
194 #define right_width 8
195 #define right_height 8
196 static unsigned char right_bits[] = {
197 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
199 /* Marker for continued lines. */
201 #define continued_width 8
202 #define continued_height 8
203 static unsigned char continued_bits[] = {
204 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
206 /* Marker for continuation lines. */
208 #define continuation_width 8
209 #define continuation_height 8
210 static unsigned char continuation_bits[] = {
211 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
213 /* Overlay arrow bitmap. */
215 #if 0
216 /* A bomb. */
217 #define ov_width 8
218 #define ov_height 8
219 static unsigned char ov_bits[] = {
220 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
221 #else
222 /* A triangular arrow. */
223 #define ov_width 8
224 #define ov_height 8
225 static unsigned char ov_bits[] = {
226 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
228 #endif
230 extern Lisp_Object Qhelp_echo;
233 /* Non-zero means Emacs uses toolkit scroll bars. */
235 int x_toolkit_scroll_bars_p;
237 /* If a string, XTread_socket generates an event to display that string.
238 (The display is done in read_char.) */
240 static Lisp_Object help_echo;
241 static Lisp_Object help_echo_window;
242 static Lisp_Object help_echo_object;
243 static int help_echo_pos;
245 /* Temporary variable for XTread_socket. */
247 static Lisp_Object previous_help_echo;
249 /* Non-zero means that a HELP_EVENT has been generated since Emacs
250 start. */
252 static int any_help_event_p;
254 /* Non-zero means draw block and hollow cursor as wide as the glyph
255 under it. For example, if a block cursor is over a tab, it will be
256 drawn as wide as that tab on the display. */
258 int x_stretch_cursor_p;
260 /* This is a chain of structures for all the X displays currently in
261 use. */
263 struct x_display_info *x_display_list;
265 /* This is a list of cons cells, each of the form (NAME
266 . FONT-LIST-CACHE), one for each element of x_display_list and in
267 the same order. NAME is the name of the frame. FONT-LIST-CACHE
268 records previous values returned by x-list-fonts. */
270 Lisp_Object x_display_name_list;
272 /* Frame being updated by update_frame. This is declared in term.c.
273 This is set by update_begin and looked at by all the XT functions.
274 It is zero while not inside an update. In that case, the XT
275 functions assume that `selected_frame' is the frame to apply to. */
277 extern struct frame *updating_frame;
279 extern int waiting_for_input;
281 /* This is a frame waiting to be auto-raised, within XTread_socket. */
283 struct frame *pending_autoraise_frame;
285 #ifdef USE_X_TOOLKIT
286 /* The application context for Xt use. */
287 XtAppContext Xt_app_con;
288 static String Xt_default_resources[] = {0};
289 #endif /* USE_X_TOOLKIT */
291 /* Nominal cursor position -- where to draw output.
292 HPOS and VPOS are window relative glyph matrix coordinates.
293 X and Y are window relative pixel coordinates. */
295 struct cursor_pos output_cursor;
297 /* Non-zero means user is interacting with a toolkit scroll bar. */
299 static int toolkit_scroll_bar_interaction;
301 /* Mouse movement.
303 Formerly, we used PointerMotionHintMask (in standard_event_mask)
304 so that we would have to call XQueryPointer after each MotionNotify
305 event to ask for another such event. However, this made mouse tracking
306 slow, and there was a bug that made it eventually stop.
308 Simply asking for MotionNotify all the time seems to work better.
310 In order to avoid asking for motion events and then throwing most
311 of them away or busy-polling the server for mouse positions, we ask
312 the server for pointer motion hints. This means that we get only
313 one event per group of mouse movements. "Groups" are delimited by
314 other kinds of events (focus changes and button clicks, for
315 example), or by XQueryPointer calls; when one of these happens, we
316 get another MotionNotify event the next time the mouse moves. This
317 is at least as efficient as getting motion events when mouse
318 tracking is on, and I suspect only negligibly worse when tracking
319 is off. */
321 /* Where the mouse was last time we reported a mouse event. */
323 FRAME_PTR last_mouse_frame;
324 static XRectangle last_mouse_glyph;
325 static Lisp_Object last_mouse_press_frame;
327 /* The scroll bar in which the last X motion event occurred.
329 If the last X motion event occurred in a scroll bar, we set this so
330 XTmouse_position can know whether to report a scroll bar motion or
331 an ordinary motion.
333 If the last X motion event didn't occur in a scroll bar, we set
334 this to Qnil, to tell XTmouse_position to return an ordinary motion
335 event. */
337 static Lisp_Object last_mouse_scroll_bar;
339 /* This is a hack. We would really prefer that XTmouse_position would
340 return the time associated with the position it returns, but there
341 doesn't seem to be any way to wrest the time-stamp from the server
342 along with the position query. So, we just keep track of the time
343 of the last movement we received, and return that in hopes that
344 it's somewhat accurate. */
346 static Time last_mouse_movement_time;
348 /* Incremented by XTread_socket whenever it really tries to read
349 events. */
351 #ifdef __STDC__
352 static int volatile input_signal_count;
353 #else
354 static int input_signal_count;
355 #endif
357 /* Used locally within XTread_socket. */
359 static int x_noop_count;
361 /* Initial values of argv and argc. */
363 extern char **initial_argv;
364 extern int initial_argc;
366 extern Lisp_Object Vcommand_line_args, Vsystem_name;
368 /* Tells if a window manager is present or not. */
370 extern Lisp_Object Vx_no_window_manager;
372 extern Lisp_Object Qface, Qmouse_face;
374 extern int errno;
376 /* A mask of extra modifier bits to put into every keyboard char. */
378 extern int extra_keyboard_modifiers;
380 static Lisp_Object Qvendor_specific_keysyms;
382 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
383 extern Lisp_Object x_icon_type P_ ((struct frame *));
386 /* Enumeration for overriding/changing the face to use for drawing
387 glyphs in x_draw_glyphs. */
389 enum draw_glyphs_face
391 DRAW_NORMAL_TEXT,
392 DRAW_INVERSE_VIDEO,
393 DRAW_CURSOR,
394 DRAW_MOUSE_FACE,
395 DRAW_IMAGE_RAISED,
396 DRAW_IMAGE_SUNKEN
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 void set_output_cursor P_ ((struct cursor_pos *));
408 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
409 int *, int *, int *));
410 static void note_mode_line_highlight P_ ((struct window *, int, int));
411 static void note_mouse_highlight P_ ((struct frame *, int, int));
412 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
413 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
414 static void show_mouse_face P_ ((struct x_display_info *,
415 enum draw_glyphs_face));
416 static int x_io_error_quitter P_ ((Display *));
417 int x_catch_errors P_ ((Display *));
418 void x_uncatch_errors P_ ((Display *, int));
419 void x_lower_frame P_ ((struct frame *));
420 void x_scroll_bar_clear P_ ((struct frame *));
421 int x_had_errors_p P_ ((Display *));
422 void x_wm_set_size_hint P_ ((struct frame *, long, int));
423 void x_raise_frame P_ ((struct frame *));
424 void x_set_window_size P_ ((struct frame *, int, int, int));
425 void x_wm_set_window_state P_ ((struct frame *, int));
426 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
427 void x_initialize P_ ((void));
428 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
429 static int x_compute_min_glyph_bounds P_ ((struct frame *));
430 static void x_draw_phys_cursor_glyph P_ ((struct window *,
431 struct glyph_row *,
432 enum draw_glyphs_face));
433 static void x_update_end P_ ((struct frame *));
434 static void XTframe_up_to_date P_ ((struct frame *));
435 static void XTreassert_line_highlight P_ ((int, int));
436 static void x_change_line_highlight P_ ((int, int, int, int));
437 static void XTset_terminal_modes P_ ((void));
438 static void XTreset_terminal_modes P_ ((void));
439 static void XTcursor_to P_ ((int, int, int, int));
440 static void x_write_glyphs P_ ((struct glyph *, int));
441 static void x_clear_end_of_line P_ ((int));
442 static void x_clear_frame P_ ((void));
443 static void x_clear_cursor P_ ((struct window *));
444 static void frame_highlight P_ ((struct frame *));
445 static void frame_unhighlight P_ ((struct frame *));
446 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
447 static void XTframe_rehighlight P_ ((struct frame *));
448 static void x_frame_rehighlight P_ ((struct x_display_info *));
449 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
450 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
451 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
452 XRectangle *));
453 static void expose_frame P_ ((struct frame *, int, int, int, int));
454 static void expose_window_tree P_ ((struct window *, XRectangle *));
455 static void expose_window P_ ((struct window *, XRectangle *));
456 static void expose_area P_ ((struct window *, struct glyph_row *,
457 XRectangle *, enum glyph_row_area));
458 static void expose_line P_ ((struct window *, struct glyph_row *,
459 XRectangle *));
460 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
461 static void x_update_window_cursor P_ ((struct window *, int));
462 static void x_erase_phys_cursor P_ ((struct window *));
463 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
464 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
465 enum bitmap_type));
467 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
468 GC, int));
469 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
470 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
471 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
472 static void x_flush P_ ((struct frame *f));
473 static void x_update_begin P_ ((struct frame *));
474 static void x_update_window_begin P_ ((struct window *));
475 static void x_draw_vertical_border P_ ((struct window *));
476 static void x_after_update_window_line P_ ((struct glyph_row *));
477 static INLINE void take_vertical_position_into_account P_ ((struct it *));
478 static void x_produce_stretch_glyph P_ ((struct it *));
481 /* Flush display of frame F, or of all frames if F is null. */
483 static void
484 x_flush (f)
485 struct frame *f;
487 BLOCK_INPUT;
488 if (f == NULL)
490 Lisp_Object rest, frame;
491 FOR_EACH_FRAME (rest, frame)
492 x_flush (XFRAME (frame));
494 else if (FRAME_X_P (f))
495 XFlush (FRAME_X_DISPLAY (f));
496 UNBLOCK_INPUT;
500 /* Remove calls to XFlush by defining XFlush to an empty replacement.
501 Calls to XFlush should be unnecessary because the X output buffer
502 is flushed automatically as needed by calls to XPending,
503 XNextEvent, or XWindowEvent according to the XFlush man page.
504 XTread_socket calls XPending. Removing XFlush improves
505 performance. */
507 #define XFlush(DISPLAY) (void) 0
510 /***********************************************************************
511 Debugging
512 ***********************************************************************/
514 #if 0
516 /* This is a function useful for recording debugging information about
517 the sequence of occurrences in this file. */
519 struct record
521 char *locus;
522 int type;
525 struct record event_record[100];
527 int event_record_index;
529 record_event (locus, type)
530 char *locus;
531 int type;
533 if (event_record_index == sizeof (event_record) / sizeof (struct record))
534 event_record_index = 0;
536 event_record[event_record_index].locus = locus;
537 event_record[event_record_index].type = type;
538 event_record_index++;
541 #endif /* 0 */
545 /* Return the struct x_display_info corresponding to DPY. */
547 struct x_display_info *
548 x_display_info_for_display (dpy)
549 Display *dpy;
551 struct x_display_info *dpyinfo;
553 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
554 if (dpyinfo->display == dpy)
555 return dpyinfo;
557 return 0;
562 /***********************************************************************
563 Starting and ending an update
564 ***********************************************************************/
566 /* Start an update of frame F. This function is installed as a hook
567 for update_begin, i.e. it is called when update_begin is called.
568 This function is called prior to calls to x_update_window_begin for
569 each window being updated. Currently, there is nothing to do here
570 because all interesting stuff is done on a window basis. */
572 static void
573 x_update_begin (f)
574 struct frame *f;
576 /* Nothing to do. */
580 /* Start update of window W. Set the global variable updated_window
581 to the window being updated and set output_cursor to the cursor
582 position of W. */
584 static void
585 x_update_window_begin (w)
586 struct window *w;
588 struct frame *f = XFRAME (WINDOW_FRAME (w));
589 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
591 updated_window = w;
592 set_output_cursor (&w->cursor);
594 BLOCK_INPUT;
596 if (f == display_info->mouse_face_mouse_frame)
598 /* Don't do highlighting for mouse motion during the update. */
599 display_info->mouse_face_defer = 1;
601 /* If F needs to be redrawn, simply forget about any prior mouse
602 highlighting. */
603 if (FRAME_GARBAGED_P (f))
604 display_info->mouse_face_window = Qnil;
606 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
607 their mouse_face_p flag set, which means that they are always
608 unequal to rows in a desired matrix which never have that
609 flag set. So, rows containing mouse-face glyphs are never
610 scrolled, and we don't have to switch the mouse highlight off
611 here to prevent it from being scrolled. */
613 /* Can we tell that this update does not affect the window
614 where the mouse highlight is? If so, no need to turn off.
615 Likewise, don't do anything if the frame is garbaged;
616 in that case, the frame's current matrix that we would use
617 is all wrong, and we will redisplay that line anyway. */
618 if (!NILP (display_info->mouse_face_window)
619 && w == XWINDOW (display_info->mouse_face_window))
621 int i;
623 for (i = 0; i < w->desired_matrix->nrows; ++i)
624 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
625 break;
627 if (i < w->desired_matrix->nrows)
628 clear_mouse_face (display_info);
630 #endif /* 0 */
633 UNBLOCK_INPUT;
637 /* Draw a vertical window border to the right of window W if W doesn't
638 have vertical scroll bars. */
640 static void
641 x_draw_vertical_border (w)
642 struct window *w;
644 struct frame *f = XFRAME (WINDOW_FRAME (w));
646 /* Redraw borders between horizontally adjacent windows. Don't
647 do it for frames with vertical scroll bars because either the
648 right scroll bar of a window, or the left scroll bar of its
649 neighbor will suffice as a border. */
650 if (!WINDOW_RIGHTMOST_P (w)
651 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
653 int x0, x1, y0, y1;
655 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
656 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
657 y1 -= 1;
659 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
660 f->output_data.x->normal_gc, x1, y0, x1, y1);
665 /* End update of window W (which is equal to updated_window).
667 Draw vertical borders between horizontally adjacent windows, and
668 display W's cursor if CURSOR_ON_P is non-zero.
670 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
671 glyphs in mouse-face were overwritten. In that case we have to
672 make sure that the mouse-highlight is properly redrawn.
674 W may be a menu bar pseudo-window in case we don't have X toolkit
675 support. Such windows don't have a cursor, so don't display it
676 here. */
678 static void
679 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
680 struct window *w;
681 int cursor_on_p, mouse_face_overwritten_p;
683 if (!w->pseudo_window_p)
685 struct x_display_info *dpyinfo
686 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
688 BLOCK_INPUT;
690 /* If a row with mouse-face was overwritten, arrange for
691 XTframe_up_to_date to redisplay the mouse highlight. */
692 if (mouse_face_overwritten_p)
694 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
695 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
696 dpyinfo->mouse_face_window = Qnil;
699 if (cursor_on_p)
700 x_display_and_set_cursor (w, 1, output_cursor.hpos,
701 output_cursor.vpos,
702 output_cursor.x, output_cursor.y);
704 x_draw_vertical_border (w);
705 UNBLOCK_INPUT;
708 updated_window = NULL;
712 /* End update of frame F. This function is installed as a hook in
713 update_end. */
715 static void
716 x_update_end (f)
717 struct frame *f;
719 /* Mouse highlight may be displayed again. */
720 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
722 BLOCK_INPUT;
723 XFlush (FRAME_X_DISPLAY (f));
724 UNBLOCK_INPUT;
728 /* This function is called from various places in xdisp.c whenever a
729 complete update has been performed. The global variable
730 updated_window is not available here. */
732 static void
733 XTframe_up_to_date (f)
734 struct frame *f;
736 if (FRAME_X_P (f))
738 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
740 if (dpyinfo->mouse_face_deferred_gc
741 || f == dpyinfo->mouse_face_mouse_frame)
743 BLOCK_INPUT;
744 if (dpyinfo->mouse_face_mouse_frame)
745 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
746 dpyinfo->mouse_face_mouse_x,
747 dpyinfo->mouse_face_mouse_y);
748 dpyinfo->mouse_face_deferred_gc = 0;
749 UNBLOCK_INPUT;
755 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
756 arrow bitmaps, or clear the areas where they would be displayed
757 before DESIRED_ROW is made current. The window being updated is
758 found in updated_window. This function It is called from
759 update_window_line only if it is known that there are differences
760 between bitmaps to be drawn between current row and DESIRED_ROW. */
762 static void
763 x_after_update_window_line (desired_row)
764 struct glyph_row *desired_row;
766 struct window *w = updated_window;
768 xassert (w);
770 if (!desired_row->mode_line_p && !w->pseudo_window_p)
772 BLOCK_INPUT;
773 x_draw_row_bitmaps (w, desired_row);
775 /* When a window has disappeared, make sure that no rest of
776 full-width rows stays visible in the internal border. */
777 if (windows_or_buffers_changed)
779 struct frame *f = XFRAME (w->frame);
780 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
781 int height = desired_row->visible_height;
782 int x = (window_box_right (w, -1)
783 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
784 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
786 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
787 x, y, width, height, False);
790 UNBLOCK_INPUT;
795 /* Draw the bitmap WHICH in one of the areas to the left or right of
796 window W. ROW is the glyph row for which to display the bitmap; it
797 determines the vertical position at which the bitmap has to be
798 drawn. */
800 static void
801 x_draw_bitmap (w, row, which)
802 struct window *w;
803 struct glyph_row *row;
804 enum bitmap_type which;
806 struct frame *f = XFRAME (WINDOW_FRAME (w));
807 Display *display = FRAME_X_DISPLAY (f);
808 Window window = FRAME_X_WINDOW (f);
809 int x, y, wd, h, dy;
810 unsigned char *bits;
811 Pixmap pixmap;
812 GC gc = f->output_data.x->normal_gc;
813 struct face *face;
814 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
816 /* Must clip because of partially visible lines. */
817 x_clip_to_row (w, row, gc, 1);
819 switch (which)
821 case LEFT_TRUNCATION_BITMAP:
822 wd = left_width;
823 h = left_height;
824 bits = left_bits;
825 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
826 - wd
827 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
828 break;
830 case OVERLAY_ARROW_BITMAP:
831 wd = left_width;
832 h = left_height;
833 bits = ov_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 RIGHT_TRUNCATION_BITMAP:
840 wd = right_width;
841 h = right_height;
842 bits = right_bits;
843 x = window_box_right (w, -1);
844 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
845 break;
847 case CONTINUED_LINE_BITMAP:
848 wd = right_width;
849 h = right_height;
850 bits = continued_bits;
851 x = window_box_right (w, -1);
852 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
853 break;
855 case CONTINUATION_LINE_BITMAP:
856 wd = continuation_width;
857 h = continuation_height;
858 bits = continuation_bits;
859 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
860 - wd
861 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
862 break;
864 case ZV_LINE_BITMAP:
865 wd = zv_width;
866 h = zv_height;
867 bits = zv_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 default:
874 abort ();
877 /* Convert to frame coordinates. Set dy to the offset in the row to
878 start drawing the bitmap. */
879 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
880 dy = (row->height - h) / 2;
882 /* Draw the bitmap. I believe these small pixmaps can be cached
883 by the server. */
884 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
885 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
886 face->foreground,
887 face->background, depth);
888 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
889 XFreePixmap (display, pixmap);
890 XSetClipMask (display, gc, None);
894 /* Draw flags bitmaps for glyph row ROW on window W. Call this
895 function with input blocked. */
897 static void
898 x_draw_row_bitmaps (w, row)
899 struct window *w;
900 struct glyph_row *row;
902 struct frame *f = XFRAME (w->frame);
903 enum bitmap_type bitmap;
904 struct face *face;
905 int header_line_height = -1;
907 xassert (interrupt_input_blocked);
909 /* If row is completely invisible, because of vscrolling, we
910 don't have to draw anything. */
911 if (row->visible_height <= 0)
912 return;
914 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
915 PREPARE_FACE_FOR_DISPLAY (f, face);
917 /* Decide which bitmap to draw at the left side. */
918 if (row->overlay_arrow_p)
919 bitmap = OVERLAY_ARROW_BITMAP;
920 else if (row->truncated_on_left_p)
921 bitmap = LEFT_TRUNCATION_BITMAP;
922 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
923 bitmap = CONTINUATION_LINE_BITMAP;
924 else if (row->indicate_empty_line_p)
925 bitmap = ZV_LINE_BITMAP;
926 else
927 bitmap = NO_BITMAP;
929 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
930 the flags area. */
931 if (bitmap == NO_BITMAP
932 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
933 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
935 /* If W has a vertical border to its left, don't draw over it. */
936 int border = ((XFASTINT (w->left) > 0
937 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
938 ? 1 : 0);
939 int left = window_box_left (w, -1);
941 if (header_line_height < 0)
942 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
944 /* In case the same realized face is used for bitmap areas and
945 for something displayed in the text (e.g. face `region' on
946 mono-displays, the fill style may have been changed to
947 FillSolid in x_draw_glyph_string_background. */
948 if (face->stipple)
949 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
950 else
951 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
953 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
954 face->gc,
955 (left
956 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
957 + border),
958 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
959 row->y)),
960 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
961 row->visible_height);
962 if (!face->stipple)
963 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
966 /* Draw the left bitmap. */
967 if (bitmap != NO_BITMAP)
968 x_draw_bitmap (w, row, bitmap);
970 /* Decide which bitmap to draw at the right side. */
971 if (row->truncated_on_right_p)
972 bitmap = RIGHT_TRUNCATION_BITMAP;
973 else if (row->continued_p)
974 bitmap = CONTINUED_LINE_BITMAP;
975 else
976 bitmap = NO_BITMAP;
978 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
979 the flags area. */
980 if (bitmap == NO_BITMAP
981 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
982 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
984 int right = window_box_right (w, -1);
986 if (header_line_height < 0)
987 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
989 /* In case the same realized face is used for bitmap areas and
990 for something displayed in the text (e.g. face `region' on
991 mono-displays, the fill style may have been changed to
992 FillSolid in x_draw_glyph_string_background. */
993 if (face->stipple)
994 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
995 else
996 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
997 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
998 face->gc,
999 right,
1000 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1001 row->y)),
1002 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1003 row->visible_height);
1004 if (!face->stipple)
1005 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1008 /* Draw the right bitmap. */
1009 if (bitmap != NO_BITMAP)
1010 x_draw_bitmap (w, row, bitmap);
1014 /***********************************************************************
1015 Line Highlighting
1016 ***********************************************************************/
1018 /* External interface to control of standout mode. Not used for X
1019 frames. Aborts when called. */
1021 static void
1022 XTreassert_line_highlight (new, vpos)
1023 int new, vpos;
1025 abort ();
1029 /* Call this when about to modify line at position VPOS and change
1030 whether it is highlighted. Not used for X frames. Aborts when
1031 called. */
1033 static void
1034 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1035 int new_highlight, vpos, y, first_unused_hpos;
1037 abort ();
1041 /* This is called when starting Emacs and when restarting after
1042 suspend. When starting Emacs, no X window is mapped. And nothing
1043 must be done to Emacs's own window if it is suspended (though that
1044 rarely happens). */
1046 static void
1047 XTset_terminal_modes ()
1051 /* This is called when exiting or suspending Emacs. Exiting will make
1052 the X-windows go away, and suspending requires no action. */
1054 static void
1055 XTreset_terminal_modes ()
1061 /***********************************************************************
1062 Output Cursor
1063 ***********************************************************************/
1065 /* Set the global variable output_cursor to CURSOR. All cursor
1066 positions are relative to updated_window. */
1068 static void
1069 set_output_cursor (cursor)
1070 struct cursor_pos *cursor;
1072 output_cursor.hpos = cursor->hpos;
1073 output_cursor.vpos = cursor->vpos;
1074 output_cursor.x = cursor->x;
1075 output_cursor.y = cursor->y;
1079 /* Set a nominal cursor position.
1081 HPOS and VPOS are column/row positions in a window glyph matrix. X
1082 and Y are window text area relative pixel positions.
1084 If this is done during an update, updated_window will contain the
1085 window that is being updated and the position is the future output
1086 cursor position for that window. If updated_window is null, use
1087 selected_window and display the cursor at the given position. */
1089 static void
1090 XTcursor_to (vpos, hpos, y, x)
1091 int vpos, hpos, y, x;
1093 struct window *w;
1095 /* If updated_window is not set, work on selected_window. */
1096 if (updated_window)
1097 w = updated_window;
1098 else
1099 w = XWINDOW (selected_window);
1101 /* Set the output cursor. */
1102 output_cursor.hpos = hpos;
1103 output_cursor.vpos = vpos;
1104 output_cursor.x = x;
1105 output_cursor.y = y;
1107 /* If not called as part of an update, really display the cursor.
1108 This will also set the cursor position of W. */
1109 if (updated_window == NULL)
1111 BLOCK_INPUT;
1112 x_display_cursor (w, 1, hpos, vpos, x, y);
1113 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1114 UNBLOCK_INPUT;
1120 /***********************************************************************
1121 Display Iterator
1122 ***********************************************************************/
1124 /* Function prototypes of this page. */
1126 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1127 struct glyph *,
1128 XChar2b *,
1129 int *));
1130 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1131 int, XChar2b *, int));
1132 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1133 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1134 static void x_append_glyph P_ ((struct it *));
1135 static void x_append_composite_glyph P_ ((struct it *));
1136 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1137 int, int, double));
1138 static void x_produce_glyphs P_ ((struct it *));
1139 static void x_produce_image_glyph P_ ((struct it *it));
1142 /* Return a pointer to per-char metric information in FONT of a
1143 character pointed by B which is a pointer to an XChar2b. */
1145 #define PER_CHAR_METRIC(font, b) \
1146 ((font)->per_char \
1147 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1148 + (((font)->min_byte1 || (font)->max_byte1) \
1149 ? (((b)->byte1 - (font)->min_byte1) \
1150 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1151 : 0)) \
1152 : &((font)->max_bounds))
1155 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1156 is not contained in the font. */
1158 static INLINE XCharStruct *
1159 x_per_char_metric (font, char2b)
1160 XFontStruct *font;
1161 XChar2b *char2b;
1163 /* The result metric information. */
1164 XCharStruct *pcm = NULL;
1166 xassert (font && char2b);
1168 if (font->per_char != NULL)
1170 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1172 /* min_char_or_byte2 specifies the linear character index
1173 corresponding to the first element of the per_char array,
1174 max_char_or_byte2 is the index of the last character. A
1175 character with non-zero CHAR2B->byte1 is not in the font.
1176 A character with byte2 less than min_char_or_byte2 or
1177 greater max_char_or_byte2 is not in the font. */
1178 if (char2b->byte1 == 0
1179 && char2b->byte2 >= font->min_char_or_byte2
1180 && char2b->byte2 <= font->max_char_or_byte2)
1181 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1183 else
1185 /* If either min_byte1 or max_byte1 are nonzero, both
1186 min_char_or_byte2 and max_char_or_byte2 are less than
1187 256, and the 2-byte character index values corresponding
1188 to the per_char array element N (counting from 0) are:
1190 byte1 = N/D + min_byte1
1191 byte2 = N\D + min_char_or_byte2
1193 where:
1195 D = max_char_or_byte2 - min_char_or_byte2 + 1
1196 / = integer division
1197 \ = integer modulus */
1198 if (char2b->byte1 >= font->min_byte1
1199 && char2b->byte1 <= font->max_byte1
1200 && char2b->byte2 >= font->min_char_or_byte2
1201 && char2b->byte2 <= font->max_char_or_byte2)
1203 pcm = (font->per_char
1204 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1205 * (char2b->byte1 - font->min_byte1))
1206 + (char2b->byte2 - font->min_char_or_byte2));
1210 else
1212 /* If the per_char pointer is null, all glyphs between the first
1213 and last character indexes inclusive have the same
1214 information, as given by both min_bounds and max_bounds. */
1215 if (char2b->byte2 >= font->min_char_or_byte2
1216 && char2b->byte2 <= font->max_char_or_byte2)
1217 pcm = &font->max_bounds;
1220 return ((pcm == NULL
1221 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1222 ? NULL : pcm);
1226 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1227 the two-byte form of C. Encoding is returned in *CHAR2B. */
1229 static INLINE void
1230 x_encode_char (c, char2b, font_info)
1231 int c;
1232 XChar2b *char2b;
1233 struct font_info *font_info;
1235 int charset = CHAR_CHARSET (c);
1236 XFontStruct *font = font_info->font;
1238 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1239 This may be either a program in a special encoder language or a
1240 fixed encoding. */
1241 if (font_info->font_encoder)
1243 /* It's a program. */
1244 struct ccl_program *ccl = font_info->font_encoder;
1246 if (CHARSET_DIMENSION (charset) == 1)
1248 ccl->reg[0] = charset;
1249 ccl->reg[1] = char2b->byte2;
1251 else
1253 ccl->reg[0] = charset;
1254 ccl->reg[1] = char2b->byte1;
1255 ccl->reg[2] = char2b->byte2;
1258 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1260 /* We assume that MSBs are appropriately set/reset by CCL
1261 program. */
1262 if (font->max_byte1 == 0) /* 1-byte font */
1263 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1264 else
1265 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1267 else if (font_info->encoding[charset])
1269 /* Fixed encoding scheme. See fontset.h for the meaning of the
1270 encoding numbers. */
1271 int enc = font_info->encoding[charset];
1273 if ((enc == 1 || enc == 2)
1274 && CHARSET_DIMENSION (charset) == 2)
1275 char2b->byte1 |= 0x80;
1277 if (enc == 1 || enc == 3)
1278 char2b->byte2 |= 0x80;
1283 /* Get face and two-byte form of character C in face FACE_ID on frame
1284 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1285 means we want to display multibyte text. Value is a pointer to a
1286 realized face that is ready for display. */
1288 static INLINE struct face *
1289 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1290 struct frame *f;
1291 int c, face_id;
1292 XChar2b *char2b;
1293 int multibyte_p;
1295 struct face *face = FACE_FROM_ID (f, face_id);
1297 if (!multibyte_p)
1299 /* Unibyte case. We don't have to encode, but we have to make
1300 sure to use a face suitable for unibyte. */
1301 char2b->byte1 = 0;
1302 char2b->byte2 = c;
1303 face_id = FACE_FOR_CHAR (f, face, c);
1304 face = FACE_FROM_ID (f, face_id);
1306 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1308 /* Case of ASCII in a face known to fit ASCII. */
1309 char2b->byte1 = 0;
1310 char2b->byte2 = c;
1312 else
1314 int c1, c2, charset;
1316 /* Split characters into bytes. If c2 is -1 afterwards, C is
1317 really a one-byte character so that byte1 is zero. */
1318 SPLIT_CHAR (c, charset, c1, c2);
1319 if (c2 > 0)
1320 char2b->byte1 = c1, char2b->byte2 = c2;
1321 else
1322 char2b->byte1 = 0, char2b->byte2 = c1;
1324 /* Maybe encode the character in *CHAR2B. */
1325 if (face->font != NULL)
1327 struct font_info *font_info
1328 = FONT_INFO_FROM_ID (f, face->font_info_id);
1329 if (font_info)
1330 x_encode_char (c, char2b, font_info);
1334 /* Make sure X resources of the face are allocated. */
1335 xassert (face != NULL);
1336 PREPARE_FACE_FOR_DISPLAY (f, face);
1338 return face;
1342 /* Get face and two-byte form of character glyph GLYPH on frame F.
1343 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1344 a pointer to a realized face that is ready for display. */
1346 static INLINE struct face *
1347 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1348 struct frame *f;
1349 struct glyph *glyph;
1350 XChar2b *char2b;
1351 int *two_byte_p;
1353 struct face *face;
1355 xassert (glyph->type == CHAR_GLYPH);
1356 face = FACE_FROM_ID (f, glyph->face_id);
1358 if (two_byte_p)
1359 *two_byte_p = 0;
1361 if (!glyph->multibyte_p)
1363 /* Unibyte case. We don't have to encode, but we have to make
1364 sure to use a face suitable for unibyte. */
1365 char2b->byte1 = 0;
1366 char2b->byte2 = glyph->u.ch;
1368 else if (glyph->u.ch < 128
1369 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1371 /* Case of ASCII in a face known to fit ASCII. */
1372 char2b->byte1 = 0;
1373 char2b->byte2 = glyph->u.ch;
1375 else
1377 int c1, c2, charset;
1379 /* Split characters into bytes. If c2 is -1 afterwards, C is
1380 really a one-byte character so that byte1 is zero. */
1381 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1382 if (c2 > 0)
1383 char2b->byte1 = c1, char2b->byte2 = c2;
1384 else
1385 char2b->byte1 = 0, char2b->byte2 = c1;
1387 /* Maybe encode the character in *CHAR2B. */
1388 if (charset != CHARSET_ASCII)
1390 struct font_info *font_info
1391 = FONT_INFO_FROM_ID (f, face->font_info_id);
1392 if (font_info)
1394 x_encode_char (glyph->u.ch, char2b, font_info);
1395 if (two_byte_p)
1396 *two_byte_p
1397 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1402 /* Make sure X resources of the face are allocated. */
1403 xassert (face != NULL);
1404 PREPARE_FACE_FOR_DISPLAY (f, face);
1405 return face;
1409 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1410 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1412 static INLINE void
1413 x_append_glyph (it)
1414 struct it *it;
1416 struct glyph *glyph;
1417 enum glyph_row_area area = it->area;
1419 xassert (it->glyph_row);
1420 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1422 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1423 if (glyph < it->glyph_row->glyphs[area + 1])
1425 glyph->charpos = CHARPOS (it->position);
1426 glyph->object = it->object;
1427 glyph->pixel_width = it->pixel_width;
1428 glyph->voffset = it->voffset;
1429 glyph->type = CHAR_GLYPH;
1430 glyph->multibyte_p = it->multibyte_p;
1431 glyph->left_box_line_p = it->start_of_box_run_p;
1432 glyph->right_box_line_p = it->end_of_box_run_p;
1433 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1434 || it->phys_descent > it->descent);
1435 glyph->padding_p = 0;
1436 glyph->glyph_not_available_p = it->glyph_not_available_p;
1437 glyph->face_id = it->face_id;
1438 glyph->u.ch = it->char_to_display;
1439 ++it->glyph_row->used[area];
1443 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1444 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1446 static INLINE void
1447 x_append_composite_glyph (it)
1448 struct it *it;
1450 struct glyph *glyph;
1451 enum glyph_row_area area = it->area;
1453 xassert (it->glyph_row);
1455 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1456 if (glyph < it->glyph_row->glyphs[area + 1])
1458 glyph->charpos = CHARPOS (it->position);
1459 glyph->object = it->object;
1460 glyph->pixel_width = it->pixel_width;
1461 glyph->voffset = it->voffset;
1462 glyph->type = COMPOSITE_GLYPH;
1463 glyph->multibyte_p = it->multibyte_p;
1464 glyph->left_box_line_p = it->start_of_box_run_p;
1465 glyph->right_box_line_p = it->end_of_box_run_p;
1466 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1467 || it->phys_descent > it->descent);
1468 glyph->padding_p = 0;
1469 glyph->glyph_not_available_p = 0;
1470 glyph->face_id = it->face_id;
1471 glyph->u.cmp_id = it->cmp_id;
1472 ++it->glyph_row->used[area];
1477 /* Change IT->ascent and IT->height according to the setting of
1478 IT->voffset. */
1480 static INLINE void
1481 take_vertical_position_into_account (it)
1482 struct it *it;
1484 if (it->voffset)
1486 if (it->voffset < 0)
1487 /* Increase the ascent so that we can display the text higher
1488 in the line. */
1489 it->ascent += abs (it->voffset);
1490 else
1491 /* Increase the descent so that we can display the text lower
1492 in the line. */
1493 it->descent += it->voffset;
1498 /* Produce glyphs/get display metrics for the image IT is loaded with.
1499 See the description of struct display_iterator in dispextern.h for
1500 an overview of struct display_iterator. */
1502 static void
1503 x_produce_image_glyph (it)
1504 struct it *it;
1506 struct image *img;
1507 struct face *face;
1509 xassert (it->what == IT_IMAGE);
1511 face = FACE_FROM_ID (it->f, it->face_id);
1512 img = IMAGE_FROM_ID (it->f, it->image_id);
1513 xassert (img);
1515 /* Make sure X resources of the face and image are loaded. */
1516 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1517 prepare_image_for_display (it->f, img);
1519 it->ascent = it->phys_ascent = image_ascent (img, face);
1520 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1521 it->pixel_width = img->width + 2 * img->margin;
1523 it->nglyphs = 1;
1525 if (face->box != FACE_NO_BOX)
1527 it->ascent += face->box_line_width;
1528 it->descent += face->box_line_width;
1530 if (it->start_of_box_run_p)
1531 it->pixel_width += face->box_line_width;
1532 if (it->end_of_box_run_p)
1533 it->pixel_width += face->box_line_width;
1536 take_vertical_position_into_account (it);
1538 if (it->glyph_row)
1540 struct glyph *glyph;
1541 enum glyph_row_area area = it->area;
1543 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1544 if (glyph < it->glyph_row->glyphs[area + 1])
1546 glyph->charpos = CHARPOS (it->position);
1547 glyph->object = it->object;
1548 glyph->pixel_width = it->pixel_width;
1549 glyph->voffset = it->voffset;
1550 glyph->type = IMAGE_GLYPH;
1551 glyph->multibyte_p = it->multibyte_p;
1552 glyph->left_box_line_p = it->start_of_box_run_p;
1553 glyph->right_box_line_p = it->end_of_box_run_p;
1554 glyph->overlaps_vertically_p = 0;
1555 glyph->padding_p = 0;
1556 glyph->glyph_not_available_p = 0;
1557 glyph->face_id = it->face_id;
1558 glyph->u.img_id = img->id;
1559 ++it->glyph_row->used[area];
1565 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1566 of the glyph, WIDTH and HEIGHT are the width and height of the
1567 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1568 ascent of the glyph (0 <= ASCENT <= 1). */
1570 static void
1571 x_append_stretch_glyph (it, object, width, height, ascent)
1572 struct it *it;
1573 Lisp_Object object;
1574 int width, height;
1575 double ascent;
1577 struct glyph *glyph;
1578 enum glyph_row_area area = it->area;
1580 xassert (ascent >= 0 && ascent <= 1);
1582 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1583 if (glyph < it->glyph_row->glyphs[area + 1])
1585 glyph->charpos = CHARPOS (it->position);
1586 glyph->object = object;
1587 glyph->pixel_width = width;
1588 glyph->voffset = it->voffset;
1589 glyph->type = STRETCH_GLYPH;
1590 glyph->multibyte_p = it->multibyte_p;
1591 glyph->left_box_line_p = it->start_of_box_run_p;
1592 glyph->right_box_line_p = it->end_of_box_run_p;
1593 glyph->overlaps_vertically_p = 0;
1594 glyph->padding_p = 0;
1595 glyph->glyph_not_available_p = 0;
1596 glyph->face_id = it->face_id;
1597 glyph->u.stretch.ascent = height * ascent;
1598 glyph->u.stretch.height = height;
1599 ++it->glyph_row->used[area];
1604 /* Produce a stretch glyph for iterator IT. IT->object is the value
1605 of the glyph property displayed. The value must be a list
1606 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1607 being recognized:
1609 1. `:width WIDTH' specifies that the space should be WIDTH *
1610 canonical char width wide. WIDTH may be an integer or floating
1611 point number.
1613 2. `:relative-width FACTOR' specifies that the width of the stretch
1614 should be computed from the width of the first character having the
1615 `glyph' property, and should be FACTOR times that width.
1617 3. `:align-to HPOS' specifies that the space should be wide enough
1618 to reach HPOS, a value in canonical character units.
1620 Exactly one of the above pairs must be present.
1622 4. `:height HEIGHT' specifies that the height of the stretch produced
1623 should be HEIGHT, measured in canonical character units.
1625 5. `:relative-height FACTOR' specifies that the height of the the
1626 stretch should be FACTOR times the height of the characters having
1627 the glyph property.
1629 Either none or exactly one of 4 or 5 must be present.
1631 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1632 of the stretch should be used for the ascent of the stretch.
1633 ASCENT must be in the range 0 <= ASCENT <= 100. */
1635 #define NUMVAL(X) \
1636 ((INTEGERP (X) || FLOATP (X)) \
1637 ? XFLOATINT (X) \
1638 : - 1)
1641 static void
1642 x_produce_stretch_glyph (it)
1643 struct it *it;
1645 /* (space :width WIDTH :height HEIGHT. */
1646 #if GLYPH_DEBUG
1647 extern Lisp_Object Qspace;
1648 #endif
1649 extern Lisp_Object QCwidth, QCheight, QCascent;
1650 extern Lisp_Object QCrelative_width, QCrelative_height;
1651 extern Lisp_Object QCalign_to;
1652 Lisp_Object prop, plist;
1653 double width = 0, height = 0, ascent = 0;
1654 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1655 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1657 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1659 /* List should start with `space'. */
1660 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1661 plist = XCDR (it->object);
1663 /* Compute the width of the stretch. */
1664 if (prop = Fplist_get (plist, QCwidth),
1665 NUMVAL (prop) > 0)
1666 /* Absolute width `:width WIDTH' specified and valid. */
1667 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1668 else if (prop = Fplist_get (plist, QCrelative_width),
1669 NUMVAL (prop) > 0)
1671 /* Relative width `:relative-width FACTOR' specified and valid.
1672 Compute the width of the characters having the `glyph'
1673 property. */
1674 struct it it2;
1675 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1677 it2 = *it;
1678 if (it->multibyte_p)
1680 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1681 - IT_BYTEPOS (*it));
1682 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1684 else
1685 it2.c = *p, it2.len = 1;
1687 it2.glyph_row = NULL;
1688 it2.what = IT_CHARACTER;
1689 x_produce_glyphs (&it2);
1690 width = NUMVAL (prop) * it2.pixel_width;
1692 else if (prop = Fplist_get (plist, QCalign_to),
1693 NUMVAL (prop) > 0)
1694 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1695 else
1696 /* Nothing specified -> width defaults to canonical char width. */
1697 width = CANON_X_UNIT (it->f);
1699 /* Compute height. */
1700 if (prop = Fplist_get (plist, QCheight),
1701 NUMVAL (prop) > 0)
1702 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1703 else if (prop = Fplist_get (plist, QCrelative_height),
1704 NUMVAL (prop) > 0)
1705 height = FONT_HEIGHT (font) * NUMVAL (prop);
1706 else
1707 height = FONT_HEIGHT (font);
1709 /* Compute percentage of height used for ascent. If
1710 `:ascent ASCENT' is present and valid, use that. Otherwise,
1711 derive the ascent from the font in use. */
1712 if (prop = Fplist_get (plist, QCascent),
1713 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1714 ascent = NUMVAL (prop) / 100.0;
1715 else
1716 ascent = (double) font->ascent / FONT_HEIGHT (font);
1718 if (width <= 0)
1719 width = 1;
1720 if (height <= 0)
1721 height = 1;
1723 if (it->glyph_row)
1725 Lisp_Object object = it->stack[it->sp - 1].string;
1726 if (!STRINGP (object))
1727 object = it->w->buffer;
1728 x_append_stretch_glyph (it, object, width, height, ascent);
1731 it->pixel_width = width;
1732 it->ascent = it->phys_ascent = height * ascent;
1733 it->descent = it->phys_descent = height - it->ascent;
1734 it->nglyphs = 1;
1736 if (face->box != FACE_NO_BOX)
1738 it->ascent += face->box_line_width;
1739 it->descent += face->box_line_width;
1741 if (it->start_of_box_run_p)
1742 it->pixel_width += face->box_line_width;
1743 if (it->end_of_box_run_p)
1744 it->pixel_width += face->box_line_width;
1747 take_vertical_position_into_account (it);
1750 /* Return proper value to be used as baseline offset of font that has
1751 ASCENT and DESCENT to draw characters by the font at the vertical
1752 center of the line of frame F.
1754 Here, out task is to find the value of BOFF in the following figure;
1756 -------------------------+-----------+-
1757 -+-+---------+-+ | |
1758 | | | | | |
1759 | | | | F_ASCENT F_HEIGHT
1760 | | | ASCENT | |
1761 HEIGHT | | | | |
1762 | | |-|-+------+-----------|------- baseline
1763 | | | | BOFF | |
1764 | |---------|-+-+ | |
1765 | | | DESCENT | |
1766 -+-+---------+-+ F_DESCENT |
1767 -------------------------+-----------+-
1769 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1770 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1771 DESCENT = FONT->descent
1772 HEIGHT = FONT_HEIGHT (FONT)
1773 F_DESCENT = (F->output_data.x->font->descent
1774 - F->output_data.x->baseline_offset)
1775 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1778 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 ((FONT)->descent \
1780 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1781 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1782 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1784 /* Produce glyphs/get display metrics for the display element IT is
1785 loaded with. See the description of struct display_iterator in
1786 dispextern.h for an overview of struct display_iterator. */
1788 static void
1789 x_produce_glyphs (it)
1790 struct it *it;
1792 it->glyph_not_available_p = 0;
1794 if (it->what == IT_CHARACTER)
1796 XChar2b char2b;
1797 XFontStruct *font;
1798 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1799 XCharStruct *pcm;
1800 int font_not_found_p;
1801 struct font_info *font_info;
1802 int boff; /* baseline offset */
1803 /* We may change it->multibyte_p upon unibyte<->multibyte
1804 conversion. So, save the current value now and restore it
1805 later.
1807 Note: It seems that we don't have to record multibyte_p in
1808 struct glyph because the character code itself tells if or
1809 not the character is multibyte. Thus, in the future, we must
1810 consider eliminating the field `multibyte_p' in the struct
1811 glyph.
1813 int saved_multibyte_p = it->multibyte_p;
1815 /* Maybe translate single-byte characters to multibyte, or the
1816 other way. */
1817 it->char_to_display = it->c;
1818 if (!ASCII_BYTE_P (it->c))
1820 if (unibyte_display_via_language_environment
1821 && SINGLE_BYTE_CHAR_P (it->c)
1822 && (it->c >= 0240
1823 || !NILP (Vnonascii_translation_table)))
1825 it->char_to_display = unibyte_char_to_multibyte (it->c);
1826 it->multibyte_p = 1;
1827 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1828 face = FACE_FROM_ID (it->f, it->face_id);
1830 else if (!SINGLE_BYTE_CHAR_P (it->c)
1831 && !it->multibyte_p)
1833 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1834 it->multibyte_p = 0;
1835 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1836 face = FACE_FROM_ID (it->f, it->face_id);
1840 /* Get font to use. Encode IT->char_to_display. */
1841 x_get_char_face_and_encoding (it->f, it->char_to_display,
1842 it->face_id, &char2b,
1843 it->multibyte_p);
1844 font = face->font;
1846 /* When no suitable font found, use the default font. */
1847 font_not_found_p = font == NULL;
1848 if (font_not_found_p)
1850 font = FRAME_FONT (it->f);
1851 boff = it->f->output_data.x->baseline_offset;
1852 font_info = NULL;
1854 else
1856 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1857 boff = font_info->baseline_offset;
1858 if (font_info->vertical_centering)
1859 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1862 if (it->char_to_display >= ' '
1863 && (!it->multibyte_p || it->char_to_display < 128))
1865 /* Either unibyte or ASCII. */
1866 int stretched_p;
1868 it->nglyphs = 1;
1870 pcm = x_per_char_metric (font, &char2b);
1871 it->ascent = font->ascent + boff;
1872 it->descent = font->descent - boff;
1874 if (pcm)
1876 it->phys_ascent = pcm->ascent + boff;
1877 it->phys_descent = pcm->descent - boff;
1878 it->pixel_width = pcm->width;
1880 else
1882 it->glyph_not_available_p = 1;
1883 it->phys_ascent = font->ascent + boff;
1884 it->phys_descent = font->descent - boff;
1885 it->pixel_width = FONT_WIDTH (font);
1888 /* If this is a space inside a region of text with
1889 `space-width' property, change its width. */
1890 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1891 if (stretched_p)
1892 it->pixel_width *= XFLOATINT (it->space_width);
1894 /* If face has a box, add the box thickness to the character
1895 height. If character has a box line to the left and/or
1896 right, add the box line width to the character's width. */
1897 if (face->box != FACE_NO_BOX)
1899 int thick = face->box_line_width;
1901 it->ascent += thick;
1902 it->descent += thick;
1904 if (it->start_of_box_run_p)
1905 it->pixel_width += thick;
1906 if (it->end_of_box_run_p)
1907 it->pixel_width += thick;
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face->overline_p)
1913 it->ascent += 2;
1915 take_vertical_position_into_account (it);
1917 /* If we have to actually produce glyphs, do it. */
1918 if (it->glyph_row)
1920 if (stretched_p)
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1925 x_append_stretch_glyph (it, it->object, it->pixel_width,
1926 it->ascent + it->descent, ascent);
1928 else
1929 x_append_glyph (it);
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1934 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1935 it->glyph_row->contains_overlapping_glyphs_p = 1;
1938 else if (it->char_to_display == '\n')
1940 /* A newline has no width but we need the height of the line. */
1941 it->pixel_width = 0;
1942 it->nglyphs = 0;
1943 it->ascent = it->phys_ascent = font->ascent + boff;
1944 it->descent = it->phys_descent = font->descent - boff;
1946 if (face->box != FACE_NO_BOX)
1948 int thick = face->box_line_width;
1949 it->ascent += thick;
1950 it->descent += thick;
1953 else if (it->char_to_display == '\t')
1955 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1956 int x = it->current_x + it->continuation_lines_width;
1957 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x - x < CANON_X_UNIT (it->f))
1963 next_tab_x += tab_width;
1965 it->pixel_width = next_tab_x - x;
1966 it->nglyphs = 1;
1967 it->ascent = it->phys_ascent = font->ascent + boff;
1968 it->descent = it->phys_descent = font->descent - boff;
1970 if (it->glyph_row)
1972 double ascent = (double) it->ascent / (it->ascent + it->descent);
1973 x_append_stretch_glyph (it, it->object, it->pixel_width,
1974 it->ascent + it->descent, ascent);
1977 else
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
1981 width of the font. */
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character
1986 from the charset width; this is what old redisplay code
1987 did. */
1988 pcm = x_per_char_metric (font, &char2b);
1989 if (font_not_found_p || !pcm)
1991 int charset = CHAR_CHARSET (it->char_to_display);
1993 it->glyph_not_available_p = 1;
1994 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1995 * CHARSET_WIDTH (charset));
1996 it->phys_ascent = font->ascent + boff;
1997 it->phys_descent = font->descent - boff;
1999 else
2001 it->pixel_width = pcm->width;
2002 it->phys_ascent = pcm->ascent + boff;
2003 it->phys_descent = pcm->descent - boff;
2004 if (it->glyph_row
2005 && (pcm->lbearing < 0
2006 || pcm->rbearing > pcm->width))
2007 it->glyph_row->contains_overlapping_glyphs_p = 1;
2009 it->nglyphs = 1;
2010 it->ascent = font->ascent + boff;
2011 it->descent = font->descent - boff;
2012 if (face->box != FACE_NO_BOX)
2014 int thick = face->box_line_width;
2015 it->ascent += thick;
2016 it->descent += thick;
2018 if (it->start_of_box_run_p)
2019 it->pixel_width += thick;
2020 if (it->end_of_box_run_p)
2021 it->pixel_width += thick;
2024 /* If face has an overline, add the height of the overline
2025 (1 pixel) and a 1 pixel margin to the character height. */
2026 if (face->overline_p)
2027 it->ascent += 2;
2029 take_vertical_position_into_account (it);
2031 if (it->glyph_row)
2032 x_append_glyph (it);
2034 it->multibyte_p = saved_multibyte_p;
2036 else if (it->what == IT_COMPOSITION)
2038 /* Note: A composition is represented as one glyph in the
2039 glyph matrix. There are no padding glyphs. */
2040 XChar2b char2b;
2041 XFontStruct *font;
2042 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2043 XCharStruct *pcm;
2044 int font_not_found_p;
2045 struct font_info *font_info;
2046 int boff; /* baseline offset */
2047 struct composition *cmp = composition_table[it->cmp_id];
2049 /* Maybe translate single-byte characters to multibyte. */
2050 it->char_to_display = it->c;
2051 if (unibyte_display_via_language_environment
2052 && SINGLE_BYTE_CHAR_P (it->c)
2053 && (it->c >= 0240
2054 || (it->c >= 0200
2055 && !NILP (Vnonascii_translation_table))))
2057 it->char_to_display = unibyte_char_to_multibyte (it->c);
2060 /* Get face and font to use. Encode IT->char_to_display. */
2061 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2062 face = FACE_FROM_ID (it->f, it->face_id);
2063 x_get_char_face_and_encoding (it->f, it->char_to_display,
2064 it->face_id, &char2b, it->multibyte_p);
2065 font = face->font;
2067 /* When no suitable font found, use the default font. */
2068 font_not_found_p = font == NULL;
2069 if (font_not_found_p)
2071 font = FRAME_FONT (it->f);
2072 boff = it->f->output_data.x->baseline_offset;
2073 font_info = NULL;
2075 else
2077 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2078 boff = font_info->baseline_offset;
2079 if (font_info->vertical_centering)
2080 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2083 /* There are no padding glyphs, so there is only one glyph to
2084 produce for the composition. Important is that pixel_width,
2085 ascent and descent are the values of what is drawn by
2086 draw_glyphs (i.e. the values of the overall glyphs composed). */
2087 it->nglyphs = 1;
2089 /* If we have not yet calculated pixel size data of glyphs of
2090 the composition for the current face font, calculate them
2091 now. Theoretically, we have to check all fonts for the
2092 glyphs, but that requires much time and memory space. So,
2093 here we check only the font of the first glyph. This leads
2094 to incorrect display very rarely, and C-l (recenter) can
2095 correct the display anyway. */
2096 if (cmp->font != (void *) font)
2098 /* Ascent and descent of the font of the first character of
2099 this composition (adjusted by baseline offset). Ascent
2100 and descent of overall glyphs should not be less than
2101 them respectively. */
2102 int font_ascent = font->ascent + boff;
2103 int font_descent = font->descent - boff;
2104 /* Bounding box of the overall glyphs. */
2105 int leftmost, rightmost, lowest, highest;
2106 int i, width, ascent, descent;
2108 cmp->font = (void *) font;
2110 /* Initialize the bounding box. */
2111 pcm = x_per_char_metric (font, &char2b);
2112 if (pcm)
2114 width = pcm->width;
2115 ascent = pcm->ascent;
2116 descent = pcm->descent;
2118 else
2120 width = FONT_WIDTH (font);
2121 ascent = font->ascent;
2122 descent = font->descent;
2125 rightmost = width;
2126 lowest = - descent + boff;
2127 highest = ascent + boff;
2128 leftmost = 0;
2130 if (font_info
2131 && font_info->default_ascent
2132 && CHAR_TABLE_P (Vuse_default_ascent)
2133 && !NILP (Faref (Vuse_default_ascent,
2134 make_number (it->char_to_display))))
2135 highest = font_info->default_ascent + boff;
2137 /* Draw the first glyph at the normal position. It may be
2138 shifted to right later if some other glyphs are drawn at
2139 the left. */
2140 cmp->offsets[0] = 0;
2141 cmp->offsets[1] = boff;
2143 /* Set cmp->offsets for the remaining glyphs. */
2144 for (i = 1; i < cmp->glyph_len; i++)
2146 int left, right, btm, top;
2147 int ch = COMPOSITION_GLYPH (cmp, i);
2148 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2150 face = FACE_FROM_ID (it->f, face_id);
2151 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2152 it->multibyte_p);
2153 font = face->font;
2154 if (font == NULL)
2156 font = FRAME_FONT (it->f);
2157 boff = it->f->output_data.x->baseline_offset;
2158 font_info = NULL;
2160 else
2162 font_info
2163 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2164 boff = font_info->baseline_offset;
2165 if (font_info->vertical_centering)
2166 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2169 pcm = x_per_char_metric (font, &char2b);
2170 if (pcm)
2172 width = pcm->width;
2173 ascent = pcm->ascent;
2174 descent = pcm->descent;
2176 else
2178 width = FONT_WIDTH (font);
2179 ascent = font->ascent;
2180 descent = font->descent;
2183 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2185 /* Relative composition with or without
2186 alternate chars. */
2187 left = (leftmost + rightmost - width) / 2;
2188 btm = - descent + boff;
2189 if (font_info && font_info->relative_compose
2190 && (! CHAR_TABLE_P (Vignore_relative_composition)
2191 || NILP (Faref (Vignore_relative_composition,
2192 make_number (ch)))))
2195 if (- descent >= font_info->relative_compose)
2196 /* One extra pixel between two glyphs. */
2197 btm = highest + 1;
2198 else if (ascent <= 0)
2199 /* One extra pixel between two glyphs. */
2200 btm = lowest - 1 - ascent - descent;
2203 else
2205 /* A composition rule is specified by an integer
2206 value that encodes global and new reference
2207 points (GREF and NREF). GREF and NREF are
2208 specified by numbers as below:
2210 0---1---2 -- ascent
2214 9--10--11 -- center
2216 ---3---4---5--- baseline
2218 6---7---8 -- descent
2220 int rule = COMPOSITION_RULE (cmp, i);
2221 int gref, nref, grefx, grefy, nrefx, nrefy;
2223 COMPOSITION_DECODE_RULE (rule, gref, nref);
2224 grefx = gref % 3, nrefx = nref % 3;
2225 grefy = gref / 3, nrefy = nref / 3;
2227 left = (leftmost
2228 + grefx * (rightmost - leftmost) / 2
2229 - nrefx * width / 2);
2230 btm = ((grefy == 0 ? highest
2231 : grefy == 1 ? 0
2232 : grefy == 2 ? lowest
2233 : (highest + lowest) / 2)
2234 - (nrefy == 0 ? ascent + descent
2235 : nrefy == 1 ? descent - boff
2236 : nrefy == 2 ? 0
2237 : (ascent + descent) / 2));
2240 cmp->offsets[i * 2] = left;
2241 cmp->offsets[i * 2 + 1] = btm + descent;
2243 /* Update the bounding box of the overall glyphs. */
2244 right = left + width;
2245 top = btm + descent + ascent;
2246 if (left < leftmost)
2247 leftmost = left;
2248 if (right > rightmost)
2249 rightmost = right;
2250 if (top > highest)
2251 highest = top;
2252 if (btm < lowest)
2253 lowest = btm;
2256 /* If there are glyphs whose x-offsets are negative,
2257 shift all glyphs to the right and make all x-offsets
2258 non-negative. */
2259 if (leftmost < 0)
2261 for (i = 0; i < cmp->glyph_len; i++)
2262 cmp->offsets[i * 2] -= leftmost;
2263 rightmost -= leftmost;
2266 cmp->pixel_width = rightmost;
2267 cmp->ascent = highest;
2268 cmp->descent = - lowest;
2269 if (cmp->ascent < font_ascent)
2270 cmp->ascent = font_ascent;
2271 if (cmp->descent < font_descent)
2272 cmp->descent = font_descent;
2275 it->pixel_width = cmp->pixel_width;
2276 it->ascent = it->phys_ascent = cmp->ascent;
2277 it->descent = it->phys_descent = cmp->descent;
2279 if (face->box != FACE_NO_BOX)
2281 int thick = face->box_line_width;
2282 it->ascent += thick;
2283 it->descent += thick;
2285 if (it->start_of_box_run_p)
2286 it->pixel_width += thick;
2287 if (it->end_of_box_run_p)
2288 it->pixel_width += thick;
2291 /* If face has an overline, add the height of the overline
2292 (1 pixel) and a 1 pixel margin to the character height. */
2293 if (face->overline_p)
2294 it->ascent += 2;
2296 take_vertical_position_into_account (it);
2298 if (it->glyph_row)
2299 x_append_composite_glyph (it);
2301 else if (it->what == IT_IMAGE)
2302 x_produce_image_glyph (it);
2303 else if (it->what == IT_STRETCH)
2304 x_produce_stretch_glyph (it);
2306 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2307 because this isn't true for images with `:ascent 100'. */
2308 xassert (it->ascent >= 0 && it->descent >= 0);
2309 if (it->area == TEXT_AREA)
2310 it->current_x += it->pixel_width;
2312 it->descent += it->extra_line_spacing;
2314 it->max_ascent = max (it->max_ascent, it->ascent);
2315 it->max_descent = max (it->max_descent, it->descent);
2316 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2317 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2321 /* Estimate the pixel height of the mode or top line on frame F.
2322 FACE_ID specifies what line's height to estimate. */
2325 x_estimate_mode_line_height (f, face_id)
2326 struct frame *f;
2327 enum face_id face_id;
2329 int height = 1;
2331 /* This function is called so early when Emacs starts that the face
2332 cache and mode line face are not yet initialized. */
2333 if (FRAME_FACE_CACHE (f))
2335 struct face *face = FACE_FROM_ID (f, face_id);
2336 if (face)
2337 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2340 return height;
2344 /***********************************************************************
2345 Glyph display
2346 ***********************************************************************/
2348 /* A sequence of glyphs to be drawn in the same face.
2350 This data structure is not really completely X specific, so it
2351 could possibly, at least partially, be useful for other systems. It
2352 is currently not part of the external redisplay interface because
2353 it's not clear what other systems will need. */
2355 struct glyph_string
2357 /* X-origin of the string. */
2358 int x;
2360 /* Y-origin and y-position of the base line of this string. */
2361 int y, ybase;
2363 /* The width of the string, not including a face extension. */
2364 int width;
2366 /* The width of the string, including a face extension. */
2367 int background_width;
2369 /* The height of this string. This is the height of the line this
2370 string is drawn in, and can be different from the height of the
2371 font the string is drawn in. */
2372 int height;
2374 /* Number of pixels this string overwrites in front of its x-origin.
2375 This number is zero if the string has an lbearing >= 0; it is
2376 -lbearing, if the string has an lbearing < 0. */
2377 int left_overhang;
2379 /* Number of pixels this string overwrites past its right-most
2380 nominal x-position, i.e. x + width. Zero if the string's
2381 rbearing is <= its nominal width, rbearing - width otherwise. */
2382 int right_overhang;
2384 /* The frame on which the glyph string is drawn. */
2385 struct frame *f;
2387 /* The window on which the glyph string is drawn. */
2388 struct window *w;
2390 /* X display and window for convenience. */
2391 Display *display;
2392 Window window;
2394 /* The glyph row for which this string was built. It determines the
2395 y-origin and height of the string. */
2396 struct glyph_row *row;
2398 /* The area within row. */
2399 enum glyph_row_area area;
2401 /* Characters to be drawn, and number of characters. */
2402 XChar2b *char2b;
2403 int nchars;
2405 /* A face-override for drawing cursors, mouse face and similar. */
2406 enum draw_glyphs_face hl;
2408 /* Face in which this string is to be drawn. */
2409 struct face *face;
2411 /* Font in which this string is to be drawn. */
2412 XFontStruct *font;
2414 /* Font info for this string. */
2415 struct font_info *font_info;
2417 /* Non-null means this string describes (part of) a composition.
2418 All characters from char2b are drawn composed. */
2419 struct composition *cmp;
2421 /* Index of this glyph string's first character in the glyph
2422 definition of CMP. If this is zero, this glyph string describes
2423 the first character of a composition. */
2424 int gidx;
2426 /* 1 means this glyph strings face has to be drawn to the right end
2427 of the window's drawing area. */
2428 unsigned extends_to_end_of_line_p : 1;
2430 /* 1 means the background of this string has been drawn. */
2431 unsigned background_filled_p : 1;
2433 /* 1 means glyph string must be drawn with 16-bit functions. */
2434 unsigned two_byte_p : 1;
2436 /* 1 means that the original font determined for drawing this glyph
2437 string could not be loaded. The member `font' has been set to
2438 the frame's default font in this case. */
2439 unsigned font_not_found_p : 1;
2441 /* 1 means that the face in which this glyph string is drawn has a
2442 stipple pattern. */
2443 unsigned stippled_p : 1;
2445 /* 1 means only the foreground of this glyph string must be drawn,
2446 and we should use the physical height of the line this glyph
2447 string appears in as clip rect. */
2448 unsigned for_overlaps_p : 1;
2450 /* The GC to use for drawing this glyph string. */
2451 GC gc;
2453 /* A pointer to the first glyph in the string. This glyph
2454 corresponds to char2b[0]. Needed to draw rectangles if
2455 font_not_found_p is 1. */
2456 struct glyph *first_glyph;
2458 /* Image, if any. */
2459 struct image *img;
2461 struct glyph_string *next, *prev;
2465 #if 0
2467 static void
2468 x_dump_glyph_string (s)
2469 struct glyph_string *s;
2471 fprintf (stderr, "glyph string\n");
2472 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2473 s->x, s->y, s->width, s->height);
2474 fprintf (stderr, " ybase = %d\n", s->ybase);
2475 fprintf (stderr, " hl = %d\n", s->hl);
2476 fprintf (stderr, " left overhang = %d, right = %d\n",
2477 s->left_overhang, s->right_overhang);
2478 fprintf (stderr, " nchars = %d\n", s->nchars);
2479 fprintf (stderr, " extends to end of line = %d\n",
2480 s->extends_to_end_of_line_p);
2481 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2482 fprintf (stderr, " bg width = %d\n", s->background_width);
2485 #endif /* GLYPH_DEBUG */
2489 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2490 struct glyph_string **,
2491 struct glyph_string *,
2492 struct glyph_string *));
2493 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2494 struct glyph_string **,
2495 struct glyph_string *,
2496 struct glyph_string *));
2497 static void x_append_glyph_string P_ ((struct glyph_string **,
2498 struct glyph_string **,
2499 struct glyph_string *));
2500 static int x_left_overwritten P_ ((struct glyph_string *));
2501 static int x_left_overwriting P_ ((struct glyph_string *));
2502 static int x_right_overwritten P_ ((struct glyph_string *));
2503 static int x_right_overwriting P_ ((struct glyph_string *));
2504 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2505 int));
2506 static void x_init_glyph_string P_ ((struct glyph_string *,
2507 XChar2b *, struct window *,
2508 struct glyph_row *,
2509 enum glyph_row_area, int,
2510 enum draw_glyphs_face));
2511 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2512 enum glyph_row_area, int, int,
2513 enum draw_glyphs_face, int *, int *, int));
2514 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2515 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2516 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2517 int));
2518 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2519 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2520 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2521 static void x_draw_glyph_string P_ ((struct glyph_string *));
2522 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2523 static void x_set_cursor_gc P_ ((struct glyph_string *));
2524 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2525 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2526 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2527 int *, int *));
2528 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2529 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2530 unsigned long *, double, int));
2531 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2532 double, int, unsigned long));
2533 static void x_setup_relief_colors P_ ((struct glyph_string *));
2534 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2535 static void x_draw_image_relief P_ ((struct glyph_string *));
2536 static void x_draw_image_foreground P_ ((struct glyph_string *));
2537 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2538 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2539 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2540 int, int, int));
2541 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2542 int, int, int, int, XRectangle *));
2543 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2544 int, int, int, XRectangle *));
2545 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2546 enum glyph_row_area));
2547 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2548 struct glyph_row *,
2549 enum glyph_row_area, int, int));
2551 #if GLYPH_DEBUG
2552 static void x_check_font P_ ((struct frame *, XFontStruct *));
2553 #endif
2556 /* Append the list of glyph strings with head H and tail T to the list
2557 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2559 static INLINE void
2560 x_append_glyph_string_lists (head, tail, h, t)
2561 struct glyph_string **head, **tail;
2562 struct glyph_string *h, *t;
2564 if (h)
2566 if (*head)
2567 (*tail)->next = h;
2568 else
2569 *head = h;
2570 h->prev = *tail;
2571 *tail = t;
2576 /* Prepend the list of glyph strings with head H and tail T to the
2577 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2578 result. */
2580 static INLINE void
2581 x_prepend_glyph_string_lists (head, tail, h, t)
2582 struct glyph_string **head, **tail;
2583 struct glyph_string *h, *t;
2585 if (h)
2587 if (*head)
2588 (*head)->prev = t;
2589 else
2590 *tail = t;
2591 t->next = *head;
2592 *head = h;
2597 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2598 Set *HEAD and *TAIL to the resulting list. */
2600 static INLINE void
2601 x_append_glyph_string (head, tail, s)
2602 struct glyph_string **head, **tail;
2603 struct glyph_string *s;
2605 s->next = s->prev = NULL;
2606 x_append_glyph_string_lists (head, tail, s, s);
2610 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2611 face. */
2613 static void
2614 x_set_cursor_gc (s)
2615 struct glyph_string *s;
2617 if (s->font == FRAME_FONT (s->f)
2618 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2619 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2620 && !s->cmp)
2621 s->gc = s->f->output_data.x->cursor_gc;
2622 else
2624 /* Cursor on non-default face: must merge. */
2625 XGCValues xgcv;
2626 unsigned long mask;
2628 xgcv.background = s->f->output_data.x->cursor_pixel;
2629 xgcv.foreground = s->face->background;
2631 /* If the glyph would be invisible, try a different foreground. */
2632 if (xgcv.foreground == xgcv.background)
2633 xgcv.foreground = s->face->foreground;
2634 if (xgcv.foreground == xgcv.background)
2635 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2636 if (xgcv.foreground == xgcv.background)
2637 xgcv.foreground = s->face->foreground;
2639 /* Make sure the cursor is distinct from text in this face. */
2640 if (xgcv.background == s->face->background
2641 && xgcv.foreground == s->face->foreground)
2643 xgcv.background = s->face->foreground;
2644 xgcv.foreground = s->face->background;
2647 IF_DEBUG (x_check_font (s->f, s->font));
2648 xgcv.font = s->font->fid;
2649 xgcv.graphics_exposures = False;
2650 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2652 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2653 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2654 mask, &xgcv);
2655 else
2656 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2657 = XCreateGC (s->display, s->window, mask, &xgcv);
2659 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2664 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2666 static void
2667 x_set_mouse_face_gc (s)
2668 struct glyph_string *s;
2670 int face_id;
2671 struct face *face;
2673 /* What face has to be used for the mouse face? */
2674 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2675 face = FACE_FROM_ID (s->f, face_id);
2676 if (s->first_glyph->type == CHAR_GLYPH)
2677 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2678 else
2679 face_id = FACE_FOR_CHAR (s->f, face, 0);
2680 s->face = FACE_FROM_ID (s->f, face_id);
2681 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2683 /* If font in this face is same as S->font, use it. */
2684 if (s->font == s->face->font)
2685 s->gc = s->face->gc;
2686 else
2688 /* Otherwise construct scratch_cursor_gc with values from FACE
2689 but font FONT. */
2690 XGCValues xgcv;
2691 unsigned long mask;
2693 xgcv.background = s->face->background;
2694 xgcv.foreground = s->face->foreground;
2695 IF_DEBUG (x_check_font (s->f, s->font));
2696 xgcv.font = s->font->fid;
2697 xgcv.graphics_exposures = False;
2698 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2700 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2701 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2702 mask, &xgcv);
2703 else
2704 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2705 = XCreateGC (s->display, s->window, mask, &xgcv);
2707 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2710 xassert (s->gc != 0);
2714 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2715 Faces to use in the mode line have already been computed when the
2716 matrix was built, so there isn't much to do, here. */
2718 static INLINE void
2719 x_set_mode_line_face_gc (s)
2720 struct glyph_string *s;
2722 s->gc = s->face->gc;
2726 /* Set S->gc of glyph string S for drawing that glyph string. Set
2727 S->stippled_p to a non-zero value if the face of S has a stipple
2728 pattern. */
2730 static INLINE void
2731 x_set_glyph_string_gc (s)
2732 struct glyph_string *s;
2734 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2736 if (s->hl == DRAW_NORMAL_TEXT)
2738 s->gc = s->face->gc;
2739 s->stippled_p = s->face->stipple != 0;
2741 else if (s->hl == DRAW_INVERSE_VIDEO)
2743 x_set_mode_line_face_gc (s);
2744 s->stippled_p = s->face->stipple != 0;
2746 else if (s->hl == DRAW_CURSOR)
2748 x_set_cursor_gc (s);
2749 s->stippled_p = 0;
2751 else if (s->hl == DRAW_MOUSE_FACE)
2753 x_set_mouse_face_gc (s);
2754 s->stippled_p = s->face->stipple != 0;
2756 else if (s->hl == DRAW_IMAGE_RAISED
2757 || s->hl == DRAW_IMAGE_SUNKEN)
2759 s->gc = s->face->gc;
2760 s->stippled_p = s->face->stipple != 0;
2762 else
2764 s->gc = s->face->gc;
2765 s->stippled_p = s->face->stipple != 0;
2768 /* GC must have been set. */
2769 xassert (s->gc != 0);
2773 /* Return in *R the clipping rectangle for glyph string S. */
2775 static void
2776 x_get_glyph_string_clip_rect (s, r)
2777 struct glyph_string *s;
2778 XRectangle *r;
2780 if (s->row->full_width_p)
2782 /* Draw full-width. X coordinates are relative to S->w->left. */
2783 int canon_x = CANON_X_UNIT (s->f);
2785 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2786 r->width = XFASTINT (s->w->width) * canon_x;
2788 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2790 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2791 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2792 r->x -= width;
2795 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2797 /* Unless displaying a mode or menu bar line, which are always
2798 fully visible, clip to the visible part of the row. */
2799 if (s->w->pseudo_window_p)
2800 r->height = s->row->visible_height;
2801 else
2802 r->height = s->height;
2804 else
2806 /* This is a text line that may be partially visible. */
2807 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2808 r->width = window_box_width (s->w, s->area);
2809 r->height = s->row->visible_height;
2812 /* Don't use S->y for clipping because it doesn't take partially
2813 visible lines into account. For example, it can be negative for
2814 partially visible lines at the top of a window. */
2815 if (!s->row->full_width_p
2816 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2817 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2818 else
2819 r->y = max (0, s->row->y);
2821 /* If drawing a tool-bar window, draw it over the internal border
2822 at the top of the window. */
2823 if (s->w == XWINDOW (s->f->tool_bar_window))
2824 r->y -= s->f->output_data.x->internal_border_width;
2826 /* If S draws overlapping rows, it's sufficient to use the top and
2827 bottom of the window for clipping because this glyph string
2828 intentionally draws over other lines. */
2829 if (s->for_overlaps_p)
2831 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2832 r->height = window_text_bottom_y (s->w) - r->y;
2835 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2839 /* Set clipping for output of glyph string S. S may be part of a mode
2840 line or menu if we don't have X toolkit support. */
2842 static INLINE void
2843 x_set_glyph_string_clipping (s)
2844 struct glyph_string *s;
2846 XRectangle r;
2847 x_get_glyph_string_clip_rect (s, &r);
2848 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2852 /* Compute left and right overhang of glyph string S. If S is a glyph
2853 string for a composition, assume overhangs don't exist. */
2855 static INLINE void
2856 x_compute_glyph_string_overhangs (s)
2857 struct glyph_string *s;
2859 if (s->cmp == NULL
2860 && s->first_glyph->type == CHAR_GLYPH)
2862 XCharStruct cs;
2863 int direction, font_ascent, font_descent;
2864 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2865 &font_ascent, &font_descent, &cs);
2866 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2867 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2872 /* Compute overhangs and x-positions for glyph string S and its
2873 predecessors, or successors. X is the starting x-position for S.
2874 BACKWARD_P non-zero means process predecessors. */
2876 static void
2877 x_compute_overhangs_and_x (s, x, backward_p)
2878 struct glyph_string *s;
2879 int x;
2880 int backward_p;
2882 if (backward_p)
2884 while (s)
2886 x_compute_glyph_string_overhangs (s);
2887 x -= s->width;
2888 s->x = x;
2889 s = s->prev;
2892 else
2894 while (s)
2896 x_compute_glyph_string_overhangs (s);
2897 s->x = x;
2898 x += s->width;
2899 s = s->next;
2905 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2906 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2907 assumed to be zero. */
2909 static void
2910 x_get_glyph_overhangs (glyph, f, left, right)
2911 struct glyph *glyph;
2912 struct frame *f;
2913 int *left, *right;
2915 *left = *right = 0;
2917 if (glyph->type == CHAR_GLYPH)
2919 XFontStruct *font;
2920 struct face *face;
2921 struct font_info *font_info;
2922 XChar2b char2b;
2923 XCharStruct *pcm;
2925 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2926 font = face->font;
2927 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2928 if (font
2929 && (pcm = x_per_char_metric (font, &char2b)))
2931 if (pcm->rbearing > pcm->width)
2932 *right = pcm->rbearing - pcm->width;
2933 if (pcm->lbearing < 0)
2934 *left = -pcm->lbearing;
2940 /* Return the index of the first glyph preceding glyph string S that
2941 is overwritten by S because of S's left overhang. Value is -1
2942 if no glyphs are overwritten. */
2944 static int
2945 x_left_overwritten (s)
2946 struct glyph_string *s;
2948 int k;
2950 if (s->left_overhang)
2952 int x = 0, i;
2953 struct glyph *glyphs = s->row->glyphs[s->area];
2954 int first = s->first_glyph - glyphs;
2956 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2957 x -= glyphs[i].pixel_width;
2959 k = i + 1;
2961 else
2962 k = -1;
2964 return k;
2968 /* Return the index of the first glyph preceding glyph string S that
2969 is overwriting S because of its right overhang. Value is -1 if no
2970 glyph in front of S overwrites S. */
2972 static int
2973 x_left_overwriting (s)
2974 struct glyph_string *s;
2976 int i, k, x;
2977 struct glyph *glyphs = s->row->glyphs[s->area];
2978 int first = s->first_glyph - glyphs;
2980 k = -1;
2981 x = 0;
2982 for (i = first - 1; i >= 0; --i)
2984 int left, right;
2985 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2986 if (x + right > 0)
2987 k = i;
2988 x -= glyphs[i].pixel_width;
2991 return k;
2995 /* Return the index of the last glyph following glyph string S that is
2996 not overwritten by S because of S's right overhang. Value is -1 if
2997 no such glyph is found. */
2999 static int
3000 x_right_overwritten (s)
3001 struct glyph_string *s;
3003 int k = -1;
3005 if (s->right_overhang)
3007 int x = 0, i;
3008 struct glyph *glyphs = s->row->glyphs[s->area];
3009 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3010 int end = s->row->used[s->area];
3012 for (i = first; i < end && s->right_overhang > x; ++i)
3013 x += glyphs[i].pixel_width;
3015 k = i;
3018 return k;
3022 /* Return the index of the last glyph following glyph string S that
3023 overwrites S because of its left overhang. Value is negative
3024 if no such glyph is found. */
3026 static int
3027 x_right_overwriting (s)
3028 struct glyph_string *s;
3030 int i, k, x;
3031 int end = s->row->used[s->area];
3032 struct glyph *glyphs = s->row->glyphs[s->area];
3033 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3035 k = -1;
3036 x = 0;
3037 for (i = first; i < end; ++i)
3039 int left, right;
3040 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3041 if (x - left < 0)
3042 k = i;
3043 x += glyphs[i].pixel_width;
3046 return k;
3050 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3052 static INLINE void
3053 x_clear_glyph_string_rect (s, x, y, w, h)
3054 struct glyph_string *s;
3055 int x, y, w, h;
3057 XGCValues xgcv;
3058 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3059 XSetForeground (s->display, s->gc, xgcv.background);
3060 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3061 XSetForeground (s->display, s->gc, xgcv.foreground);
3065 /* Draw the background of glyph_string S. If S->background_filled_p
3066 is non-zero don't draw it. FORCE_P non-zero means draw the
3067 background even if it wouldn't be drawn normally. This is used
3068 when a string preceding S draws into the background of S, or S
3069 contains the first component of a composition. */
3071 static void
3072 x_draw_glyph_string_background (s, force_p)
3073 struct glyph_string *s;
3074 int force_p;
3076 /* Nothing to do if background has already been drawn or if it
3077 shouldn't be drawn in the first place. */
3078 if (!s->background_filled_p)
3080 if (s->stippled_p)
3082 /* Fill background with a stipple pattern. */
3083 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3084 XFillRectangle (s->display, s->window, s->gc, s->x,
3085 s->y + s->face->box_line_width,
3086 s->background_width,
3087 s->height - 2 * s->face->box_line_width);
3088 XSetFillStyle (s->display, s->gc, FillSolid);
3089 s->background_filled_p = 1;
3091 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3092 || s->font_not_found_p
3093 || s->extends_to_end_of_line_p
3094 || force_p)
3096 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3097 s->background_width,
3098 s->height - 2 * s->face->box_line_width);
3099 s->background_filled_p = 1;
3105 /* Draw the foreground of glyph string S. */
3107 static void
3108 x_draw_glyph_string_foreground (s)
3109 struct glyph_string *s;
3111 int i, x;
3113 /* If first glyph of S has a left box line, start drawing the text
3114 of S to the right of that box line. */
3115 if (s->face->box != FACE_NO_BOX
3116 && s->first_glyph->left_box_line_p)
3117 x = s->x + s->face->box_line_width;
3118 else
3119 x = s->x;
3121 /* Draw characters of S as rectangles if S's font could not be
3122 loaded. */
3123 if (s->font_not_found_p)
3125 for (i = 0; i < s->nchars; ++i)
3127 struct glyph *g = s->first_glyph + i;
3128 XDrawRectangle (s->display, s->window,
3129 s->gc, x, s->y, g->pixel_width - 1,
3130 s->height - 1);
3131 x += g->pixel_width;
3134 else
3136 char *char1b = (char *) s->char2b;
3137 int boff = s->font_info->baseline_offset;
3139 if (s->font_info->vertical_centering)
3140 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3142 /* If we can use 8-bit functions, condense S->char2b. */
3143 if (!s->two_byte_p)
3144 for (i = 0; i < s->nchars; ++i)
3145 char1b[i] = s->char2b[i].byte2;
3147 /* Draw text with XDrawString if background has already been
3148 filled. Otherwise, use XDrawImageString. (Note that
3149 XDrawImageString is usually faster than XDrawString.) Always
3150 use XDrawImageString when drawing the cursor so that there is
3151 no chance that characters under a box cursor are invisible. */
3152 if (s->for_overlaps_p
3153 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3155 /* Draw characters with 16-bit or 8-bit functions. */
3156 if (s->two_byte_p)
3157 XDrawString16 (s->display, s->window, s->gc, x,
3158 s->ybase - boff, s->char2b, s->nchars);
3159 else
3160 XDrawString (s->display, s->window, s->gc, x,
3161 s->ybase - boff, char1b, s->nchars);
3163 else
3165 if (s->two_byte_p)
3166 XDrawImageString16 (s->display, s->window, s->gc, x,
3167 s->ybase - boff, s->char2b, s->nchars);
3168 else
3169 XDrawImageString (s->display, s->window, s->gc, x,
3170 s->ybase - boff, char1b, s->nchars);
3175 /* Draw the foreground of composite glyph string S. */
3177 static void
3178 x_draw_composite_glyph_string_foreground (s)
3179 struct glyph_string *s;
3181 int i, x;
3183 /* If first glyph of S has a left box line, start drawing the text
3184 of S to the right of that box line. */
3185 if (s->face->box != FACE_NO_BOX
3186 && s->first_glyph->left_box_line_p)
3187 x = s->x + s->face->box_line_width;
3188 else
3189 x = s->x;
3191 /* S is a glyph string for a composition. S->gidx is the index of
3192 the first character drawn for glyphs of this composition.
3193 S->gidx == 0 means we are drawing the very first character of
3194 this composition. */
3196 /* Draw a rectangle for the composition if the font for the very
3197 first character of the composition could not be loaded. */
3198 if (s->font_not_found_p)
3200 if (s->gidx == 0)
3201 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3202 s->width - 1, s->height - 1);
3204 else
3206 for (i = 0; i < s->nchars; i++, ++s->gidx)
3207 XDrawString16 (s->display, s->window, s->gc,
3208 x + s->cmp->offsets[s->gidx * 2],
3209 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3210 s->char2b + i, 1);
3215 #ifdef USE_X_TOOLKIT
3217 static struct frame *x_frame_of_widget P_ ((Widget));
3220 /* Return the frame on which widget WIDGET is used.. Abort if frame
3221 cannot be determined. */
3223 static struct frame *
3224 x_frame_of_widget (widget)
3225 Widget widget;
3227 struct x_display_info *dpyinfo;
3228 Lisp_Object tail;
3229 struct frame *f;
3231 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3233 /* Find the top-level shell of the widget. Note that this function
3234 can be called when the widget is not yet realized, so XtWindow
3235 (widget) == 0. That's the reason we can't simply use
3236 x_any_window_to_frame. */
3237 while (!XtIsTopLevelShell (widget))
3238 widget = XtParent (widget);
3240 /* Look for a frame with that top-level widget. Allocate the color
3241 on that frame to get the right gamma correction value. */
3242 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3243 if (GC_FRAMEP (XCAR (tail))
3244 && (f = XFRAME (XCAR (tail)),
3245 (f->output_data.nothing != 1
3246 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3247 && f->output_data.x->widget == widget)
3248 return f;
3250 abort ();
3254 /* Allocate the color COLOR->pixel on the screen and display of
3255 widget WIDGET in colormap CMAP. If an exact match cannot be
3256 allocated, try the nearest color available. Value is non-zero
3257 if successful. This is called from lwlib. */
3260 x_alloc_nearest_color_for_widget (widget, cmap, color)
3261 Widget widget;
3262 Colormap cmap;
3263 XColor *color;
3265 struct frame *f = x_frame_of_widget (widget);
3266 return x_alloc_nearest_color (f, cmap, color);
3270 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3271 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3272 If this produces the same color as PIXEL, try a color where all RGB
3273 values have DELTA added. Return the allocated color in *PIXEL.
3274 DISPLAY is the X display, CMAP is the colormap to operate on.
3275 Value is non-zero if successful. */
3278 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3279 Widget widget;
3280 Display *display;
3281 Colormap cmap;
3282 unsigned long *pixel;
3283 double factor;
3284 int delta;
3286 struct frame *f = x_frame_of_widget (widget);
3287 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3291 #endif /* USE_X_TOOLKIT */
3294 /* Value is an array of XColor structures for the contents of the
3295 color map of frame F. Set *NCELLS to the size of the array.
3296 Note that this probably shouldn't be called for large color maps,
3297 say a 24-bit TrueColor map. */
3299 static const XColor *
3300 x_color_cells (f, ncells)
3301 struct frame *f;
3302 int *ncells;
3304 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3306 if (dpyinfo->color_cells == NULL)
3308 Display *display = FRAME_X_DISPLAY (f);
3309 Screen *screen = FRAME_X_SCREEN (f);
3310 int i;
3312 dpyinfo->ncolor_cells
3313 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3314 dpyinfo->color_cells
3315 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3316 * sizeof *dpyinfo->color_cells);
3318 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3319 dpyinfo->color_cells[i].pixel = i;
3321 XQueryColors (display, FRAME_X_COLORMAP (f),
3322 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3325 *ncells = dpyinfo->ncolor_cells;
3326 return dpyinfo->color_cells;
3330 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3331 colors in COLORS. Use cached information, if available. */
3333 void
3334 x_query_colors (f, colors, ncolors)
3335 struct frame *f;
3336 XColor *colors;
3337 int ncolors;
3339 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3341 if (dpyinfo->color_cells)
3343 int i;
3344 for (i = 0; i < ncolors; ++i)
3346 unsigned long pixel = colors[i].pixel;
3347 xassert (pixel < dpyinfo->ncolor_cells);
3348 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3349 colors[i] = dpyinfo->color_cells[pixel];
3352 else
3353 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3357 /* On frame F, translate pixel color to RGB values for the color in
3358 COLOR. Use cached information, if available. */
3360 void
3361 x_query_color (f, color)
3362 struct frame *f;
3363 XColor *color;
3365 x_query_colors (f, color, 1);
3369 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3370 CMAP. If an exact match can't be allocated, try the nearest color
3371 available. Value is non-zero if successful. Set *COLOR to the
3372 color allocated. */
3375 x_alloc_nearest_color (f, cmap, color)
3376 struct frame *f;
3377 Colormap cmap;
3378 XColor *color;
3380 Display *display = FRAME_X_DISPLAY (f);
3381 Screen *screen = FRAME_X_SCREEN (f);
3382 int rc;
3384 gamma_correct (f, color);
3385 rc = XAllocColor (display, cmap, color);
3386 if (rc == 0)
3388 /* If we got to this point, the colormap is full, so we're going
3389 to try to get the next closest color. The algorithm used is
3390 a least-squares matching, which is what X uses for closest
3391 color matching with StaticColor visuals. */
3392 int nearest, i;
3393 unsigned long nearest_delta = ~0;
3394 int ncells;
3395 const XColor *cells = x_color_cells (f, &ncells);
3397 for (nearest = i = 0; i < ncells; ++i)
3399 long dred = (color->red >> 8) - (cells[i].red >> 8);
3400 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3401 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3402 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3404 if (delta < nearest_delta)
3406 nearest = i;
3407 nearest_delta = delta;
3411 color->red = cells[nearest].red;
3412 color->green = cells[nearest].green;
3413 color->blue = cells[nearest].blue;
3414 rc = XAllocColor (display, cmap, color);
3416 else
3418 /* If allocation succeeded, and the allocated pixel color is not
3419 equal to a cached pixel color recorded earlier, there was a
3420 change in the colormap, so clear the color cache. */
3421 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3422 XColor *cached_color;
3424 if (dpyinfo->color_cells
3425 && (cached_color = &dpyinfo->color_cells[color->pixel],
3426 (cached_color->red != color->red
3427 || cached_color->blue != color->blue
3428 || cached_color->green != color->green)))
3430 xfree (dpyinfo->color_cells);
3431 dpyinfo->color_cells = NULL;
3432 dpyinfo->ncolor_cells = 0;
3436 #ifdef DEBUG_X_COLORS
3437 if (rc)
3438 register_color (color->pixel);
3439 #endif /* DEBUG_X_COLORS */
3441 return rc;
3445 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3446 It's necessary to do this instead of just using PIXEL directly to
3447 get color reference counts right. */
3449 unsigned long
3450 x_copy_color (f, pixel)
3451 struct frame *f;
3452 unsigned long pixel;
3454 XColor color;
3456 color.pixel = pixel;
3457 BLOCK_INPUT;
3458 x_query_color (f, &color);
3459 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3460 UNBLOCK_INPUT;
3461 #ifdef DEBUG_X_COLORS
3462 register_color (pixel);
3463 #endif
3464 return color.pixel;
3468 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3469 It's necessary to do this instead of just using PIXEL directly to
3470 get color reference counts right. */
3472 unsigned long
3473 x_copy_dpy_color (dpy, cmap, pixel)
3474 Display *dpy;
3475 Colormap cmap;
3476 unsigned long pixel;
3478 XColor color;
3480 color.pixel = pixel;
3481 BLOCK_INPUT;
3482 XQueryColor (dpy, cmap, &color);
3483 XAllocColor (dpy, cmap, &color);
3484 UNBLOCK_INPUT;
3485 #ifdef DEBUG_X_COLORS
3486 register_color (pixel);
3487 #endif
3488 return color.pixel;
3492 /* Brightness beyond which a color won't have its highlight brightness
3493 boosted.
3495 Nominally, highlight colors for `3d' faces are calculated by
3496 brightening an object's color by a constant scale factor, but this
3497 doesn't yield good results for dark colors, so for colors who's
3498 brightness is less than this value (on a scale of 0-65535) have an
3499 use an additional additive factor.
3501 The value here is set so that the default menu-bar/mode-line color
3502 (grey75) will not have its highlights changed at all. */
3503 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3506 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3507 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3508 If this produces the same color as PIXEL, try a color where all RGB
3509 values have DELTA added. Return the allocated color in *PIXEL.
3510 DISPLAY is the X display, CMAP is the colormap to operate on.
3511 Value is non-zero if successful. */
3513 static int
3514 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3515 struct frame *f;
3516 Display *display;
3517 Colormap cmap;
3518 unsigned long *pixel;
3519 double factor;
3520 int delta;
3522 XColor color, new;
3523 long bright;
3524 int success_p;
3526 /* Get RGB color values. */
3527 color.pixel = *pixel;
3528 x_query_color (f, &color);
3530 /* Change RGB values by specified FACTOR. Avoid overflow! */
3531 xassert (factor >= 0);
3532 new.red = min (0xffff, factor * color.red);
3533 new.green = min (0xffff, factor * color.green);
3534 new.blue = min (0xffff, factor * color.blue);
3536 /* Calculate brightness of COLOR. */
3537 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3539 /* We only boost colors that are darker than
3540 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3541 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3542 /* Make an additive adjustment to NEW, because it's dark enough so
3543 that scaling by FACTOR alone isn't enough. */
3545 /* How far below the limit this color is (0 - 1, 1 being darker). */
3546 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3547 /* The additive adjustment. */
3548 int min_delta = delta * dimness * factor / 2;
3550 if (factor < 1)
3552 new.red = max (0, new.red - min_delta);
3553 new.green = max (0, new.green - min_delta);
3554 new.blue = max (0, new.blue - min_delta);
3556 else
3558 new.red = min (0xffff, min_delta + new.red);
3559 new.green = min (0xffff, min_delta + new.green);
3560 new.blue = min (0xffff, min_delta + new.blue);
3564 /* Try to allocate the color. */
3565 success_p = x_alloc_nearest_color (f, cmap, &new);
3566 if (success_p)
3568 if (new.pixel == *pixel)
3570 /* If we end up with the same color as before, try adding
3571 delta to the RGB values. */
3572 x_free_colors (f, &new.pixel, 1);
3574 new.red = min (0xffff, delta + color.red);
3575 new.green = min (0xffff, delta + color.green);
3576 new.blue = min (0xffff, delta + color.blue);
3577 success_p = x_alloc_nearest_color (f, cmap, &new);
3579 else
3580 success_p = 1;
3581 *pixel = new.pixel;
3584 return success_p;
3588 /* Set up the foreground color for drawing relief lines of glyph
3589 string S. RELIEF is a pointer to a struct relief containing the GC
3590 with which lines will be drawn. Use a color that is FACTOR or
3591 DELTA lighter or darker than the relief's background which is found
3592 in S->f->output_data.x->relief_background. If such a color cannot
3593 be allocated, use DEFAULT_PIXEL, instead. */
3595 static void
3596 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3597 struct frame *f;
3598 struct relief *relief;
3599 double factor;
3600 int delta;
3601 unsigned long default_pixel;
3603 XGCValues xgcv;
3604 struct x_output *di = f->output_data.x;
3605 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3606 unsigned long pixel;
3607 unsigned long background = di->relief_background;
3608 Colormap cmap = FRAME_X_COLORMAP (f);
3609 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3610 Display *dpy = FRAME_X_DISPLAY (f);
3612 xgcv.graphics_exposures = False;
3613 xgcv.line_width = 1;
3615 /* Free previously allocated color. The color cell will be reused
3616 when it has been freed as many times as it was allocated, so this
3617 doesn't affect faces using the same colors. */
3618 if (relief->gc
3619 && relief->allocated_p)
3621 x_free_colors (f, &relief->pixel, 1);
3622 relief->allocated_p = 0;
3625 /* Allocate new color. */
3626 xgcv.foreground = default_pixel;
3627 pixel = background;
3628 if (dpyinfo->n_planes != 1
3629 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3631 relief->allocated_p = 1;
3632 xgcv.foreground = relief->pixel = pixel;
3635 if (relief->gc == 0)
3637 xgcv.stipple = dpyinfo->gray;
3638 mask |= GCStipple;
3639 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3641 else
3642 XChangeGC (dpy, relief->gc, mask, &xgcv);
3646 /* Set up colors for the relief lines around glyph string S. */
3648 static void
3649 x_setup_relief_colors (s)
3650 struct glyph_string *s;
3652 struct x_output *di = s->f->output_data.x;
3653 unsigned long color;
3655 if (s->face->use_box_color_for_shadows_p)
3656 color = s->face->box_color;
3657 else
3659 XGCValues xgcv;
3661 /* Get the background color of the face. */
3662 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3663 color = xgcv.background;
3666 if (di->white_relief.gc == 0
3667 || color != di->relief_background)
3669 di->relief_background = color;
3670 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3671 WHITE_PIX_DEFAULT (s->f));
3672 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3673 BLACK_PIX_DEFAULT (s->f));
3678 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3679 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3680 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3681 relief. LEFT_P non-zero means draw a relief on the left side of
3682 the rectangle. RIGHT_P non-zero means draw a relief on the right
3683 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3684 when drawing. */
3686 static void
3687 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3688 raised_p, left_p, right_p, clip_rect)
3689 struct frame *f;
3690 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3691 XRectangle *clip_rect;
3693 int i;
3694 GC gc;
3696 if (raised_p)
3697 gc = f->output_data.x->white_relief.gc;
3698 else
3699 gc = f->output_data.x->black_relief.gc;
3700 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3702 /* Top. */
3703 for (i = 0; i < width; ++i)
3704 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3705 left_x + i * left_p, top_y + i,
3706 right_x + 1 - i * right_p, top_y + i);
3708 /* Left. */
3709 if (left_p)
3710 for (i = 0; i < width; ++i)
3711 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3712 left_x + i, top_y + i, left_x + i, bottom_y - i);
3714 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3715 if (raised_p)
3716 gc = f->output_data.x->black_relief.gc;
3717 else
3718 gc = f->output_data.x->white_relief.gc;
3719 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3721 /* Bottom. */
3722 for (i = 0; i < width; ++i)
3723 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3724 left_x + i * left_p, bottom_y - i,
3725 right_x + 1 - i * right_p, bottom_y - i);
3727 /* Right. */
3728 if (right_p)
3729 for (i = 0; i < width; ++i)
3730 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3731 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3733 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3737 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3738 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3739 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3740 left side of the rectangle. RIGHT_P non-zero means draw a line
3741 on the right side of the rectangle. CLIP_RECT is the clipping
3742 rectangle to use when drawing. */
3744 static void
3745 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3746 left_p, right_p, clip_rect)
3747 struct glyph_string *s;
3748 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3749 XRectangle *clip_rect;
3751 XGCValues xgcv;
3753 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3754 XSetForeground (s->display, s->gc, s->face->box_color);
3755 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3757 /* Top. */
3758 XFillRectangle (s->display, s->window, s->gc,
3759 left_x, top_y, right_x - left_x + 1, width);
3761 /* Left. */
3762 if (left_p)
3763 XFillRectangle (s->display, s->window, s->gc,
3764 left_x, top_y, width, bottom_y - top_y + 1);
3766 /* Bottom. */
3767 XFillRectangle (s->display, s->window, s->gc,
3768 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3770 /* Right. */
3771 if (right_p)
3772 XFillRectangle (s->display, s->window, s->gc,
3773 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3775 XSetForeground (s->display, s->gc, xgcv.foreground);
3776 XSetClipMask (s->display, s->gc, None);
3780 /* Draw a box around glyph string S. */
3782 static void
3783 x_draw_glyph_string_box (s)
3784 struct glyph_string *s;
3786 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3787 int left_p, right_p;
3788 struct glyph *last_glyph;
3789 XRectangle clip_rect;
3791 last_x = window_box_right (s->w, s->area);
3792 if (s->row->full_width_p
3793 && !s->w->pseudo_window_p)
3795 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3796 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3797 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3800 /* The glyph that may have a right box line. */
3801 last_glyph = (s->cmp || s->img
3802 ? s->first_glyph
3803 : s->first_glyph + s->nchars - 1);
3805 width = s->face->box_line_width;
3806 raised_p = s->face->box == FACE_RAISED_BOX;
3807 left_x = s->x;
3808 right_x = ((s->row->full_width_p
3809 ? last_x - 1
3810 : min (last_x, s->x + s->background_width) - 1));
3811 top_y = s->y;
3812 bottom_y = top_y + s->height - 1;
3814 left_p = (s->first_glyph->left_box_line_p
3815 || (s->hl == DRAW_MOUSE_FACE
3816 && (s->prev == NULL
3817 || s->prev->hl != s->hl)));
3818 right_p = (last_glyph->right_box_line_p
3819 || (s->hl == DRAW_MOUSE_FACE
3820 && (s->next == NULL
3821 || s->next->hl != s->hl)));
3823 x_get_glyph_string_clip_rect (s, &clip_rect);
3825 if (s->face->box == FACE_SIMPLE_BOX)
3826 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3827 left_p, right_p, &clip_rect);
3828 else
3830 x_setup_relief_colors (s);
3831 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3832 width, raised_p, left_p, right_p, &clip_rect);
3837 /* Draw foreground of image glyph string S. */
3839 static void
3840 x_draw_image_foreground (s)
3841 struct glyph_string *s;
3843 int x;
3844 int y = s->ybase - image_ascent (s->img, s->face);
3846 /* If first glyph of S has a left box line, start drawing it to the
3847 right of that line. */
3848 if (s->face->box != FACE_NO_BOX
3849 && s->first_glyph->left_box_line_p)
3850 x = s->x + s->face->box_line_width;
3851 else
3852 x = s->x;
3854 /* If there is a margin around the image, adjust x- and y-position
3855 by that margin. */
3856 if (s->img->margin)
3858 x += s->img->margin;
3859 y += s->img->margin;
3862 if (s->img->pixmap)
3864 if (s->img->mask)
3866 /* We can't set both a clip mask and use XSetClipRectangles
3867 because the latter also sets a clip mask. We also can't
3868 trust on the shape extension to be available
3869 (XShapeCombineRegion). So, compute the rectangle to draw
3870 manually. */
3871 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3872 | GCFunction);
3873 XGCValues xgcv;
3874 XRectangle clip_rect, image_rect, r;
3876 xgcv.clip_mask = s->img->mask;
3877 xgcv.clip_x_origin = x;
3878 xgcv.clip_y_origin = y;
3879 xgcv.function = GXcopy;
3880 XChangeGC (s->display, s->gc, mask, &xgcv);
3882 x_get_glyph_string_clip_rect (s, &clip_rect);
3883 image_rect.x = x;
3884 image_rect.y = y;
3885 image_rect.width = s->img->width;
3886 image_rect.height = s->img->height;
3887 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3888 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3889 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3891 else
3893 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3894 XGCValues xgcv;
3895 XRectangle clip_rect, image_rect, r;
3897 x_get_glyph_string_clip_rect (s, &clip_rect);
3898 image_rect.x = x;
3899 image_rect.y = y;
3900 image_rect.width = s->img->width;
3901 image_rect.height = s->img->height;
3902 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3903 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3904 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3906 /* When the image has a mask, we can expect that at
3907 least part of a mouse highlight or a block cursor will
3908 be visible. If the image doesn't have a mask, make
3909 a block cursor visible by drawing a rectangle around
3910 the image. I believe it's looking better if we do
3911 nothing here for mouse-face. */
3912 if (s->hl == DRAW_CURSOR)
3913 XDrawRectangle (s->display, s->window, s->gc, x, y,
3914 s->img->width - 1, s->img->height - 1);
3917 else
3918 /* Draw a rectangle if image could not be loaded. */
3919 XDrawRectangle (s->display, s->window, s->gc, x, y,
3920 s->img->width - 1, s->img->height - 1);
3924 /* Draw a relief around the image glyph string S. */
3926 static void
3927 x_draw_image_relief (s)
3928 struct glyph_string *s;
3930 int x0, y0, x1, y1, thick, raised_p;
3931 XRectangle r;
3932 int x;
3933 int y = s->ybase - image_ascent (s->img, s->face);
3935 /* If first glyph of S has a left box line, start drawing it to the
3936 right of that line. */
3937 if (s->face->box != FACE_NO_BOX
3938 && s->first_glyph->left_box_line_p)
3939 x = s->x + s->face->box_line_width;
3940 else
3941 x = s->x;
3943 /* If there is a margin around the image, adjust x- and y-position
3944 by that margin. */
3945 if (s->img->margin)
3947 x += s->img->margin;
3948 y += s->img->margin;
3951 if (s->hl == DRAW_IMAGE_SUNKEN
3952 || s->hl == DRAW_IMAGE_RAISED)
3954 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3955 raised_p = s->hl == DRAW_IMAGE_RAISED;
3957 else
3959 thick = abs (s->img->relief);
3960 raised_p = s->img->relief > 0;
3963 x0 = x - thick;
3964 y0 = y - thick;
3965 x1 = x + s->img->width + thick - 1;
3966 y1 = y + s->img->height + thick - 1;
3968 x_setup_relief_colors (s);
3969 x_get_glyph_string_clip_rect (s, &r);
3970 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3974 /* Draw the foreground of image glyph string S to PIXMAP. */
3976 static void
3977 x_draw_image_foreground_1 (s, pixmap)
3978 struct glyph_string *s;
3979 Pixmap pixmap;
3981 int x;
3982 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3984 /* If first glyph of S has a left box line, start drawing it to the
3985 right of that line. */
3986 if (s->face->box != FACE_NO_BOX
3987 && s->first_glyph->left_box_line_p)
3988 x = s->face->box_line_width;
3989 else
3990 x = 0;
3992 /* If there is a margin around the image, adjust x- and y-position
3993 by that margin. */
3994 if (s->img->margin)
3996 x += s->img->margin;
3997 y += s->img->margin;
4000 if (s->img->pixmap)
4002 if (s->img->mask)
4004 /* We can't set both a clip mask and use XSetClipRectangles
4005 because the latter also sets a clip mask. We also can't
4006 trust on the shape extension to be available
4007 (XShapeCombineRegion). So, compute the rectangle to draw
4008 manually. */
4009 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4010 | GCFunction);
4011 XGCValues xgcv;
4013 xgcv.clip_mask = s->img->mask;
4014 xgcv.clip_x_origin = x;
4015 xgcv.clip_y_origin = y;
4016 xgcv.function = GXcopy;
4017 XChangeGC (s->display, s->gc, mask, &xgcv);
4019 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4020 0, 0, s->img->width, s->img->height, x, y);
4021 XSetClipMask (s->display, s->gc, None);
4023 else
4025 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4026 0, 0, s->img->width, s->img->height, x, y);
4028 /* When the image has a mask, we can expect that at
4029 least part of a mouse highlight or a block cursor will
4030 be visible. If the image doesn't have a mask, make
4031 a block cursor visible by drawing a rectangle around
4032 the image. I believe it's looking better if we do
4033 nothing here for mouse-face. */
4034 if (s->hl == DRAW_CURSOR)
4035 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4036 s->img->width - 1, s->img->height - 1);
4039 else
4040 /* Draw a rectangle if image could not be loaded. */
4041 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4042 s->img->width - 1, s->img->height - 1);
4046 /* Draw part of the background of glyph string S. X, Y, W, and H
4047 give the rectangle to draw. */
4049 static void
4050 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4051 struct glyph_string *s;
4052 int x, y, w, h;
4054 if (s->stippled_p)
4056 /* Fill background with a stipple pattern. */
4057 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4058 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4059 XSetFillStyle (s->display, s->gc, FillSolid);
4061 else
4062 x_clear_glyph_string_rect (s, x, y, w, h);
4066 /* Draw image glyph string S.
4068 s->y
4069 s->x +-------------------------
4070 | s->face->box
4072 | +-------------------------
4073 | | s->img->margin
4075 | | +-------------------
4076 | | | the image
4080 static void
4081 x_draw_image_glyph_string (s)
4082 struct glyph_string *s;
4084 int x, y;
4085 int box_line_width = s->face->box_line_width;
4086 int margin = s->img->margin;
4087 int height;
4088 Pixmap pixmap = None;
4090 height = s->height - 2 * box_line_width;
4092 /* Fill background with face under the image. Do it only if row is
4093 taller than image or if image has a clip mask to reduce
4094 flickering. */
4095 s->stippled_p = s->face->stipple != 0;
4096 if (height > s->img->height
4097 || margin
4098 || s->img->mask
4099 || s->img->pixmap == 0
4100 || s->width != s->background_width)
4102 if (box_line_width && s->first_glyph->left_box_line_p)
4103 x = s->x + box_line_width;
4104 else
4105 x = s->x;
4107 y = s->y + box_line_width;
4109 if (s->img->mask)
4111 /* Create a pixmap as large as the glyph string. Fill it
4112 with the background color. Copy the image to it, using
4113 its mask. Copy the temporary pixmap to the display. */
4114 Screen *screen = FRAME_X_SCREEN (s->f);
4115 int depth = DefaultDepthOfScreen (screen);
4117 /* Create a pixmap as large as the glyph string. */
4118 pixmap = XCreatePixmap (s->display, s->window,
4119 s->background_width,
4120 s->height, depth);
4122 /* Don't clip in the following because we're working on the
4123 pixmap. */
4124 XSetClipMask (s->display, s->gc, None);
4126 /* Fill the pixmap with the background color/stipple. */
4127 if (s->stippled_p)
4129 /* Fill background with a stipple pattern. */
4130 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4131 XFillRectangle (s->display, pixmap, s->gc,
4132 0, 0, s->background_width, s->height);
4133 XSetFillStyle (s->display, s->gc, FillSolid);
4135 else
4137 XGCValues xgcv;
4138 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4139 &xgcv);
4140 XSetForeground (s->display, s->gc, xgcv.background);
4141 XFillRectangle (s->display, pixmap, s->gc,
4142 0, 0, s->background_width, s->height);
4143 XSetForeground (s->display, s->gc, xgcv.foreground);
4146 else
4147 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4149 s->background_filled_p = 1;
4152 /* Draw the foreground. */
4153 if (pixmap != None)
4155 x_draw_image_foreground_1 (s, pixmap);
4156 x_set_glyph_string_clipping (s);
4157 XCopyArea (s->display, pixmap, s->window, s->gc,
4158 0, 0, s->background_width, s->height, s->x, s->y);
4159 XFreePixmap (s->display, pixmap);
4161 else
4162 x_draw_image_foreground (s);
4164 /* If we must draw a relief around the image, do it. */
4165 if (s->img->relief
4166 || s->hl == DRAW_IMAGE_RAISED
4167 || s->hl == DRAW_IMAGE_SUNKEN)
4168 x_draw_image_relief (s);
4172 /* Draw stretch glyph string S. */
4174 static void
4175 x_draw_stretch_glyph_string (s)
4176 struct glyph_string *s;
4178 xassert (s->first_glyph->type == STRETCH_GLYPH);
4179 s->stippled_p = s->face->stipple != 0;
4181 if (s->hl == DRAW_CURSOR
4182 && !x_stretch_cursor_p)
4184 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4185 as wide as the stretch glyph. */
4186 int width = min (CANON_X_UNIT (s->f), s->background_width);
4188 /* Draw cursor. */
4189 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4191 /* Clear rest using the GC of the original non-cursor face. */
4192 if (width < s->background_width)
4194 GC gc = s->face->gc;
4195 int x = s->x + width, y = s->y;
4196 int w = s->background_width - width, h = s->height;
4197 XRectangle r;
4199 x_get_glyph_string_clip_rect (s, &r);
4200 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4202 if (s->face->stipple)
4204 /* Fill background with a stipple pattern. */
4205 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4206 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4207 XSetFillStyle (s->display, gc, FillSolid);
4209 else
4211 XGCValues xgcv;
4212 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4213 XSetForeground (s->display, gc, xgcv.background);
4214 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4215 XSetForeground (s->display, gc, xgcv.foreground);
4219 else
4220 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4221 s->height);
4223 s->background_filled_p = 1;
4227 /* Draw glyph string S. */
4229 static void
4230 x_draw_glyph_string (s)
4231 struct glyph_string *s;
4233 /* If S draws into the background of its successor, draw the
4234 background of the successor first so that S can draw into it.
4235 This makes S->next use XDrawString instead of XDrawImageString. */
4236 if (s->next && s->right_overhang && !s->for_overlaps_p)
4238 xassert (s->next->img == NULL);
4239 x_set_glyph_string_gc (s->next);
4240 x_set_glyph_string_clipping (s->next);
4241 x_draw_glyph_string_background (s->next, 1);
4244 /* Set up S->gc, set clipping and draw S. */
4245 x_set_glyph_string_gc (s);
4246 x_set_glyph_string_clipping (s);
4248 switch (s->first_glyph->type)
4250 case IMAGE_GLYPH:
4251 x_draw_image_glyph_string (s);
4252 break;
4254 case STRETCH_GLYPH:
4255 x_draw_stretch_glyph_string (s);
4256 break;
4258 case CHAR_GLYPH:
4259 if (s->for_overlaps_p)
4260 s->background_filled_p = 1;
4261 else
4262 x_draw_glyph_string_background (s, 0);
4263 x_draw_glyph_string_foreground (s);
4264 break;
4266 case COMPOSITE_GLYPH:
4267 if (s->for_overlaps_p || s->gidx > 0)
4268 s->background_filled_p = 1;
4269 else
4270 x_draw_glyph_string_background (s, 1);
4271 x_draw_composite_glyph_string_foreground (s);
4272 break;
4274 default:
4275 abort ();
4278 if (!s->for_overlaps_p)
4280 /* Draw underline. */
4281 if (s->face->underline_p)
4283 unsigned long tem, h;
4284 int y;
4286 /* Get the underline thickness. Default is 1 pixel. */
4287 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4288 h = 1;
4290 /* Get the underline position. This is the recommended
4291 vertical offset in pixels from the baseline to the top of
4292 the underline. This is a signed value according to the
4293 specs, and its default is
4295 ROUND ((maximum descent) / 2), with
4296 ROUND(x) = floor (x + 0.5) */
4298 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4299 y = s->ybase + (long) tem;
4300 else if (s->face->font)
4301 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4302 else
4303 y = s->height - h;
4305 if (s->face->underline_defaulted_p)
4306 XFillRectangle (s->display, s->window, s->gc,
4307 s->x, y, s->width, h);
4308 else
4310 XGCValues xgcv;
4311 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4312 XSetForeground (s->display, s->gc, s->face->underline_color);
4313 XFillRectangle (s->display, s->window, s->gc,
4314 s->x, y, s->width, h);
4315 XSetForeground (s->display, s->gc, xgcv.foreground);
4319 /* Draw overline. */
4320 if (s->face->overline_p)
4322 unsigned long dy = 0, h = 1;
4324 if (s->face->overline_color_defaulted_p)
4325 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4326 s->width, h);
4327 else
4329 XGCValues xgcv;
4330 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4331 XSetForeground (s->display, s->gc, s->face->overline_color);
4332 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4333 s->width, h);
4334 XSetForeground (s->display, s->gc, xgcv.foreground);
4338 /* Draw strike-through. */
4339 if (s->face->strike_through_p)
4341 unsigned long h = 1;
4342 unsigned long dy = (s->height - h) / 2;
4344 if (s->face->strike_through_color_defaulted_p)
4345 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4346 s->width, h);
4347 else
4349 XGCValues xgcv;
4350 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4351 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4352 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4353 s->width, h);
4354 XSetForeground (s->display, s->gc, xgcv.foreground);
4358 /* Draw relief. */
4359 if (s->face->box != FACE_NO_BOX)
4360 x_draw_glyph_string_box (s);
4363 /* Reset clipping. */
4364 XSetClipMask (s->display, s->gc, None);
4368 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4369 struct face **, int));
4372 /* Fill glyph string S with composition components specified by S->cmp.
4374 FACES is an array of faces for all components of this composition.
4375 S->gidx is the index of the first component for S.
4376 OVERLAPS_P non-zero means S should draw the foreground only, and
4377 use its physical height for clipping.
4379 Value is the index of a component not in S. */
4381 static int
4382 x_fill_composite_glyph_string (s, faces, overlaps_p)
4383 struct glyph_string *s;
4384 struct face **faces;
4385 int overlaps_p;
4387 int i;
4389 xassert (s);
4391 s->for_overlaps_p = overlaps_p;
4393 s->face = faces[s->gidx];
4394 s->font = s->face->font;
4395 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4397 /* For all glyphs of this composition, starting at the offset
4398 S->gidx, until we reach the end of the definition or encounter a
4399 glyph that requires the different face, add it to S. */
4400 ++s->nchars;
4401 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4402 ++s->nchars;
4404 /* All glyph strings for the same composition has the same width,
4405 i.e. the width set for the first component of the composition. */
4407 s->width = s->first_glyph->pixel_width;
4409 /* If the specified font could not be loaded, use the frame's
4410 default font, but record the fact that we couldn't load it in
4411 the glyph string so that we can draw rectangles for the
4412 characters of the glyph string. */
4413 if (s->font == NULL)
4415 s->font_not_found_p = 1;
4416 s->font = FRAME_FONT (s->f);
4419 /* Adjust base line for subscript/superscript text. */
4420 s->ybase += s->first_glyph->voffset;
4422 xassert (s->face && s->face->gc);
4424 /* This glyph string must always be drawn with 16-bit functions. */
4425 s->two_byte_p = 1;
4427 return s->gidx + s->nchars;
4431 /* Fill glyph string S from a sequence of character glyphs.
4433 FACE_ID is the face id of the string. START is the index of the
4434 first glyph to consider, END is the index of the last + 1.
4435 OVERLAPS_P non-zero means S should draw the foreground only, and
4436 use its physical height for clipping.
4438 Value is the index of the first glyph not in S. */
4440 static int
4441 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4442 struct glyph_string *s;
4443 int face_id;
4444 int start, end, overlaps_p;
4446 struct glyph *glyph, *last;
4447 int voffset;
4448 int glyph_not_available_p;
4450 xassert (s->f == XFRAME (s->w->frame));
4451 xassert (s->nchars == 0);
4452 xassert (start >= 0 && end > start);
4454 s->for_overlaps_p = overlaps_p,
4455 glyph = s->row->glyphs[s->area] + start;
4456 last = s->row->glyphs[s->area] + end;
4457 voffset = glyph->voffset;
4459 glyph_not_available_p = glyph->glyph_not_available_p;
4461 while (glyph < last
4462 && glyph->type == CHAR_GLYPH
4463 && glyph->voffset == voffset
4464 /* Same face id implies same font, nowadays. */
4465 && glyph->face_id == face_id
4466 && glyph->glyph_not_available_p == glyph_not_available_p)
4468 int two_byte_p;
4470 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4471 s->char2b + s->nchars,
4472 &two_byte_p);
4473 s->two_byte_p = two_byte_p;
4474 ++s->nchars;
4475 xassert (s->nchars <= end - start);
4476 s->width += glyph->pixel_width;
4477 ++glyph;
4480 s->font = s->face->font;
4481 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4483 /* If the specified font could not be loaded, use the frame's font,
4484 but record the fact that we couldn't load it in
4485 S->font_not_found_p so that we can draw rectangles for the
4486 characters of the glyph string. */
4487 if (s->font == NULL || glyph_not_available_p)
4489 s->font_not_found_p = 1;
4490 s->font = FRAME_FONT (s->f);
4493 /* Adjust base line for subscript/superscript text. */
4494 s->ybase += voffset;
4496 xassert (s->face && s->face->gc);
4497 return glyph - s->row->glyphs[s->area];
4501 /* Fill glyph string S from image glyph S->first_glyph. */
4503 static void
4504 x_fill_image_glyph_string (s)
4505 struct glyph_string *s;
4507 xassert (s->first_glyph->type == IMAGE_GLYPH);
4508 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4509 xassert (s->img);
4510 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4511 s->font = s->face->font;
4512 s->width = s->first_glyph->pixel_width;
4514 /* Adjust base line for subscript/superscript text. */
4515 s->ybase += s->first_glyph->voffset;
4519 /* Fill glyph string S from a sequence of stretch glyphs.
4521 ROW is the glyph row in which the glyphs are found, AREA is the
4522 area within the row. START is the index of the first glyph to
4523 consider, END is the index of the last + 1.
4525 Value is the index of the first glyph not in S. */
4527 static int
4528 x_fill_stretch_glyph_string (s, row, area, start, end)
4529 struct glyph_string *s;
4530 struct glyph_row *row;
4531 enum glyph_row_area area;
4532 int start, end;
4534 struct glyph *glyph, *last;
4535 int voffset, face_id;
4537 xassert (s->first_glyph->type == STRETCH_GLYPH);
4539 glyph = s->row->glyphs[s->area] + start;
4540 last = s->row->glyphs[s->area] + end;
4541 face_id = glyph->face_id;
4542 s->face = FACE_FROM_ID (s->f, face_id);
4543 s->font = s->face->font;
4544 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4545 s->width = glyph->pixel_width;
4546 voffset = glyph->voffset;
4548 for (++glyph;
4549 (glyph < last
4550 && glyph->type == STRETCH_GLYPH
4551 && glyph->voffset == voffset
4552 && glyph->face_id == face_id);
4553 ++glyph)
4554 s->width += glyph->pixel_width;
4556 /* Adjust base line for subscript/superscript text. */
4557 s->ybase += voffset;
4559 xassert (s->face && s->face->gc);
4560 return glyph - s->row->glyphs[s->area];
4564 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4565 of XChar2b structures for S; it can't be allocated in
4566 x_init_glyph_string because it must be allocated via `alloca'. W
4567 is the window on which S is drawn. ROW and AREA are the glyph row
4568 and area within the row from which S is constructed. START is the
4569 index of the first glyph structure covered by S. HL is a
4570 face-override for drawing S. */
4572 static void
4573 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4574 struct glyph_string *s;
4575 XChar2b *char2b;
4576 struct window *w;
4577 struct glyph_row *row;
4578 enum glyph_row_area area;
4579 int start;
4580 enum draw_glyphs_face hl;
4582 bzero (s, sizeof *s);
4583 s->w = w;
4584 s->f = XFRAME (w->frame);
4585 s->display = FRAME_X_DISPLAY (s->f);
4586 s->window = FRAME_X_WINDOW (s->f);
4587 s->char2b = char2b;
4588 s->hl = hl;
4589 s->row = row;
4590 s->area = area;
4591 s->first_glyph = row->glyphs[area] + start;
4592 s->height = row->height;
4593 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4595 /* Display the internal border below the tool-bar window. */
4596 if (s->w == XWINDOW (s->f->tool_bar_window))
4597 s->y -= s->f->output_data.x->internal_border_width;
4599 s->ybase = s->y + row->ascent;
4603 /* Set background width of glyph string S. START is the index of the
4604 first glyph following S. LAST_X is the right-most x-position + 1
4605 in the drawing area. */
4607 static INLINE void
4608 x_set_glyph_string_background_width (s, start, last_x)
4609 struct glyph_string *s;
4610 int start;
4611 int last_x;
4613 /* If the face of this glyph string has to be drawn to the end of
4614 the drawing area, set S->extends_to_end_of_line_p. */
4615 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4617 if (start == s->row->used[s->area]
4618 && s->hl == DRAW_NORMAL_TEXT
4619 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4620 || s->face->background != default_face->background
4621 || s->face->stipple != default_face->stipple))
4622 s->extends_to_end_of_line_p = 1;
4624 /* If S extends its face to the end of the line, set its
4625 background_width to the distance to the right edge of the drawing
4626 area. */
4627 if (s->extends_to_end_of_line_p)
4628 s->background_width = last_x - s->x + 1;
4629 else
4630 s->background_width = s->width;
4634 /* Add a glyph string for a stretch glyph to the list of strings
4635 between HEAD and TAIL. START is the index of the stretch glyph in
4636 row area AREA of glyph row ROW. END is the index of the last glyph
4637 in that glyph row area. X is the current output position assigned
4638 to the new glyph string constructed. HL overrides that face of the
4639 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4640 is the right-most x-position of the drawing area. */
4642 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4643 and below -- keep them on one line. */
4644 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4645 do \
4647 s = (struct glyph_string *) alloca (sizeof *s); \
4648 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4649 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4650 x_append_glyph_string (&HEAD, &TAIL, s); \
4651 s->x = (X); \
4653 while (0)
4656 /* Add a glyph string for an image glyph to the list of strings
4657 between HEAD and TAIL. START is the index of the image glyph in
4658 row area AREA of glyph row ROW. END is the index of the last glyph
4659 in that glyph row area. X is the current output position assigned
4660 to the new glyph string constructed. HL overrides that face of the
4661 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4662 is the right-most x-position of the drawing area. */
4664 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4665 do \
4667 s = (struct glyph_string *) alloca (sizeof *s); \
4668 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4669 x_fill_image_glyph_string (s); \
4670 x_append_glyph_string (&HEAD, &TAIL, s); \
4671 ++START; \
4672 s->x = (X); \
4674 while (0)
4677 /* Add a glyph string for a sequence of character glyphs to the list
4678 of strings between HEAD and TAIL. START is the index of the first
4679 glyph in row area AREA of glyph row ROW that is part of the new
4680 glyph string. END is the index of the last glyph in that glyph row
4681 area. X is the current output position assigned to the new glyph
4682 string constructed. HL overrides that face of the glyph; e.g. it
4683 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4684 right-most x-position of the drawing area. */
4686 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4687 do \
4689 int c, face_id; \
4690 XChar2b *char2b; \
4692 c = (ROW)->glyphs[AREA][START].u.ch; \
4693 face_id = (ROW)->glyphs[AREA][START].face_id; \
4695 s = (struct glyph_string *) alloca (sizeof *s); \
4696 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4697 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4698 x_append_glyph_string (&HEAD, &TAIL, s); \
4699 s->x = (X); \
4700 START = x_fill_glyph_string (s, face_id, START, END, \
4701 OVERLAPS_P); \
4703 while (0)
4706 /* Add a glyph string for a composite sequence to the list of strings
4707 between HEAD and TAIL. START is the index of the first glyph in
4708 row area AREA of glyph row ROW that is part of the new glyph
4709 string. END is the index of the last glyph in that glyph row area.
4710 X is the current output position assigned to the new glyph string
4711 constructed. HL overrides that face of the glyph; e.g. it is
4712 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4713 x-position of the drawing area. */
4715 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4716 do { \
4717 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4718 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4719 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4720 struct composition *cmp = composition_table[cmp_id]; \
4721 int glyph_len = cmp->glyph_len; \
4722 XChar2b *char2b; \
4723 struct face **faces; \
4724 struct glyph_string *first_s = NULL; \
4725 int n; \
4727 base_face = base_face->ascii_face; \
4728 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4729 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4730 /* At first, fill in `char2b' and `faces'. */ \
4731 for (n = 0; n < glyph_len; n++) \
4733 int c = COMPOSITION_GLYPH (cmp, n); \
4734 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4735 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4736 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4737 this_face_id, char2b + n, 1); \
4740 /* Make glyph_strings for each glyph sequence that is drawable by \
4741 the same face, and append them to HEAD/TAIL. */ \
4742 for (n = 0; n < cmp->glyph_len;) \
4744 s = (struct glyph_string *) alloca (sizeof *s); \
4745 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4746 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4747 s->cmp = cmp; \
4748 s->gidx = n; \
4749 s->x = (X); \
4751 if (n == 0) \
4752 first_s = s; \
4754 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4757 ++START; \
4758 s = first_s; \
4759 } while (0)
4762 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4763 of AREA of glyph row ROW on window W between indices START and END.
4764 HL overrides the face for drawing glyph strings, e.g. it is
4765 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4766 x-positions of the drawing area.
4768 This is an ugly monster macro construct because we must use alloca
4769 to allocate glyph strings (because x_draw_glyphs can be called
4770 asynchronously). */
4772 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4773 do \
4775 HEAD = TAIL = NULL; \
4776 while (START < END) \
4778 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4779 switch (first_glyph->type) \
4781 case CHAR_GLYPH: \
4782 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4783 TAIL, HL, X, LAST_X, \
4784 OVERLAPS_P); \
4785 break; \
4787 case COMPOSITE_GLYPH: \
4788 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4789 HEAD, TAIL, HL, X, LAST_X,\
4790 OVERLAPS_P); \
4791 break; \
4793 case STRETCH_GLYPH: \
4794 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4795 HEAD, TAIL, HL, X, LAST_X); \
4796 break; \
4798 case IMAGE_GLYPH: \
4799 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4800 TAIL, HL, X, LAST_X); \
4801 break; \
4803 default: \
4804 abort (); \
4807 x_set_glyph_string_background_width (s, START, LAST_X); \
4808 (X) += s->width; \
4811 while (0)
4814 /* Draw glyphs between START and END in AREA of ROW on window W,
4815 starting at x-position X. X is relative to AREA in W. HL is a
4816 face-override with the following meaning:
4818 DRAW_NORMAL_TEXT draw normally
4819 DRAW_CURSOR draw in cursor face
4820 DRAW_MOUSE_FACE draw in mouse face.
4821 DRAW_INVERSE_VIDEO draw in mode line face
4822 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4823 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4825 If REAL_START is non-null, return in *REAL_START the real starting
4826 position for display. This can be different from START in case
4827 overlapping glyphs must be displayed. If REAL_END is non-null,
4828 return in *REAL_END the real end position for display. This can be
4829 different from END in case overlapping glyphs must be displayed.
4831 If OVERLAPS_P is non-zero, draw only the foreground of characters
4832 and clip to the physical height of ROW.
4834 Value is the x-position reached, relative to AREA of W. */
4836 static int
4837 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4838 overlaps_p)
4839 struct window *w;
4840 int x;
4841 struct glyph_row *row;
4842 enum glyph_row_area area;
4843 int start, end;
4844 enum draw_glyphs_face hl;
4845 int *real_start, *real_end;
4846 int overlaps_p;
4848 struct glyph_string *head, *tail;
4849 struct glyph_string *s;
4850 int last_x, area_width;
4851 int x_reached;
4852 int i, j;
4854 /* Let's rather be paranoid than getting a SEGV. */
4855 end = min (end, row->used[area]);
4856 start = max (0, start);
4857 start = min (end, start);
4858 if (real_start)
4859 *real_start = start;
4860 if (real_end)
4861 *real_end = end;
4863 /* Translate X to frame coordinates. Set last_x to the right
4864 end of the drawing area. */
4865 if (row->full_width_p)
4867 /* X is relative to the left edge of W, without scroll bars
4868 or flag areas. */
4869 struct frame *f = XFRAME (w->frame);
4870 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4871 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4873 x += window_left_x;
4874 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4875 last_x = window_left_x + area_width;
4877 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4879 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4880 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4881 last_x += width;
4882 else
4883 x -= width;
4886 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4887 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4889 else
4891 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4892 area_width = window_box_width (w, area);
4893 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4896 /* Build a doubly-linked list of glyph_string structures between
4897 head and tail from what we have to draw. Note that the macro
4898 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4899 the reason we use a separate variable `i'. */
4900 i = start;
4901 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4902 overlaps_p);
4903 if (tail)
4904 x_reached = tail->x + tail->background_width;
4905 else
4906 x_reached = x;
4908 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4909 the row, redraw some glyphs in front or following the glyph
4910 strings built above. */
4911 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4913 int dummy_x = 0;
4914 struct glyph_string *h, *t;
4916 /* Compute overhangs for all glyph strings. */
4917 for (s = head; s; s = s->next)
4918 x_compute_glyph_string_overhangs (s);
4920 /* Prepend glyph strings for glyphs in front of the first glyph
4921 string that are overwritten because of the first glyph
4922 string's left overhang. The background of all strings
4923 prepended must be drawn because the first glyph string
4924 draws over it. */
4925 i = x_left_overwritten (head);
4926 if (i >= 0)
4928 j = i;
4929 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4930 DRAW_NORMAL_TEXT, dummy_x, last_x,
4931 overlaps_p);
4932 start = i;
4933 if (real_start)
4934 *real_start = start;
4935 x_compute_overhangs_and_x (t, head->x, 1);
4936 x_prepend_glyph_string_lists (&head, &tail, h, t);
4939 /* Prepend glyph strings for glyphs in front of the first glyph
4940 string that overwrite that glyph string because of their
4941 right overhang. For these strings, only the foreground must
4942 be drawn, because it draws over the glyph string at `head'.
4943 The background must not be drawn because this would overwrite
4944 right overhangs of preceding glyphs for which no glyph
4945 strings exist. */
4946 i = x_left_overwriting (head);
4947 if (i >= 0)
4949 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4950 DRAW_NORMAL_TEXT, dummy_x, last_x,
4951 overlaps_p);
4952 for (s = h; s; s = s->next)
4953 s->background_filled_p = 1;
4954 if (real_start)
4955 *real_start = i;
4956 x_compute_overhangs_and_x (t, head->x, 1);
4957 x_prepend_glyph_string_lists (&head, &tail, h, t);
4960 /* Append glyphs strings for glyphs following the last glyph
4961 string tail that are overwritten by tail. The background of
4962 these strings has to be drawn because tail's foreground draws
4963 over it. */
4964 i = x_right_overwritten (tail);
4965 if (i >= 0)
4967 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4968 DRAW_NORMAL_TEXT, x, last_x,
4969 overlaps_p);
4970 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4971 x_append_glyph_string_lists (&head, &tail, h, t);
4972 if (real_end)
4973 *real_end = i;
4976 /* Append glyph strings for glyphs following the last glyph
4977 string tail that overwrite tail. The foreground of such
4978 glyphs has to be drawn because it writes into the background
4979 of tail. The background must not be drawn because it could
4980 paint over the foreground of following glyphs. */
4981 i = x_right_overwriting (tail);
4982 if (i >= 0)
4984 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4985 DRAW_NORMAL_TEXT, x, last_x,
4986 overlaps_p);
4987 for (s = h; s; s = s->next)
4988 s->background_filled_p = 1;
4989 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4990 x_append_glyph_string_lists (&head, &tail, h, t);
4991 if (real_end)
4992 *real_end = i;
4996 /* Draw all strings. */
4997 for (s = head; s; s = s->next)
4998 x_draw_glyph_string (s);
5000 /* Value is the x-position up to which drawn, relative to AREA of W.
5001 This doesn't include parts drawn because of overhangs. */
5002 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5003 if (!row->full_width_p)
5005 if (area > LEFT_MARGIN_AREA)
5006 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5007 if (area > TEXT_AREA)
5008 x_reached -= window_box_width (w, TEXT_AREA);
5011 return x_reached;
5015 /* Fix the display of area AREA of overlapping row ROW in window W. */
5017 static void
5018 x_fix_overlapping_area (w, row, area)
5019 struct window *w;
5020 struct glyph_row *row;
5021 enum glyph_row_area area;
5023 int i, x;
5025 BLOCK_INPUT;
5027 if (area == LEFT_MARGIN_AREA)
5028 x = 0;
5029 else if (area == TEXT_AREA)
5030 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5031 else
5032 x = (window_box_width (w, LEFT_MARGIN_AREA)
5033 + window_box_width (w, TEXT_AREA));
5035 for (i = 0; i < row->used[area];)
5037 if (row->glyphs[area][i].overlaps_vertically_p)
5039 int start = i, start_x = x;
5043 x += row->glyphs[area][i].pixel_width;
5044 ++i;
5046 while (i < row->used[area]
5047 && row->glyphs[area][i].overlaps_vertically_p);
5049 x_draw_glyphs (w, start_x, row, area, start, i,
5050 (row->inverse_p
5051 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5052 NULL, NULL, 1);
5054 else
5056 x += row->glyphs[area][i].pixel_width;
5057 ++i;
5061 UNBLOCK_INPUT;
5065 /* Output LEN glyphs starting at START at the nominal cursor position.
5066 Advance the nominal cursor over the text. The global variable
5067 updated_window contains the window being updated, updated_row is
5068 the glyph row being updated, and updated_area is the area of that
5069 row being updated. */
5071 static void
5072 x_write_glyphs (start, len)
5073 struct glyph *start;
5074 int len;
5076 int x, hpos, real_start, real_end;
5078 xassert (updated_window && updated_row);
5079 BLOCK_INPUT;
5081 /* Write glyphs. */
5083 hpos = start - updated_row->glyphs[updated_area];
5084 x = x_draw_glyphs (updated_window, output_cursor.x,
5085 updated_row, updated_area,
5086 hpos, hpos + len,
5087 (updated_row->inverse_p
5088 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5089 &real_start, &real_end, 0);
5091 /* If we drew over the cursor, note that it is not visible any more. */
5092 note_overwritten_text_cursor (updated_window, real_start,
5093 real_end - real_start);
5095 UNBLOCK_INPUT;
5097 /* Advance the output cursor. */
5098 output_cursor.hpos += len;
5099 output_cursor.x = x;
5103 /* Insert LEN glyphs from START at the nominal cursor position. */
5105 static void
5106 x_insert_glyphs (start, len)
5107 struct glyph *start;
5108 register int len;
5110 struct frame *f;
5111 struct window *w;
5112 int line_height, shift_by_width, shifted_region_width;
5113 struct glyph_row *row;
5114 struct glyph *glyph;
5115 int frame_x, frame_y, hpos, real_start, real_end;
5117 xassert (updated_window && updated_row);
5118 BLOCK_INPUT;
5119 w = updated_window;
5120 f = XFRAME (WINDOW_FRAME (w));
5122 /* Get the height of the line we are in. */
5123 row = updated_row;
5124 line_height = row->height;
5126 /* Get the width of the glyphs to insert. */
5127 shift_by_width = 0;
5128 for (glyph = start; glyph < start + len; ++glyph)
5129 shift_by_width += glyph->pixel_width;
5131 /* Get the width of the region to shift right. */
5132 shifted_region_width = (window_box_width (w, updated_area)
5133 - output_cursor.x
5134 - shift_by_width);
5136 /* Shift right. */
5137 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5138 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5139 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5140 f->output_data.x->normal_gc,
5141 frame_x, frame_y,
5142 shifted_region_width, line_height,
5143 frame_x + shift_by_width, frame_y);
5145 /* Write the glyphs. */
5146 hpos = start - row->glyphs[updated_area];
5147 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5148 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5149 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5151 /* Advance the output cursor. */
5152 output_cursor.hpos += len;
5153 output_cursor.x += shift_by_width;
5154 UNBLOCK_INPUT;
5158 /* Delete N glyphs at the nominal cursor position. Not implemented
5159 for X frames. */
5161 static void
5162 x_delete_glyphs (n)
5163 register int n;
5165 abort ();
5169 /* Erase the current text line from the nominal cursor position
5170 (inclusive) to pixel column TO_X (exclusive). The idea is that
5171 everything from TO_X onward is already erased.
5173 TO_X is a pixel position relative to updated_area of
5174 updated_window. TO_X == -1 means clear to the end of this area. */
5176 static void
5177 x_clear_end_of_line (to_x)
5178 int to_x;
5180 struct frame *f;
5181 struct window *w = updated_window;
5182 int max_x, min_y, max_y;
5183 int from_x, from_y, to_y;
5185 xassert (updated_window && updated_row);
5186 f = XFRAME (w->frame);
5188 if (updated_row->full_width_p)
5190 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5191 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5192 && !w->pseudo_window_p)
5193 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5195 else
5196 max_x = window_box_width (w, updated_area);
5197 max_y = window_text_bottom_y (w);
5199 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5200 of window. For TO_X > 0, truncate to end of drawing area. */
5201 if (to_x == 0)
5202 return;
5203 else if (to_x < 0)
5204 to_x = max_x;
5205 else
5206 to_x = min (to_x, max_x);
5208 to_y = min (max_y, output_cursor.y + updated_row->height);
5210 /* Notice if the cursor will be cleared by this operation. */
5211 if (!updated_row->full_width_p)
5212 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5214 from_x = output_cursor.x;
5216 /* Translate to frame coordinates. */
5217 if (updated_row->full_width_p)
5219 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5220 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5222 else
5224 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5225 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5228 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5229 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5230 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5232 /* Prevent inadvertently clearing to end of the X window. */
5233 if (to_x > from_x && to_y > from_y)
5235 BLOCK_INPUT;
5236 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5237 from_x, from_y, to_x - from_x, to_y - from_y,
5238 False);
5239 UNBLOCK_INPUT;
5244 /* Clear entire frame. If updating_frame is non-null, clear that
5245 frame. Otherwise clear the selected frame. */
5247 static void
5248 x_clear_frame ()
5250 struct frame *f;
5252 if (updating_frame)
5253 f = updating_frame;
5254 else
5255 f = SELECTED_FRAME ();
5257 /* Clearing the frame will erase any cursor, so mark them all as no
5258 longer visible. */
5259 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5260 output_cursor.hpos = output_cursor.vpos = 0;
5261 output_cursor.x = -1;
5263 /* We don't set the output cursor here because there will always
5264 follow an explicit cursor_to. */
5265 BLOCK_INPUT;
5266 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5268 /* We have to clear the scroll bars, too. If we have changed
5269 colors or something like that, then they should be notified. */
5270 x_scroll_bar_clear (f);
5272 XFlush (FRAME_X_DISPLAY (f));
5273 UNBLOCK_INPUT;
5278 /* Invert the middle quarter of the frame for .15 sec. */
5280 /* We use the select system call to do the waiting, so we have to make
5281 sure it's available. If it isn't, we just won't do visual bells. */
5283 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5286 /* Subtract the `struct timeval' values X and Y, storing the result in
5287 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5289 static int
5290 timeval_subtract (result, x, y)
5291 struct timeval *result, x, y;
5293 /* Perform the carry for the later subtraction by updating y. This
5294 is safer because on some systems the tv_sec member is unsigned. */
5295 if (x.tv_usec < y.tv_usec)
5297 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5298 y.tv_usec -= 1000000 * nsec;
5299 y.tv_sec += nsec;
5302 if (x.tv_usec - y.tv_usec > 1000000)
5304 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5305 y.tv_usec += 1000000 * nsec;
5306 y.tv_sec -= nsec;
5309 /* Compute the time remaining to wait. tv_usec is certainly
5310 positive. */
5311 result->tv_sec = x.tv_sec - y.tv_sec;
5312 result->tv_usec = x.tv_usec - y.tv_usec;
5314 /* Return indication of whether the result should be considered
5315 negative. */
5316 return x.tv_sec < y.tv_sec;
5319 void
5320 XTflash (f)
5321 struct frame *f;
5323 BLOCK_INPUT;
5326 GC gc;
5328 /* Create a GC that will use the GXxor function to flip foreground
5329 pixels into background pixels. */
5331 XGCValues values;
5333 values.function = GXxor;
5334 values.foreground = (f->output_data.x->foreground_pixel
5335 ^ f->output_data.x->background_pixel);
5337 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5338 GCFunction | GCForeground, &values);
5342 /* Get the height not including a menu bar widget. */
5343 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5344 /* Height of each line to flash. */
5345 int flash_height = FRAME_LINE_HEIGHT (f);
5346 /* These will be the left and right margins of the rectangles. */
5347 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5348 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5350 int width;
5352 /* Don't flash the area between a scroll bar and the frame
5353 edge it is next to. */
5354 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5356 case vertical_scroll_bar_left:
5357 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5358 break;
5360 case vertical_scroll_bar_right:
5361 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5362 break;
5364 default:
5365 break;
5368 width = flash_right - flash_left;
5370 /* If window is tall, flash top and bottom line. */
5371 if (height > 3 * FRAME_LINE_HEIGHT (f))
5373 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5374 flash_left,
5375 (FRAME_INTERNAL_BORDER_WIDTH (f)
5376 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5377 width, flash_height);
5378 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5379 flash_left,
5380 (height - flash_height
5381 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5382 width, flash_height);
5384 else
5385 /* If it is short, flash it all. */
5386 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5387 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5388 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5390 x_flush (f);
5393 struct timeval wakeup;
5395 EMACS_GET_TIME (wakeup);
5397 /* Compute time to wait until, propagating carry from usecs. */
5398 wakeup.tv_usec += 150000;
5399 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5400 wakeup.tv_usec %= 1000000;
5402 /* Keep waiting until past the time wakeup. */
5403 while (1)
5405 struct timeval timeout;
5407 EMACS_GET_TIME (timeout);
5409 /* In effect, timeout = wakeup - timeout.
5410 Break if result would be negative. */
5411 if (timeval_subtract (&timeout, wakeup, timeout))
5412 break;
5414 /* Try to wait that long--but we might wake up sooner. */
5415 select (0, NULL, NULL, NULL, &timeout);
5419 /* If window is tall, flash top and bottom line. */
5420 if (height > 3 * FRAME_LINE_HEIGHT (f))
5422 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5423 flash_left,
5424 (FRAME_INTERNAL_BORDER_WIDTH (f)
5425 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5426 width, flash_height);
5427 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5428 flash_left,
5429 (height - flash_height
5430 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5431 width, flash_height);
5433 else
5434 /* If it is short, flash it all. */
5435 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5436 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5437 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5439 XFreeGC (FRAME_X_DISPLAY (f), gc);
5440 x_flush (f);
5444 UNBLOCK_INPUT;
5447 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5450 /* Make audible bell. */
5452 void
5453 XTring_bell ()
5455 struct frame *f = SELECTED_FRAME ();
5457 if (FRAME_X_DISPLAY (f))
5459 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5460 if (visible_bell)
5461 XTflash (f);
5462 else
5463 #endif
5465 BLOCK_INPUT;
5466 XBell (FRAME_X_DISPLAY (f), 0);
5467 XFlush (FRAME_X_DISPLAY (f));
5468 UNBLOCK_INPUT;
5474 /* Specify how many text lines, from the top of the window,
5475 should be affected by insert-lines and delete-lines operations.
5476 This, and those operations, are used only within an update
5477 that is bounded by calls to x_update_begin and x_update_end. */
5479 static void
5480 XTset_terminal_window (n)
5481 register int n;
5483 /* This function intentionally left blank. */
5488 /***********************************************************************
5489 Line Dance
5490 ***********************************************************************/
5492 /* Perform an insert-lines or delete-lines operation, inserting N
5493 lines or deleting -N lines at vertical position VPOS. */
5495 static void
5496 x_ins_del_lines (vpos, n)
5497 int vpos, n;
5499 abort ();
5503 /* Scroll part of the display as described by RUN. */
5505 static void
5506 x_scroll_run (w, run)
5507 struct window *w;
5508 struct run *run;
5510 struct frame *f = XFRAME (w->frame);
5511 int x, y, width, height, from_y, to_y, bottom_y;
5513 /* Get frame-relative bounding box of the text display area of W,
5514 without mode lines. Include in this box the flags areas to the
5515 left and right of W. */
5516 window_box (w, -1, &x, &y, &width, &height);
5517 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5518 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5520 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5521 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5522 bottom_y = y + height;
5524 if (to_y < from_y)
5526 /* Scrolling up. Make sure we don't copy part of the mode
5527 line at the bottom. */
5528 if (from_y + run->height > bottom_y)
5529 height = bottom_y - from_y;
5530 else
5531 height = run->height;
5533 else
5535 /* Scolling down. Make sure we don't copy over the mode line.
5536 at the bottom. */
5537 if (to_y + run->height > bottom_y)
5538 height = bottom_y - to_y;
5539 else
5540 height = run->height;
5543 BLOCK_INPUT;
5545 /* Cursor off. Will be switched on again in x_update_window_end. */
5546 updated_window = w;
5547 x_clear_cursor (w);
5549 XCopyArea (FRAME_X_DISPLAY (f),
5550 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5551 f->output_data.x->normal_gc,
5552 x, from_y,
5553 width, height,
5554 x, to_y);
5556 UNBLOCK_INPUT;
5561 /***********************************************************************
5562 Exposure Events
5563 ***********************************************************************/
5565 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5566 corner of the exposed rectangle. W and H are width and height of
5567 the exposed area. All are pixel values. W or H zero means redraw
5568 the entire frame. */
5570 static void
5571 expose_frame (f, x, y, w, h)
5572 struct frame *f;
5573 int x, y, w, h;
5575 XRectangle r;
5577 TRACE ((stderr, "expose_frame "));
5579 /* No need to redraw if frame will be redrawn soon. */
5580 if (FRAME_GARBAGED_P (f))
5582 TRACE ((stderr, " garbaged\n"));
5583 return;
5586 /* If basic faces haven't been realized yet, there is no point in
5587 trying to redraw anything. This can happen when we get an expose
5588 event while Emacs is starting, e.g. by moving another window. */
5589 if (FRAME_FACE_CACHE (f) == NULL
5590 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5592 TRACE ((stderr, " no faces\n"));
5593 return;
5596 if (w == 0 || h == 0)
5598 r.x = r.y = 0;
5599 r.width = CANON_X_UNIT (f) * f->width;
5600 r.height = CANON_Y_UNIT (f) * f->height;
5602 else
5604 r.x = x;
5605 r.y = y;
5606 r.width = w;
5607 r.height = h;
5610 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5611 expose_window_tree (XWINDOW (f->root_window), &r);
5613 if (WINDOWP (f->tool_bar_window))
5615 struct window *w = XWINDOW (f->tool_bar_window);
5616 XRectangle window_rect;
5617 XRectangle intersection_rect;
5618 int window_x, window_y, window_width, window_height;
5621 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5622 window_rect.x = window_x;
5623 window_rect.y = window_y;
5624 window_rect.width = window_width;
5625 window_rect.height = window_height;
5627 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5628 expose_window (w, &intersection_rect);
5631 #ifndef USE_X_TOOLKIT
5632 if (WINDOWP (f->menu_bar_window))
5634 struct window *w = XWINDOW (f->menu_bar_window);
5635 XRectangle window_rect;
5636 XRectangle intersection_rect;
5637 int window_x, window_y, window_width, window_height;
5640 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5641 window_rect.x = window_x;
5642 window_rect.y = window_y;
5643 window_rect.width = window_width;
5644 window_rect.height = window_height;
5646 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5647 expose_window (w, &intersection_rect);
5649 #endif /* not USE_X_TOOLKIT */
5653 /* Redraw (parts) of all windows in the window tree rooted at W that
5654 intersect R. R contains frame pixel coordinates. */
5656 static void
5657 expose_window_tree (w, r)
5658 struct window *w;
5659 XRectangle *r;
5661 while (w)
5663 if (!NILP (w->hchild))
5664 expose_window_tree (XWINDOW (w->hchild), r);
5665 else if (!NILP (w->vchild))
5666 expose_window_tree (XWINDOW (w->vchild), r);
5667 else
5669 XRectangle window_rect;
5670 XRectangle intersection_rect;
5671 struct frame *f = XFRAME (w->frame);
5672 int window_x, window_y, window_width, window_height;
5674 /* Frame-relative pixel rectangle of W. */
5675 window_box (w, -1, &window_x, &window_y, &window_width,
5676 &window_height);
5677 window_rect.x
5678 = (window_x
5679 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5680 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5681 window_rect.y = window_y;
5682 window_rect.width
5683 = (window_width
5684 + FRAME_X_FLAGS_AREA_WIDTH (f)
5685 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5686 window_rect.height
5687 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5689 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5690 expose_window (w, &intersection_rect);
5693 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5698 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5699 which intersects rectangle R. R is in window-relative coordinates. */
5701 static void
5702 expose_area (w, row, r, area)
5703 struct window *w;
5704 struct glyph_row *row;
5705 XRectangle *r;
5706 enum glyph_row_area area;
5708 int x;
5709 struct glyph *first = row->glyphs[area];
5710 struct glyph *end = row->glyphs[area] + row->used[area];
5711 struct glyph *last;
5712 int first_x;
5714 /* Set x to the window-relative start position for drawing glyphs of
5715 AREA. The first glyph of the text area can be partially visible.
5716 The first glyphs of other areas cannot. */
5717 if (area == LEFT_MARGIN_AREA)
5718 x = 0;
5719 else if (area == TEXT_AREA)
5720 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5721 else
5722 x = (window_box_width (w, LEFT_MARGIN_AREA)
5723 + window_box_width (w, TEXT_AREA));
5725 if (area == TEXT_AREA && row->fill_line_p)
5726 /* If row extends face to end of line write the whole line. */
5727 x_draw_glyphs (w, x, row, area,
5728 0, row->used[area],
5729 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5730 NULL, NULL, 0);
5731 else
5733 /* Find the first glyph that must be redrawn. */
5734 while (first < end
5735 && x + first->pixel_width < r->x)
5737 x += first->pixel_width;
5738 ++first;
5741 /* Find the last one. */
5742 last = first;
5743 first_x = x;
5744 while (last < end
5745 && x < r->x + r->width)
5747 x += last->pixel_width;
5748 ++last;
5751 /* Repaint. */
5752 if (last > first)
5753 x_draw_glyphs (w, first_x, row, area,
5754 first - row->glyphs[area],
5755 last - row->glyphs[area],
5756 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5757 NULL, NULL, 0);
5762 /* Redraw the parts of the glyph row ROW on window W intersecting
5763 rectangle R. R is in window-relative coordinates. */
5765 static void
5766 expose_line (w, row, r)
5767 struct window *w;
5768 struct glyph_row *row;
5769 XRectangle *r;
5771 xassert (row->enabled_p);
5773 if (row->mode_line_p || w->pseudo_window_p)
5774 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5775 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5776 NULL, NULL, 0);
5777 else
5779 if (row->used[LEFT_MARGIN_AREA])
5780 expose_area (w, row, r, LEFT_MARGIN_AREA);
5781 if (row->used[TEXT_AREA])
5782 expose_area (w, row, r, TEXT_AREA);
5783 if (row->used[RIGHT_MARGIN_AREA])
5784 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5785 x_draw_row_bitmaps (w, row);
5790 /* Return non-zero if W's cursor intersects rectangle R. */
5792 static int
5793 x_phys_cursor_in_rect_p (w, r)
5794 struct window *w;
5795 XRectangle *r;
5797 XRectangle cr, result;
5798 struct glyph *cursor_glyph;
5800 cursor_glyph = get_phys_cursor_glyph (w);
5801 if (cursor_glyph)
5803 cr.x = w->phys_cursor.x;
5804 cr.y = w->phys_cursor.y;
5805 cr.width = cursor_glyph->pixel_width;
5806 cr.height = w->phys_cursor_height;
5807 return x_intersect_rectangles (&cr, r, &result);
5809 else
5810 return 0;
5814 /* Redraw a rectangle of window W. R is a rectangle in window
5815 relative coordinates. Call this function with input blocked. */
5817 static void
5818 expose_window (w, r)
5819 struct window *w;
5820 XRectangle *r;
5822 struct glyph_row *row;
5823 int y;
5824 int yb = window_text_bottom_y (w);
5825 int cursor_cleared_p;
5827 /* If window is not yet fully initialized, do nothing. This can
5828 happen when toolkit scroll bars are used and a window is split.
5829 Reconfiguring the scroll bar will generate an expose for a newly
5830 created window. */
5831 if (w->current_matrix == NULL)
5832 return;
5834 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5835 r->x, r->y, r->width, r->height));
5837 /* Convert to window coordinates. */
5838 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5839 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5841 /* Turn off the cursor. */
5842 if (!w->pseudo_window_p
5843 && x_phys_cursor_in_rect_p (w, r))
5845 x_clear_cursor (w);
5846 cursor_cleared_p = 1;
5848 else
5849 cursor_cleared_p = 0;
5851 /* Find the first row intersecting the rectangle R. */
5852 row = w->current_matrix->rows;
5853 y = 0;
5854 while (row->enabled_p
5855 && y < yb
5856 && y + row->height < r->y)
5858 y += row->height;
5859 ++row;
5862 /* Display the text in the rectangle, one text line at a time. */
5863 while (row->enabled_p
5864 && y < yb
5865 && y < r->y + r->height)
5867 expose_line (w, row, r);
5868 y += row->height;
5869 ++row;
5872 /* Display the mode line if there is one. */
5873 if (WINDOW_WANTS_MODELINE_P (w)
5874 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5875 row->enabled_p)
5876 && row->y < r->y + r->height)
5877 expose_line (w, row, r);
5879 if (!w->pseudo_window_p)
5881 /* Draw border between windows. */
5882 x_draw_vertical_border (w);
5884 /* Turn the cursor on again. */
5885 if (cursor_cleared_p)
5886 x_update_window_cursor (w, 1);
5891 /* Determine the intersection of two rectangles R1 and R2. Return
5892 the intersection in *RESULT. Value is non-zero if RESULT is not
5893 empty. */
5895 static int
5896 x_intersect_rectangles (r1, r2, result)
5897 XRectangle *r1, *r2, *result;
5899 XRectangle *left, *right;
5900 XRectangle *upper, *lower;
5901 int intersection_p = 0;
5903 /* Rearrange so that R1 is the left-most rectangle. */
5904 if (r1->x < r2->x)
5905 left = r1, right = r2;
5906 else
5907 left = r2, right = r1;
5909 /* X0 of the intersection is right.x0, if this is inside R1,
5910 otherwise there is no intersection. */
5911 if (right->x <= left->x + left->width)
5913 result->x = right->x;
5915 /* The right end of the intersection is the minimum of the
5916 the right ends of left and right. */
5917 result->width = (min (left->x + left->width, right->x + right->width)
5918 - result->x);
5920 /* Same game for Y. */
5921 if (r1->y < r2->y)
5922 upper = r1, lower = r2;
5923 else
5924 upper = r2, lower = r1;
5926 /* The upper end of the intersection is lower.y0, if this is inside
5927 of upper. Otherwise, there is no intersection. */
5928 if (lower->y <= upper->y + upper->height)
5930 result->y = lower->y;
5932 /* The lower end of the intersection is the minimum of the lower
5933 ends of upper and lower. */
5934 result->height = (min (lower->y + lower->height,
5935 upper->y + upper->height)
5936 - result->y);
5937 intersection_p = 1;
5941 return intersection_p;
5948 static void
5949 frame_highlight (f)
5950 struct frame *f;
5952 /* We used to only do this if Vx_no_window_manager was non-nil, but
5953 the ICCCM (section 4.1.6) says that the window's border pixmap
5954 and border pixel are window attributes which are "private to the
5955 client", so we can always change it to whatever we want. */
5956 BLOCK_INPUT;
5957 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5958 f->output_data.x->border_pixel);
5959 UNBLOCK_INPUT;
5960 x_update_cursor (f, 1);
5963 static void
5964 frame_unhighlight (f)
5965 struct frame *f;
5967 /* We used to only do this if Vx_no_window_manager was non-nil, but
5968 the ICCCM (section 4.1.6) says that the window's border pixmap
5969 and border pixel are window attributes which are "private to the
5970 client", so we can always change it to whatever we want. */
5971 BLOCK_INPUT;
5972 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5973 f->output_data.x->border_tile);
5974 UNBLOCK_INPUT;
5975 x_update_cursor (f, 1);
5978 /* The focus has changed. Update the frames as necessary to reflect
5979 the new situation. Note that we can't change the selected frame
5980 here, because the Lisp code we are interrupting might become confused.
5981 Each event gets marked with the frame in which it occurred, so the
5982 Lisp code can tell when the switch took place by examining the events. */
5984 static void
5985 x_new_focus_frame (dpyinfo, frame)
5986 struct x_display_info *dpyinfo;
5987 struct frame *frame;
5989 struct frame *old_focus = dpyinfo->x_focus_frame;
5991 if (frame != dpyinfo->x_focus_frame)
5993 /* Set this before calling other routines, so that they see
5994 the correct value of x_focus_frame. */
5995 dpyinfo->x_focus_frame = frame;
5997 if (old_focus && old_focus->auto_lower)
5998 x_lower_frame (old_focus);
6000 #if 0
6001 selected_frame = frame;
6002 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6003 selected_frame);
6004 Fselect_window (selected_frame->selected_window);
6005 choose_minibuf_frame ();
6006 #endif /* ! 0 */
6008 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6009 pending_autoraise_frame = dpyinfo->x_focus_frame;
6010 else
6011 pending_autoraise_frame = 0;
6014 x_frame_rehighlight (dpyinfo);
6017 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6019 void
6020 x_mouse_leave (dpyinfo)
6021 struct x_display_info *dpyinfo;
6023 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6026 /* The focus has changed, or we have redirected a frame's focus to
6027 another frame (this happens when a frame uses a surrogate
6028 mini-buffer frame). Shift the highlight as appropriate.
6030 The FRAME argument doesn't necessarily have anything to do with which
6031 frame is being highlighted or un-highlighted; we only use it to find
6032 the appropriate X display info. */
6034 static void
6035 XTframe_rehighlight (frame)
6036 struct frame *frame;
6038 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6041 static void
6042 x_frame_rehighlight (dpyinfo)
6043 struct x_display_info *dpyinfo;
6045 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6047 if (dpyinfo->x_focus_frame)
6049 dpyinfo->x_highlight_frame
6050 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6051 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6052 : dpyinfo->x_focus_frame);
6053 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6055 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6056 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6059 else
6060 dpyinfo->x_highlight_frame = 0;
6062 if (dpyinfo->x_highlight_frame != old_highlight)
6064 if (old_highlight)
6065 frame_unhighlight (old_highlight);
6066 if (dpyinfo->x_highlight_frame)
6067 frame_highlight (dpyinfo->x_highlight_frame);
6073 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6075 /* Initialize mode_switch_bit and modifier_meaning. */
6076 static void
6077 x_find_modifier_meanings (dpyinfo)
6078 struct x_display_info *dpyinfo;
6080 int min_code, max_code;
6081 KeySym *syms;
6082 int syms_per_code;
6083 XModifierKeymap *mods;
6085 dpyinfo->meta_mod_mask = 0;
6086 dpyinfo->shift_lock_mask = 0;
6087 dpyinfo->alt_mod_mask = 0;
6088 dpyinfo->super_mod_mask = 0;
6089 dpyinfo->hyper_mod_mask = 0;
6091 #ifdef HAVE_X11R4
6092 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6093 #else
6094 min_code = dpyinfo->display->min_keycode;
6095 max_code = dpyinfo->display->max_keycode;
6096 #endif
6098 syms = XGetKeyboardMapping (dpyinfo->display,
6099 min_code, max_code - min_code + 1,
6100 &syms_per_code);
6101 mods = XGetModifierMapping (dpyinfo->display);
6103 /* Scan the modifier table to see which modifier bits the Meta and
6104 Alt keysyms are on. */
6106 int row, col; /* The row and column in the modifier table. */
6108 for (row = 3; row < 8; row++)
6109 for (col = 0; col < mods->max_keypermod; col++)
6111 KeyCode code
6112 = mods->modifiermap[(row * mods->max_keypermod) + col];
6114 /* Zeroes are used for filler. Skip them. */
6115 if (code == 0)
6116 continue;
6118 /* Are any of this keycode's keysyms a meta key? */
6120 int code_col;
6122 for (code_col = 0; code_col < syms_per_code; code_col++)
6124 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6126 switch (sym)
6128 case XK_Meta_L:
6129 case XK_Meta_R:
6130 dpyinfo->meta_mod_mask |= (1 << row);
6131 break;
6133 case XK_Alt_L:
6134 case XK_Alt_R:
6135 dpyinfo->alt_mod_mask |= (1 << row);
6136 break;
6138 case XK_Hyper_L:
6139 case XK_Hyper_R:
6140 dpyinfo->hyper_mod_mask |= (1 << row);
6141 break;
6143 case XK_Super_L:
6144 case XK_Super_R:
6145 dpyinfo->super_mod_mask |= (1 << row);
6146 break;
6148 case XK_Shift_Lock:
6149 /* Ignore this if it's not on the lock modifier. */
6150 if ((1 << row) == LockMask)
6151 dpyinfo->shift_lock_mask = LockMask;
6152 break;
6159 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6160 if (! dpyinfo->meta_mod_mask)
6162 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6163 dpyinfo->alt_mod_mask = 0;
6166 /* If some keys are both alt and meta,
6167 make them just meta, not alt. */
6168 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6170 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6173 XFree ((char *) syms);
6174 XFreeModifiermap (mods);
6177 /* Convert between the modifier bits X uses and the modifier bits
6178 Emacs uses. */
6180 static unsigned int
6181 x_x_to_emacs_modifiers (dpyinfo, state)
6182 struct x_display_info *dpyinfo;
6183 unsigned int state;
6185 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6186 | ((state & ControlMask) ? ctrl_modifier : 0)
6187 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6188 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6189 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6190 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6193 static unsigned int
6194 x_emacs_to_x_modifiers (dpyinfo, state)
6195 struct x_display_info *dpyinfo;
6196 unsigned int state;
6198 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6199 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6200 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6201 | ((state & shift_modifier) ? ShiftMask : 0)
6202 | ((state & ctrl_modifier) ? ControlMask : 0)
6203 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6206 /* Convert a keysym to its name. */
6208 char *
6209 x_get_keysym_name (keysym)
6210 KeySym keysym;
6212 char *value;
6214 BLOCK_INPUT;
6215 value = XKeysymToString (keysym);
6216 UNBLOCK_INPUT;
6218 return value;
6223 /* Mouse clicks and mouse movement. Rah. */
6225 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6226 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6227 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6228 not force the value into range. */
6230 void
6231 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6232 FRAME_PTR f;
6233 register int pix_x, pix_y;
6234 register int *x, *y;
6235 XRectangle *bounds;
6236 int noclip;
6238 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6239 even for negative values. */
6240 if (pix_x < 0)
6241 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6242 if (pix_y < 0)
6243 pix_y -= (f)->output_data.x->line_height - 1;
6245 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6246 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6248 if (bounds)
6250 bounds->width = FONT_WIDTH (f->output_data.x->font);
6251 bounds->height = f->output_data.x->line_height;
6252 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6253 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6256 if (!noclip)
6258 if (pix_x < 0)
6259 pix_x = 0;
6260 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6261 pix_x = FRAME_WINDOW_WIDTH (f);
6263 if (pix_y < 0)
6264 pix_y = 0;
6265 else if (pix_y > f->height)
6266 pix_y = f->height;
6269 *x = pix_x;
6270 *y = pix_y;
6274 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6275 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6276 can't tell the positions because W's display is not up to date,
6277 return 0. */
6280 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6281 struct window *w;
6282 int hpos, vpos;
6283 int *frame_x, *frame_y;
6285 int success_p;
6287 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6288 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6290 if (display_completed)
6292 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6293 struct glyph *glyph = row->glyphs[TEXT_AREA];
6294 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6296 *frame_y = row->y;
6297 *frame_x = row->x;
6298 while (glyph < end)
6300 *frame_x += glyph->pixel_width;
6301 ++glyph;
6304 success_p = 1;
6306 else
6308 *frame_y = *frame_x = 0;
6309 success_p = 0;
6312 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6313 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6314 return success_p;
6318 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6320 If the event is a button press, then note that we have grabbed
6321 the mouse. */
6323 static Lisp_Object
6324 construct_mouse_click (result, event, f)
6325 struct input_event *result;
6326 XButtonEvent *event;
6327 struct frame *f;
6329 /* Make the event type no_event; we'll change that when we decide
6330 otherwise. */
6331 result->kind = mouse_click;
6332 result->code = event->button - Button1;
6333 result->timestamp = event->time;
6334 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6335 event->state)
6336 | (event->type == ButtonRelease
6337 ? up_modifier
6338 : down_modifier));
6340 XSETINT (result->x, event->x);
6341 XSETINT (result->y, event->y);
6342 XSETFRAME (result->frame_or_window, f);
6343 result->arg = Qnil;
6344 return Qnil;
6348 /* Function to report a mouse movement to the mainstream Emacs code.
6349 The input handler calls this.
6351 We have received a mouse movement event, which is given in *event.
6352 If the mouse is over a different glyph than it was last time, tell
6353 the mainstream emacs code by setting mouse_moved. If not, ask for
6354 another motion event, so we can check again the next time it moves. */
6356 static XMotionEvent last_mouse_motion_event;
6357 static Lisp_Object last_mouse_motion_frame;
6359 static void
6360 note_mouse_movement (frame, event)
6361 FRAME_PTR frame;
6362 XMotionEvent *event;
6364 last_mouse_movement_time = event->time;
6365 last_mouse_motion_event = *event;
6366 XSETFRAME (last_mouse_motion_frame, frame);
6368 if (event->window != FRAME_X_WINDOW (frame))
6370 frame->mouse_moved = 1;
6371 last_mouse_scroll_bar = Qnil;
6372 note_mouse_highlight (frame, -1, -1);
6375 /* Has the mouse moved off the glyph it was on at the last sighting? */
6376 else if (event->x < last_mouse_glyph.x
6377 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6378 || event->y < last_mouse_glyph.y
6379 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6381 frame->mouse_moved = 1;
6382 last_mouse_scroll_bar = Qnil;
6383 note_mouse_highlight (frame, event->x, event->y);
6387 /* This is used for debugging, to turn off note_mouse_highlight. */
6389 int disable_mouse_highlight;
6393 /************************************************************************
6394 Mouse Face
6395 ************************************************************************/
6397 /* Find the glyph under window-relative coordinates X/Y in window W.
6398 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6399 strings. Return in *HPOS and *VPOS the row and column number of
6400 the glyph found. Return in *AREA the glyph area containing X.
6401 Value is a pointer to the glyph found or null if X/Y is not on
6402 text, or we can't tell because W's current matrix is not up to
6403 date. */
6405 static struct glyph *
6406 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6407 struct window *w;
6408 int x, y;
6409 int *hpos, *vpos, *area;
6411 struct glyph *glyph, *end;
6412 struct glyph_row *row = NULL;
6413 int x0, i, left_area_width;
6415 /* Find row containing Y. Give up if some row is not enabled. */
6416 for (i = 0; i < w->current_matrix->nrows; ++i)
6418 row = MATRIX_ROW (w->current_matrix, i);
6419 if (!row->enabled_p)
6420 return NULL;
6421 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6422 break;
6425 *vpos = i;
6426 *hpos = 0;
6428 /* Give up if Y is not in the window. */
6429 if (i == w->current_matrix->nrows)
6430 return NULL;
6432 /* Get the glyph area containing X. */
6433 if (w->pseudo_window_p)
6435 *area = TEXT_AREA;
6436 x0 = 0;
6438 else
6440 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6441 if (x < left_area_width)
6443 *area = LEFT_MARGIN_AREA;
6444 x0 = 0;
6446 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6448 *area = TEXT_AREA;
6449 x0 = row->x + left_area_width;
6451 else
6453 *area = RIGHT_MARGIN_AREA;
6454 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6458 /* Find glyph containing X. */
6459 glyph = row->glyphs[*area];
6460 end = glyph + row->used[*area];
6461 while (glyph < end)
6463 if (x < x0 + glyph->pixel_width)
6465 if (w->pseudo_window_p)
6466 break;
6467 else if (BUFFERP (glyph->object))
6468 break;
6471 x0 += glyph->pixel_width;
6472 ++glyph;
6475 if (glyph == end)
6476 return NULL;
6478 *hpos = glyph - row->glyphs[*area];
6479 return glyph;
6483 /* Convert frame-relative x/y to coordinates relative to window W.
6484 Takes pseudo-windows into account. */
6486 static void
6487 frame_to_window_pixel_xy (w, x, y)
6488 struct window *w;
6489 int *x, *y;
6491 if (w->pseudo_window_p)
6493 /* A pseudo-window is always full-width, and starts at the
6494 left edge of the frame, plus a frame border. */
6495 struct frame *f = XFRAME (w->frame);
6496 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6497 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6499 else
6501 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6502 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6507 /* Take proper action when mouse has moved to the mode or top line of
6508 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6509 mode line. X is relative to the start of the text display area of
6510 W, so the width of bitmap areas and scroll bars must be subtracted
6511 to get a position relative to the start of the mode line. */
6513 static void
6514 note_mode_line_highlight (w, x, mode_line_p)
6515 struct window *w;
6516 int x, mode_line_p;
6518 struct frame *f = XFRAME (w->frame);
6519 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6520 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6521 struct glyph_row *row;
6523 if (mode_line_p)
6524 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6525 else
6526 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6528 if (row->enabled_p)
6530 struct glyph *glyph, *end;
6531 Lisp_Object help, map;
6532 int x0;
6534 /* Find the glyph under X. */
6535 glyph = row->glyphs[TEXT_AREA];
6536 end = glyph + row->used[TEXT_AREA];
6537 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6538 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6539 while (glyph < end
6540 && x >= x0 + glyph->pixel_width)
6542 x0 += glyph->pixel_width;
6543 ++glyph;
6546 if (glyph < end
6547 && STRINGP (glyph->object)
6548 && XSTRING (glyph->object)->intervals
6549 && glyph->charpos >= 0
6550 && glyph->charpos < XSTRING (glyph->object)->size)
6552 /* If we're on a string with `help-echo' text property,
6553 arrange for the help to be displayed. This is done by
6554 setting the global variable help_echo to the help string. */
6555 help = Fget_text_property (make_number (glyph->charpos),
6556 Qhelp_echo, glyph->object);
6557 if (!NILP (help))
6559 help_echo = help;
6560 XSETWINDOW (help_echo_window, w);
6561 help_echo_object = glyph->object;
6562 help_echo_pos = glyph->charpos;
6565 /* Change the mouse pointer according to what is under X/Y. */
6566 map = Fget_text_property (make_number (glyph->charpos),
6567 Qlocal_map, glyph->object);
6568 if (KEYMAPP (map))
6569 cursor = f->output_data.x->nontext_cursor;
6570 else
6572 map = Fget_text_property (make_number (glyph->charpos),
6573 Qkeymap, glyph->object);
6574 if (KEYMAPP (map))
6575 cursor = f->output_data.x->nontext_cursor;
6580 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6584 /* Take proper action when the mouse has moved to position X, Y on
6585 frame F as regards highlighting characters that have mouse-face
6586 properties. Also de-highlighting chars where the mouse was before.
6587 X and Y can be negative or out of range. */
6589 static void
6590 note_mouse_highlight (f, x, y)
6591 struct frame *f;
6592 int x, y;
6594 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6595 int portion;
6596 Lisp_Object window;
6597 struct window *w;
6599 /* When a menu is active, don't highlight because this looks odd. */
6600 #ifdef USE_X_TOOLKIT
6601 if (popup_activated ())
6602 return;
6603 #endif
6605 if (disable_mouse_highlight
6606 || !f->glyphs_initialized_p)
6607 return;
6609 dpyinfo->mouse_face_mouse_x = x;
6610 dpyinfo->mouse_face_mouse_y = y;
6611 dpyinfo->mouse_face_mouse_frame = f;
6613 if (dpyinfo->mouse_face_defer)
6614 return;
6616 if (gc_in_progress)
6618 dpyinfo->mouse_face_deferred_gc = 1;
6619 return;
6622 /* Which window is that in? */
6623 window = window_from_coordinates (f, x, y, &portion, 1);
6625 /* If we were displaying active text in another window, clear that. */
6626 if (! EQ (window, dpyinfo->mouse_face_window))
6627 clear_mouse_face (dpyinfo);
6629 /* Not on a window -> return. */
6630 if (!WINDOWP (window))
6631 return;
6633 /* Convert to window-relative pixel coordinates. */
6634 w = XWINDOW (window);
6635 frame_to_window_pixel_xy (w, &x, &y);
6637 /* Handle tool-bar window differently since it doesn't display a
6638 buffer. */
6639 if (EQ (window, f->tool_bar_window))
6641 note_tool_bar_highlight (f, x, y);
6642 return;
6645 if (portion == 1 || portion == 3)
6647 /* Mouse is on the mode or top line. */
6648 note_mode_line_highlight (w, x, portion == 1);
6649 return;
6651 else
6652 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6653 f->output_data.x->text_cursor);
6655 /* Are we in a window whose display is up to date?
6656 And verify the buffer's text has not changed. */
6657 if (/* Within text portion of the window. */
6658 portion == 0
6659 && EQ (w->window_end_valid, w->buffer)
6660 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6661 && (XFASTINT (w->last_overlay_modified)
6662 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6664 int hpos, vpos, pos, i, area;
6665 struct glyph *glyph;
6667 /* Find the glyph under X/Y. */
6668 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6670 /* Clear mouse face if X/Y not over text. */
6671 if (glyph == NULL
6672 || area != TEXT_AREA
6673 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6675 clear_mouse_face (dpyinfo);
6676 return;
6679 pos = glyph->charpos;
6680 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6682 /* Check for mouse-face and help-echo. */
6684 Lisp_Object mouse_face, overlay, position;
6685 Lisp_Object *overlay_vec;
6686 int len, noverlays;
6687 struct buffer *obuf;
6688 int obegv, ozv;
6690 /* If we get an out-of-range value, return now; avoid an error. */
6691 if (pos > BUF_Z (XBUFFER (w->buffer)))
6692 return;
6694 /* Make the window's buffer temporarily current for
6695 overlays_at and compute_char_face. */
6696 obuf = current_buffer;
6697 current_buffer = XBUFFER (w->buffer);
6698 obegv = BEGV;
6699 ozv = ZV;
6700 BEGV = BEG;
6701 ZV = Z;
6703 /* Is this char mouse-active or does it have help-echo? */
6704 XSETINT (position, pos);
6706 /* Put all the overlays we want in a vector in overlay_vec.
6707 Store the length in len. If there are more than 10, make
6708 enough space for all, and try again. */
6709 len = 10;
6710 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6711 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6712 if (noverlays > len)
6714 len = noverlays;
6715 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6716 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6719 /* Sort overlays into increasing priority order. */
6720 noverlays = sort_overlays (overlay_vec, noverlays, w);
6722 /* Check mouse-face highlighting. */
6723 if (! (EQ (window, dpyinfo->mouse_face_window)
6724 && vpos >= dpyinfo->mouse_face_beg_row
6725 && vpos <= dpyinfo->mouse_face_end_row
6726 && (vpos > dpyinfo->mouse_face_beg_row
6727 || hpos >= dpyinfo->mouse_face_beg_col)
6728 && (vpos < dpyinfo->mouse_face_end_row
6729 || hpos < dpyinfo->mouse_face_end_col
6730 || dpyinfo->mouse_face_past_end)))
6732 /* Clear the display of the old active region, if any. */
6733 clear_mouse_face (dpyinfo);
6735 /* Find the highest priority overlay that has a mouse-face prop. */
6736 overlay = Qnil;
6737 for (i = noverlays - 1; i >= 0; --i)
6739 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6740 if (!NILP (mouse_face))
6742 overlay = overlay_vec[i];
6743 break;
6747 /* If no overlay applies, get a text property. */
6748 if (NILP (overlay))
6749 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6751 /* Handle the overlay case. */
6752 if (! NILP (overlay))
6754 /* Find the range of text around this char that
6755 should be active. */
6756 Lisp_Object before, after;
6757 int ignore;
6759 before = Foverlay_start (overlay);
6760 after = Foverlay_end (overlay);
6761 /* Record this as the current active region. */
6762 fast_find_position (w, XFASTINT (before),
6763 &dpyinfo->mouse_face_beg_col,
6764 &dpyinfo->mouse_face_beg_row,
6765 &dpyinfo->mouse_face_beg_x,
6766 &dpyinfo->mouse_face_beg_y);
6767 dpyinfo->mouse_face_past_end
6768 = !fast_find_position (w, XFASTINT (after),
6769 &dpyinfo->mouse_face_end_col,
6770 &dpyinfo->mouse_face_end_row,
6771 &dpyinfo->mouse_face_end_x,
6772 &dpyinfo->mouse_face_end_y);
6773 dpyinfo->mouse_face_window = window;
6774 dpyinfo->mouse_face_face_id
6775 = face_at_buffer_position (w, pos, 0, 0,
6776 &ignore, pos + 1, 1);
6778 /* Display it as active. */
6779 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6781 /* Handle the text property case. */
6782 else if (! NILP (mouse_face))
6784 /* Find the range of text around this char that
6785 should be active. */
6786 Lisp_Object before, after, beginning, end;
6787 int ignore;
6789 beginning = Fmarker_position (w->start);
6790 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6791 - XFASTINT (w->window_end_pos)));
6792 before
6793 = Fprevious_single_property_change (make_number (pos + 1),
6794 Qmouse_face,
6795 w->buffer, beginning);
6796 after
6797 = Fnext_single_property_change (position, Qmouse_face,
6798 w->buffer, end);
6799 /* Record this as the current active region. */
6800 fast_find_position (w, XFASTINT (before),
6801 &dpyinfo->mouse_face_beg_col,
6802 &dpyinfo->mouse_face_beg_row,
6803 &dpyinfo->mouse_face_beg_x,
6804 &dpyinfo->mouse_face_beg_y);
6805 dpyinfo->mouse_face_past_end
6806 = !fast_find_position (w, XFASTINT (after),
6807 &dpyinfo->mouse_face_end_col,
6808 &dpyinfo->mouse_face_end_row,
6809 &dpyinfo->mouse_face_end_x,
6810 &dpyinfo->mouse_face_end_y);
6811 dpyinfo->mouse_face_window = window;
6812 dpyinfo->mouse_face_face_id
6813 = face_at_buffer_position (w, pos, 0, 0,
6814 &ignore, pos + 1, 1);
6816 /* Display it as active. */
6817 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6821 /* Look for a `help-echo' property. */
6823 Lisp_Object help, overlay;
6825 /* Check overlays first. */
6826 help = overlay = Qnil;
6827 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6829 overlay = overlay_vec[i];
6830 help = Foverlay_get (overlay, Qhelp_echo);
6833 if (!NILP (help))
6835 help_echo = help;
6836 help_echo_window = window;
6837 help_echo_object = overlay;
6838 help_echo_pos = pos;
6840 else
6842 /* Try text properties. */
6843 if ((STRINGP (glyph->object)
6844 && glyph->charpos >= 0
6845 && glyph->charpos < XSTRING (glyph->object)->size)
6846 || (BUFFERP (glyph->object)
6847 && glyph->charpos >= BEGV
6848 && glyph->charpos < ZV))
6849 help = Fget_text_property (make_number (glyph->charpos),
6850 Qhelp_echo, glyph->object);
6852 if (!NILP (help))
6854 help_echo = help;
6855 help_echo_window = window;
6856 help_echo_object = glyph->object;
6857 help_echo_pos = glyph->charpos;
6862 BEGV = obegv;
6863 ZV = ozv;
6864 current_buffer = obuf;
6869 static void
6870 redo_mouse_highlight ()
6872 if (!NILP (last_mouse_motion_frame)
6873 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6874 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6875 last_mouse_motion_event.x,
6876 last_mouse_motion_event.y);
6881 /***********************************************************************
6882 Tool-bars
6883 ***********************************************************************/
6885 static int x_tool_bar_item P_ ((struct frame *, int, int,
6886 struct glyph **, int *, int *, int *));
6888 /* Tool-bar item index of the item on which a mouse button was pressed
6889 or -1. */
6891 static int last_tool_bar_item;
6894 /* Get information about the tool-bar item at position X/Y on frame F.
6895 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6896 the current matrix of the tool-bar window of F, or NULL if not
6897 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6898 item in F->current_tool_bar_items. Value is
6900 -1 if X/Y is not on a tool-bar item
6901 0 if X/Y is on the same item that was highlighted before.
6902 1 otherwise. */
6904 static int
6905 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6906 struct frame *f;
6907 int x, y;
6908 struct glyph **glyph;
6909 int *hpos, *vpos, *prop_idx;
6911 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6912 struct window *w = XWINDOW (f->tool_bar_window);
6913 int area;
6915 /* Find the glyph under X/Y. */
6916 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6917 if (*glyph == NULL)
6918 return -1;
6920 /* Get the start of this tool-bar item's properties in
6921 f->current_tool_bar_items. */
6922 if (!tool_bar_item_info (f, *glyph, prop_idx))
6923 return -1;
6925 /* Is mouse on the highlighted item? */
6926 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6927 && *vpos >= dpyinfo->mouse_face_beg_row
6928 && *vpos <= dpyinfo->mouse_face_end_row
6929 && (*vpos > dpyinfo->mouse_face_beg_row
6930 || *hpos >= dpyinfo->mouse_face_beg_col)
6931 && (*vpos < dpyinfo->mouse_face_end_row
6932 || *hpos < dpyinfo->mouse_face_end_col
6933 || dpyinfo->mouse_face_past_end))
6934 return 0;
6936 return 1;
6940 /* Handle mouse button event on the tool-bar of frame F, at
6941 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6942 or ButtonRelase. */
6944 static void
6945 x_handle_tool_bar_click (f, button_event)
6946 struct frame *f;
6947 XButtonEvent *button_event;
6949 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6950 struct window *w = XWINDOW (f->tool_bar_window);
6951 int hpos, vpos, prop_idx;
6952 struct glyph *glyph;
6953 Lisp_Object enabled_p;
6954 int x = button_event->x;
6955 int y = button_event->y;
6957 /* If not on the highlighted tool-bar item, return. */
6958 frame_to_window_pixel_xy (w, &x, &y);
6959 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6960 return;
6962 /* If item is disabled, do nothing. */
6963 enabled_p = (XVECTOR (f->current_tool_bar_items)
6964 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6965 if (NILP (enabled_p))
6966 return;
6968 if (button_event->type == ButtonPress)
6970 /* Show item in pressed state. */
6971 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6972 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6973 last_tool_bar_item = prop_idx;
6975 else
6977 Lisp_Object key, frame;
6978 struct input_event event;
6980 /* Show item in released state. */
6981 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6982 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6984 key = (XVECTOR (f->current_tool_bar_items)
6985 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6987 XSETFRAME (frame, f);
6988 event.kind = TOOL_BAR_EVENT;
6989 event.frame_or_window = frame;
6990 event.arg = frame;
6991 kbd_buffer_store_event (&event);
6993 event.kind = TOOL_BAR_EVENT;
6994 event.frame_or_window = frame;
6995 event.arg = key;
6996 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6997 button_event->state);
6998 kbd_buffer_store_event (&event);
6999 last_tool_bar_item = -1;
7004 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7005 tool-bar window-relative coordinates X/Y. Called from
7006 note_mouse_highlight. */
7008 static void
7009 note_tool_bar_highlight (f, x, y)
7010 struct frame *f;
7011 int x, y;
7013 Lisp_Object window = f->tool_bar_window;
7014 struct window *w = XWINDOW (window);
7015 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7016 int hpos, vpos;
7017 struct glyph *glyph;
7018 struct glyph_row *row;
7019 int i;
7020 Lisp_Object enabled_p;
7021 int prop_idx;
7022 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7023 int mouse_down_p, rc;
7025 /* Function note_mouse_highlight is called with negative x(y
7026 values when mouse moves outside of the frame. */
7027 if (x <= 0 || y <= 0)
7029 clear_mouse_face (dpyinfo);
7030 return;
7033 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7034 if (rc < 0)
7036 /* Not on tool-bar item. */
7037 clear_mouse_face (dpyinfo);
7038 return;
7040 else if (rc == 0)
7041 /* On same tool-bar item as before. */
7042 goto set_help_echo;
7044 clear_mouse_face (dpyinfo);
7046 /* Mouse is down, but on different tool-bar item? */
7047 mouse_down_p = (dpyinfo->grabbed
7048 && f == last_mouse_frame
7049 && FRAME_LIVE_P (f));
7050 if (mouse_down_p
7051 && last_tool_bar_item != prop_idx)
7052 return;
7054 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7055 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7057 /* If tool-bar item is not enabled, don't highlight it. */
7058 enabled_p = (XVECTOR (f->current_tool_bar_items)
7059 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
7060 if (!NILP (enabled_p))
7062 /* Compute the x-position of the glyph. In front and past the
7063 image is a space. We include this is the highlighted area. */
7064 row = MATRIX_ROW (w->current_matrix, vpos);
7065 for (i = x = 0; i < hpos; ++i)
7066 x += row->glyphs[TEXT_AREA][i].pixel_width;
7068 /* Record this as the current active region. */
7069 dpyinfo->mouse_face_beg_col = hpos;
7070 dpyinfo->mouse_face_beg_row = vpos;
7071 dpyinfo->mouse_face_beg_x = x;
7072 dpyinfo->mouse_face_beg_y = row->y;
7073 dpyinfo->mouse_face_past_end = 0;
7075 dpyinfo->mouse_face_end_col = hpos + 1;
7076 dpyinfo->mouse_face_end_row = vpos;
7077 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7078 dpyinfo->mouse_face_end_y = row->y;
7079 dpyinfo->mouse_face_window = window;
7080 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7082 /* Display it as active. */
7083 show_mouse_face (dpyinfo, draw);
7084 dpyinfo->mouse_face_image_state = draw;
7087 set_help_echo:
7089 /* Set help_echo to a help string.to display for this tool-bar item.
7090 XTread_socket does the rest. */
7091 help_echo_object = help_echo_window = Qnil;
7092 help_echo_pos = -1;
7093 help_echo = (XVECTOR (f->current_tool_bar_items)
7094 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
7095 if (NILP (help_echo))
7096 help_echo = (XVECTOR (f->current_tool_bar_items)
7097 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
7102 /* Find the glyph matrix position of buffer position POS in window W.
7103 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7104 current glyphs must be up to date. If POS is above window start
7105 return (0, 0, 0, 0). If POS is after end of W, return end of
7106 last line in W. */
7108 static int
7109 fast_find_position (w, pos, hpos, vpos, x, y)
7110 struct window *w;
7111 int pos;
7112 int *hpos, *vpos, *x, *y;
7114 int i;
7115 int lastcol;
7116 int maybe_next_line_p = 0;
7117 int line_start_position;
7118 int yb = window_text_bottom_y (w);
7119 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7120 struct glyph_row *best_row = row;
7121 int row_vpos = 0, best_row_vpos = 0;
7122 int current_x;
7124 while (row->y < yb)
7126 if (row->used[TEXT_AREA])
7127 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7128 else
7129 line_start_position = 0;
7131 if (line_start_position > pos)
7132 break;
7133 /* If the position sought is the end of the buffer,
7134 don't include the blank lines at the bottom of the window. */
7135 else if (line_start_position == pos
7136 && pos == BUF_ZV (XBUFFER (w->buffer)))
7138 maybe_next_line_p = 1;
7139 break;
7141 else if (line_start_position > 0)
7143 best_row = row;
7144 best_row_vpos = row_vpos;
7147 if (row->y + row->height >= yb)
7148 break;
7150 ++row;
7151 ++row_vpos;
7154 /* Find the right column within BEST_ROW. */
7155 lastcol = 0;
7156 current_x = best_row->x;
7157 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7159 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7160 int charpos;
7162 charpos = glyph->charpos;
7163 if (charpos == pos)
7165 *hpos = i;
7166 *vpos = best_row_vpos;
7167 *x = current_x;
7168 *y = best_row->y;
7169 return 1;
7171 else if (charpos > pos)
7172 break;
7173 else if (charpos > 0)
7174 lastcol = i;
7176 current_x += glyph->pixel_width;
7179 /* If we're looking for the end of the buffer,
7180 and we didn't find it in the line we scanned,
7181 use the start of the following line. */
7182 if (maybe_next_line_p)
7184 ++best_row;
7185 ++best_row_vpos;
7186 lastcol = 0;
7187 current_x = best_row->x;
7190 *vpos = best_row_vpos;
7191 *hpos = lastcol + 1;
7192 *x = current_x;
7193 *y = best_row->y;
7194 return 0;
7198 /* Display the active region described by mouse_face_*
7199 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7201 static void
7202 show_mouse_face (dpyinfo, draw)
7203 struct x_display_info *dpyinfo;
7204 enum draw_glyphs_face draw;
7206 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7207 struct frame *f = XFRAME (WINDOW_FRAME (w));
7208 int i;
7209 int cursor_off_p = 0;
7210 struct cursor_pos saved_cursor;
7212 saved_cursor = output_cursor;
7214 /* If window is in the process of being destroyed, don't bother
7215 to do anything. */
7216 if (w->current_matrix == NULL)
7217 goto set_x_cursor;
7219 /* Recognize when we are called to operate on rows that don't exist
7220 anymore. This can happen when a window is split. */
7221 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7222 goto set_x_cursor;
7224 set_output_cursor (&w->phys_cursor);
7226 /* Note that mouse_face_beg_row etc. are window relative. */
7227 for (i = dpyinfo->mouse_face_beg_row;
7228 i <= dpyinfo->mouse_face_end_row;
7229 i++)
7231 int start_hpos, end_hpos, start_x;
7232 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7234 /* Don't do anything if row doesn't have valid contents. */
7235 if (!row->enabled_p)
7236 continue;
7238 /* For all but the first row, the highlight starts at column 0. */
7239 if (i == dpyinfo->mouse_face_beg_row)
7241 start_hpos = dpyinfo->mouse_face_beg_col;
7242 start_x = dpyinfo->mouse_face_beg_x;
7244 else
7246 start_hpos = 0;
7247 start_x = 0;
7250 if (i == dpyinfo->mouse_face_end_row)
7251 end_hpos = dpyinfo->mouse_face_end_col;
7252 else
7253 end_hpos = row->used[TEXT_AREA];
7255 /* If the cursor's in the text we are about to rewrite, turn the
7256 cursor off. */
7257 if (!w->pseudo_window_p
7258 && i == output_cursor.vpos
7259 && output_cursor.hpos >= start_hpos - 1
7260 && output_cursor.hpos <= end_hpos)
7262 x_update_window_cursor (w, 0);
7263 cursor_off_p = 1;
7266 if (end_hpos > start_hpos)
7268 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7269 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7270 start_hpos, end_hpos, draw, NULL, NULL, 0);
7274 /* If we turned the cursor off, turn it back on. */
7275 if (cursor_off_p)
7276 x_display_cursor (w, 1,
7277 output_cursor.hpos, output_cursor.vpos,
7278 output_cursor.x, output_cursor.y);
7280 output_cursor = saved_cursor;
7282 set_x_cursor:
7284 /* Change the mouse cursor. */
7285 if (draw == DRAW_NORMAL_TEXT)
7286 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7287 f->output_data.x->text_cursor);
7288 else if (draw == DRAW_MOUSE_FACE)
7289 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7290 f->output_data.x->cross_cursor);
7291 else
7292 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7293 f->output_data.x->nontext_cursor);
7296 /* Clear out the mouse-highlighted active region.
7297 Redraw it un-highlighted first. */
7299 void
7300 clear_mouse_face (dpyinfo)
7301 struct x_display_info *dpyinfo;
7303 if (tip_frame)
7304 return;
7306 if (! NILP (dpyinfo->mouse_face_window))
7307 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7309 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7310 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7311 dpyinfo->mouse_face_window = Qnil;
7315 /* Clear any mouse-face on window W. This function is part of the
7316 redisplay interface, and is called from try_window_id and similar
7317 functions to ensure the mouse-highlight is off. */
7319 static void
7320 x_clear_mouse_face (w)
7321 struct window *w;
7323 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7324 Lisp_Object window;
7326 BLOCK_INPUT;
7327 XSETWINDOW (window, w);
7328 if (EQ (window, dpyinfo->mouse_face_window))
7329 clear_mouse_face (dpyinfo);
7330 UNBLOCK_INPUT;
7334 /* Just discard the mouse face information for frame F, if any.
7335 This is used when the size of F is changed. */
7337 void
7338 cancel_mouse_face (f)
7339 FRAME_PTR f;
7341 Lisp_Object window;
7342 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7344 window = dpyinfo->mouse_face_window;
7345 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7347 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7348 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7349 dpyinfo->mouse_face_window = Qnil;
7353 static struct scroll_bar *x_window_to_scroll_bar ();
7354 static void x_scroll_bar_report_motion ();
7356 /* Return the current position of the mouse.
7357 *fp should be a frame which indicates which display to ask about.
7359 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7360 and *part to the frame, window, and scroll bar part that the mouse
7361 is over. Set *x and *y to the portion and whole of the mouse's
7362 position on the scroll bar.
7364 If the mouse movement started elsewhere, set *fp to the frame the
7365 mouse is on, *bar_window to nil, and *x and *y to the character cell
7366 the mouse is over.
7368 Set *time to the server time-stamp for the time at which the mouse
7369 was at this position.
7371 Don't store anything if we don't have a valid set of values to report.
7373 This clears the mouse_moved flag, so we can wait for the next mouse
7374 movement. */
7376 static void
7377 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7378 FRAME_PTR *fp;
7379 int insist;
7380 Lisp_Object *bar_window;
7381 enum scroll_bar_part *part;
7382 Lisp_Object *x, *y;
7383 unsigned long *time;
7385 FRAME_PTR f1;
7387 BLOCK_INPUT;
7389 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7390 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7391 else
7393 Window root;
7394 int root_x, root_y;
7396 Window dummy_window;
7397 int dummy;
7399 Lisp_Object frame, tail;
7401 /* Clear the mouse-moved flag for every frame on this display. */
7402 FOR_EACH_FRAME (tail, frame)
7403 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7404 XFRAME (frame)->mouse_moved = 0;
7406 last_mouse_scroll_bar = Qnil;
7408 /* Figure out which root window we're on. */
7409 XQueryPointer (FRAME_X_DISPLAY (*fp),
7410 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7412 /* The root window which contains the pointer. */
7413 &root,
7415 /* Trash which we can't trust if the pointer is on
7416 a different screen. */
7417 &dummy_window,
7419 /* The position on that root window. */
7420 &root_x, &root_y,
7422 /* More trash we can't trust. */
7423 &dummy, &dummy,
7425 /* Modifier keys and pointer buttons, about which
7426 we don't care. */
7427 (unsigned int *) &dummy);
7429 /* Now we have a position on the root; find the innermost window
7430 containing the pointer. */
7432 Window win, child;
7433 int win_x, win_y;
7434 int parent_x = 0, parent_y = 0;
7435 int count;
7437 win = root;
7439 /* XTranslateCoordinates can get errors if the window
7440 structure is changing at the same time this function
7441 is running. So at least we must not crash from them. */
7443 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7445 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7446 && FRAME_LIVE_P (last_mouse_frame))
7448 /* If mouse was grabbed on a frame, give coords for that frame
7449 even if the mouse is now outside it. */
7450 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7452 /* From-window, to-window. */
7453 root, FRAME_X_WINDOW (last_mouse_frame),
7455 /* From-position, to-position. */
7456 root_x, root_y, &win_x, &win_y,
7458 /* Child of win. */
7459 &child);
7460 f1 = last_mouse_frame;
7462 else
7464 while (1)
7466 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7468 /* From-window, to-window. */
7469 root, win,
7471 /* From-position, to-position. */
7472 root_x, root_y, &win_x, &win_y,
7474 /* Child of win. */
7475 &child);
7477 if (child == None || child == win)
7478 break;
7480 win = child;
7481 parent_x = win_x;
7482 parent_y = win_y;
7485 /* Now we know that:
7486 win is the innermost window containing the pointer
7487 (XTC says it has no child containing the pointer),
7488 win_x and win_y are the pointer's position in it
7489 (XTC did this the last time through), and
7490 parent_x and parent_y are the pointer's position in win's parent.
7491 (They are what win_x and win_y were when win was child.
7492 If win is the root window, it has no parent, and
7493 parent_{x,y} are invalid, but that's okay, because we'll
7494 never use them in that case.) */
7496 /* Is win one of our frames? */
7497 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7500 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7501 f1 = 0;
7503 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7505 /* If not, is it one of our scroll bars? */
7506 if (! f1)
7508 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7510 if (bar)
7512 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7513 win_x = parent_x;
7514 win_y = parent_y;
7518 if (f1 == 0 && insist > 0)
7519 f1 = SELECTED_FRAME ();
7521 if (f1)
7523 /* Ok, we found a frame. Store all the values.
7524 last_mouse_glyph is a rectangle used to reduce the
7525 generation of mouse events. To not miss any motion
7526 events, we must divide the frame into rectangles of the
7527 size of the smallest character that could be displayed
7528 on it, i.e. into the same rectangles that matrices on
7529 the frame are divided into. */
7531 #if OLD_REDISPLAY_CODE
7532 int ignore1, ignore2;
7533 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7534 &last_mouse_glyph,
7535 FRAME_X_DISPLAY_INFO (f1)->grabbed
7536 || insist);
7537 #else
7539 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7540 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7541 int x = win_x;
7542 int y = win_y;
7544 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7545 round down even for negative values. */
7546 if (x < 0)
7547 x -= width - 1;
7548 if (y < 0)
7549 y -= height - 1;
7551 last_mouse_glyph.width = width;
7552 last_mouse_glyph.height = height;
7553 last_mouse_glyph.x = (x + width - 1) / width * width;
7554 last_mouse_glyph.y = (y + height - 1) / height * height;
7556 #endif
7558 *bar_window = Qnil;
7559 *part = 0;
7560 *fp = f1;
7561 XSETINT (*x, win_x);
7562 XSETINT (*y, win_y);
7563 *time = last_mouse_movement_time;
7568 UNBLOCK_INPUT;
7572 #ifdef USE_X_TOOLKIT
7574 /* Atimer callback function for TIMER. Called every 0.1s to process
7575 Xt timeouts, if needed. We must avoid calling XtAppPending as
7576 much as possible because that function does an implicit XFlush
7577 that slows us down. */
7579 static void
7580 x_process_timeouts (timer)
7581 struct atimer *timer;
7583 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7585 BLOCK_INPUT;
7586 while (XtAppPending (Xt_app_con) & XtIMTimer)
7587 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7588 UNBLOCK_INPUT;
7592 #endif /* USE_X_TOOLKIT */
7595 /* Scroll bar support. */
7597 /* Given an X window ID, find the struct scroll_bar which manages it.
7598 This can be called in GC, so we have to make sure to strip off mark
7599 bits. */
7601 static struct scroll_bar *
7602 x_window_to_scroll_bar (window_id)
7603 Window window_id;
7605 Lisp_Object tail;
7607 for (tail = Vframe_list;
7608 XGCTYPE (tail) == Lisp_Cons;
7609 tail = XCDR (tail))
7611 Lisp_Object frame, bar, condemned;
7613 frame = XCAR (tail);
7614 /* All elements of Vframe_list should be frames. */
7615 if (! GC_FRAMEP (frame))
7616 abort ();
7618 /* Scan this frame's scroll bar list for a scroll bar with the
7619 right window ID. */
7620 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7621 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7622 /* This trick allows us to search both the ordinary and
7623 condemned scroll bar lists with one loop. */
7624 ! GC_NILP (bar) || (bar = condemned,
7625 condemned = Qnil,
7626 ! GC_NILP (bar));
7627 bar = XSCROLL_BAR (bar)->next)
7628 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7629 return XSCROLL_BAR (bar);
7632 return 0;
7637 /************************************************************************
7638 Toolkit scroll bars
7639 ************************************************************************/
7641 #if USE_TOOLKIT_SCROLL_BARS
7643 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7644 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7645 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7646 struct scroll_bar *));
7647 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7648 int, int, int));
7651 /* Id of action hook installed for scroll bars. */
7653 static XtActionHookId action_hook_id;
7655 /* Lisp window being scrolled. Set when starting to interact with
7656 a toolkit scroll bar, reset to nil when ending the interaction. */
7658 static Lisp_Object window_being_scrolled;
7660 /* Last scroll bar part sent in xm_scroll_callback. */
7662 static int last_scroll_bar_part;
7664 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7665 that movements of 1/20 of the screen size are mapped to up/down. */
7667 static Boolean xaw3d_arrow_scroll;
7669 /* Whether the drag scrolling maintains the mouse at the top of the
7670 thumb. If not, resizing the thumb needs to be done more carefully
7671 to avoid jerkyness. */
7673 static Boolean xaw3d_pick_top;
7676 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7677 bars are used.. The hook is responsible for detecting when
7678 the user ends an interaction with the scroll bar, and generates
7679 a `end-scroll' scroll_bar_click' event if so. */
7681 static void
7682 xt_action_hook (widget, client_data, action_name, event, params,
7683 num_params)
7684 Widget widget;
7685 XtPointer client_data;
7686 String action_name;
7687 XEvent *event;
7688 String *params;
7689 Cardinal *num_params;
7691 int scroll_bar_p;
7692 char *end_action;
7694 #ifdef USE_MOTIF
7695 scroll_bar_p = XmIsScrollBar (widget);
7696 end_action = "Release";
7697 #else /* !USE_MOTIF i.e. use Xaw */
7698 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7699 end_action = "EndScroll";
7700 #endif /* USE_MOTIF */
7702 if (scroll_bar_p
7703 && strcmp (action_name, end_action) == 0
7704 && WINDOWP (window_being_scrolled))
7706 struct window *w;
7708 x_send_scroll_bar_event (window_being_scrolled,
7709 scroll_bar_end_scroll, 0, 0);
7710 w = XWINDOW (window_being_scrolled);
7711 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7712 window_being_scrolled = Qnil;
7713 last_scroll_bar_part = -1;
7715 /* Xt timeouts no longer needed. */
7716 toolkit_scroll_bar_interaction = 0;
7721 /* Send a client message with message type Xatom_Scrollbar for a
7722 scroll action to the frame of WINDOW. PART is a value identifying
7723 the part of the scroll bar that was clicked on. PORTION is the
7724 amount to scroll of a whole of WHOLE. */
7726 static void
7727 x_send_scroll_bar_event (window, part, portion, whole)
7728 Lisp_Object window;
7729 int part, portion, whole;
7731 XEvent event;
7732 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7733 struct frame *f = XFRAME (XWINDOW (window)->frame);
7735 /* Construct a ClientMessage event to send to the frame. */
7736 ev->type = ClientMessage;
7737 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7738 ev->display = FRAME_X_DISPLAY (f);
7739 ev->window = FRAME_X_WINDOW (f);
7740 ev->format = 32;
7741 ev->data.l[0] = (long) XFASTINT (window);
7742 ev->data.l[1] = (long) part;
7743 ev->data.l[2] = (long) 0;
7744 ev->data.l[3] = (long) portion;
7745 ev->data.l[4] = (long) whole;
7747 /* Make Xt timeouts work while the scroll bar is active. */
7748 toolkit_scroll_bar_interaction = 1;
7750 /* Setting the event mask to zero means that the message will
7751 be sent to the client that created the window, and if that
7752 window no longer exists, no event will be sent. */
7753 BLOCK_INPUT;
7754 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7755 UNBLOCK_INPUT;
7759 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7760 in *IEVENT. */
7762 static void
7763 x_scroll_bar_to_input_event (event, ievent)
7764 XEvent *event;
7765 struct input_event *ievent;
7767 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7768 Lisp_Object window;
7769 struct frame *f;
7771 XSETFASTINT (window, ev->data.l[0]);
7772 f = XFRAME (XWINDOW (window)->frame);
7774 ievent->kind = scroll_bar_click;
7775 ievent->frame_or_window = window;
7776 ievent->arg = Qnil;
7777 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7778 ievent->part = ev->data.l[1];
7779 ievent->code = ev->data.l[2];
7780 ievent->x = make_number ((int) ev->data.l[3]);
7781 ievent->y = make_number ((int) ev->data.l[4]);
7782 ievent->modifiers = 0;
7786 #ifdef USE_MOTIF
7788 /* Minimum and maximum values used for Motif scroll bars. */
7790 #define XM_SB_MIN 1
7791 #define XM_SB_MAX 10000000
7792 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7795 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7796 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7797 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7799 static void
7800 xm_scroll_callback (widget, client_data, call_data)
7801 Widget widget;
7802 XtPointer client_data, call_data;
7804 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7805 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7806 double percent;
7807 int part = -1, whole = 0, portion = 0;
7809 switch (cs->reason)
7811 case XmCR_DECREMENT:
7812 bar->dragging = Qnil;
7813 part = scroll_bar_up_arrow;
7814 break;
7816 case XmCR_INCREMENT:
7817 bar->dragging = Qnil;
7818 part = scroll_bar_down_arrow;
7819 break;
7821 case XmCR_PAGE_DECREMENT:
7822 bar->dragging = Qnil;
7823 part = scroll_bar_above_handle;
7824 break;
7826 case XmCR_PAGE_INCREMENT:
7827 bar->dragging = Qnil;
7828 part = scroll_bar_below_handle;
7829 break;
7831 case XmCR_TO_TOP:
7832 bar->dragging = Qnil;
7833 part = scroll_bar_to_top;
7834 break;
7836 case XmCR_TO_BOTTOM:
7837 bar->dragging = Qnil;
7838 part = scroll_bar_to_bottom;
7839 break;
7841 case XmCR_DRAG:
7843 int slider_size;
7844 int dragging_down_p = (INTEGERP (bar->dragging)
7845 && XINT (bar->dragging) <= cs->value);
7847 /* Get the slider size. */
7848 BLOCK_INPUT;
7849 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7850 UNBLOCK_INPUT;
7852 /* At the max position of the scroll bar, do a line-wise
7853 movement. Without doing anything, the LessTif scroll bar
7854 calls us with the same cs->value again and again. If we
7855 want to make sure that we can reach the end of the buffer,
7856 we have to do something.
7858 Implementation note: setting bar->dragging always to
7859 cs->value gives a smoother movement at the max position.
7860 Setting it to nil when doing line-wise movement gives
7861 a better slider behavior. */
7863 if (cs->value + slider_size == XM_SB_MAX
7864 || (dragging_down_p
7865 && last_scroll_bar_part == scroll_bar_down_arrow))
7867 part = scroll_bar_down_arrow;
7868 bar->dragging = Qnil;
7870 else
7872 whole = XM_SB_RANGE;
7873 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7874 part = scroll_bar_handle;
7875 bar->dragging = make_number (cs->value);
7878 break;
7880 case XmCR_VALUE_CHANGED:
7881 break;
7884 if (part >= 0)
7886 window_being_scrolled = bar->window;
7887 last_scroll_bar_part = part;
7888 x_send_scroll_bar_event (bar->window, part, portion, whole);
7893 #else /* !USE_MOTIF, i.e. Xaw. */
7896 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7897 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7898 scroll bar struct. CALL_DATA is a pointer to a float saying where
7899 the thumb is. */
7901 static void
7902 xaw_jump_callback (widget, client_data, call_data)
7903 Widget widget;
7904 XtPointer client_data, call_data;
7906 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7907 float top = *(float *) call_data;
7908 float shown;
7909 int whole, portion, height;
7910 int part;
7912 /* Get the size of the thumb, a value between 0 and 1. */
7913 BLOCK_INPUT;
7914 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7915 UNBLOCK_INPUT;
7917 whole = 10000000;
7918 portion = shown < 1 ? top * whole : 0;
7920 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7921 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7922 the bottom, so we force the scrolling whenever we see that we're
7923 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7924 we try to ensure that we always stay two pixels away from the
7925 bottom). */
7926 part = scroll_bar_down_arrow;
7927 else
7928 part = scroll_bar_handle;
7930 window_being_scrolled = bar->window;
7931 bar->dragging = make_number (portion);
7932 last_scroll_bar_part = part;
7933 x_send_scroll_bar_event (bar->window, part, portion, whole);
7937 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7938 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7939 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7940 the scroll bar. CALL_DATA is an integer specifying the action that
7941 has taken place. It's magnitude is in the range 0..height of the
7942 scroll bar. Negative values mean scroll towards buffer start.
7943 Values < height of scroll bar mean line-wise movement. */
7945 static void
7946 xaw_scroll_callback (widget, client_data, call_data)
7947 Widget widget;
7948 XtPointer client_data, call_data;
7950 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7951 int position = (int) call_data;
7952 Dimension height;
7953 int part;
7955 /* Get the height of the scroll bar. */
7956 BLOCK_INPUT;
7957 XtVaGetValues (widget, XtNheight, &height, NULL);
7958 UNBLOCK_INPUT;
7960 if (abs (position) >= height)
7961 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7963 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7964 it maps line-movement to call_data = max(5, height/20). */
7965 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7966 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7967 else
7968 part = scroll_bar_move_ratio;
7970 window_being_scrolled = bar->window;
7971 bar->dragging = Qnil;
7972 last_scroll_bar_part = part;
7973 x_send_scroll_bar_event (bar->window, part, position, height);
7977 #endif /* not USE_MOTIF */
7980 /* Create the widget for scroll bar BAR on frame F. Record the widget
7981 and X window of the scroll bar in BAR. */
7983 static void
7984 x_create_toolkit_scroll_bar (f, bar)
7985 struct frame *f;
7986 struct scroll_bar *bar;
7988 Window xwindow;
7989 Widget widget;
7990 Arg av[20];
7991 int ac = 0;
7992 char *scroll_bar_name = "verticalScrollBar";
7993 unsigned long pixel;
7995 BLOCK_INPUT;
7997 #ifdef USE_MOTIF
7998 /* LessTif 0.85, problems:
8000 1. When the mouse if over the scroll bar, the scroll bar will
8001 get keyboard events. I didn't find a way to turn this off.
8003 2. Do we have to explicitly set the cursor to get an arrow
8004 cursor (see below)? */
8006 /* Set resources. Create the widget. */
8007 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8008 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8009 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8010 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8011 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8012 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8013 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8015 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8016 if (pixel != -1)
8018 XtSetArg (av[ac], XmNforeground, pixel);
8019 ++ac;
8022 pixel = f->output_data.x->scroll_bar_background_pixel;
8023 if (pixel != -1)
8025 XtSetArg (av[ac], XmNbackground, pixel);
8026 ++ac;
8029 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8030 scroll_bar_name, av, ac);
8032 /* Add one callback for everything that can happen. */
8033 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8034 (XtPointer) bar);
8035 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8036 (XtPointer) bar);
8037 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8038 (XtPointer) bar);
8039 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8040 (XtPointer) bar);
8041 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8042 (XtPointer) bar);
8043 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8044 (XtPointer) bar);
8045 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8046 (XtPointer) bar);
8048 /* Realize the widget. Only after that is the X window created. */
8049 XtRealizeWidget (widget);
8051 /* Set the cursor to an arrow. I didn't find a resource to do that.
8052 And I'm wondering why it hasn't an arrow cursor by default. */
8053 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8054 f->output_data.x->nontext_cursor);
8056 #else /* !USE_MOTIF i.e. use Xaw */
8058 /* Set resources. Create the widget. The background of the
8059 Xaw3d scroll bar widget is a little bit light for my taste.
8060 We don't alter it here to let users change it according
8061 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8062 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8063 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8064 /* For smoother scrolling with Xaw3d -sm */
8065 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8066 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8068 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8069 if (pixel != -1)
8071 XtSetArg (av[ac], XtNforeground, pixel);
8072 ++ac;
8075 pixel = f->output_data.x->scroll_bar_background_pixel;
8076 if (pixel != -1)
8078 XtSetArg (av[ac], XtNbackground, pixel);
8079 ++ac;
8082 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8083 f->output_data.x->edit_widget, av, ac);
8086 char *initial = "";
8087 char *val = initial;
8088 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8089 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8090 if (val == initial)
8091 { /* ARROW_SCROLL */
8092 xaw3d_arrow_scroll = True;
8093 /* Isn't that just a personal preference ? -sm */
8094 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8098 /* Define callbacks. */
8099 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8100 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8101 (XtPointer) bar);
8103 /* Realize the widget. Only after that is the X window created. */
8104 XtRealizeWidget (widget);
8106 #endif /* !USE_MOTIF */
8108 /* Install an action hook that let's us detect when the user
8109 finishes interacting with a scroll bar. */
8110 if (action_hook_id == 0)
8111 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8113 /* Remember X window and widget in the scroll bar vector. */
8114 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8115 xwindow = XtWindow (widget);
8116 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8118 UNBLOCK_INPUT;
8122 /* Set the thumb size and position of scroll bar BAR. We are currently
8123 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8125 static void
8126 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8127 struct scroll_bar *bar;
8128 int portion, position, whole;
8130 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8131 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8132 float top, shown;
8134 if (whole == 0)
8135 top = 0, shown = 1;
8136 else
8138 top = (float) position / whole;
8139 shown = (float) portion / whole;
8142 BLOCK_INPUT;
8144 #ifdef USE_MOTIF
8146 int size, value;
8147 Boolean arrow1_selected, arrow2_selected;
8148 unsigned char flags;
8149 XmScrollBarWidget sb;
8151 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8152 is the scroll bar's maximum and MIN is the scroll bar's minimum
8153 value. */
8154 size = shown * XM_SB_RANGE;
8155 size = min (size, XM_SB_RANGE);
8156 size = max (size, 1);
8158 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8159 value = top * XM_SB_RANGE;
8160 value = min (value, XM_SB_MAX - size);
8161 value = max (value, XM_SB_MIN);
8163 /* LessTif: Calling XmScrollBarSetValues after an increment or
8164 decrement turns off auto-repeat LessTif-internally. This can
8165 be seen in ScrollBar.c which resets Arrow1Selected and
8166 Arrow2Selected. It also sets internal flags so that LessTif
8167 believes the mouse is in the slider. We either have to change
8168 our code, or work around that by accessing private data. */
8170 sb = (XmScrollBarWidget) widget;
8171 arrow1_selected = sb->scrollBar.arrow1_selected;
8172 arrow2_selected = sb->scrollBar.arrow2_selected;
8173 flags = sb->scrollBar.flags;
8175 if (NILP (bar->dragging))
8176 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8177 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8178 /* This has the negative side effect that the slider value is
8179 not what it would be if we scrolled here using line-wise or
8180 page-wise movement. */
8181 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8182 else
8184 /* If currently dragging, only update the slider size.
8185 This reduces flicker effects. */
8186 int old_value, old_size, increment, page_increment;
8188 XmScrollBarGetValues (widget, &old_value, &old_size,
8189 &increment, &page_increment);
8190 XmScrollBarSetValues (widget, old_value,
8191 min (size, XM_SB_RANGE - old_value),
8192 0, 0, False);
8195 sb->scrollBar.arrow1_selected = arrow1_selected;
8196 sb->scrollBar.arrow2_selected = arrow2_selected;
8197 sb->scrollBar.flags = flags;
8199 #else /* !USE_MOTIF i.e. use Xaw */
8201 float old_top, old_shown;
8202 Dimension height;
8203 XtVaGetValues (widget,
8204 XtNtopOfThumb, &old_top,
8205 XtNshown, &old_shown,
8206 XtNheight, &height,
8207 NULL);
8209 /* Massage the top+shown values. */
8210 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8211 top = max (0, min (1, top));
8212 else
8213 top = old_top;
8214 /* Keep two pixels available for moving the thumb down. */
8215 shown = max (0, min (1 - top - (2.0 / height), shown));
8217 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8218 check that your system's configuration file contains a define
8219 for `NARROWPROTO'. See s/freebsd.h for an example. */
8220 if (top != old_top || shown != old_shown)
8222 if (NILP (bar->dragging))
8223 XawScrollbarSetThumb (widget, top, shown);
8224 else
8226 #ifdef HAVE_XAW3D
8227 ScrollbarWidget sb = (ScrollbarWidget) widget;
8228 int scroll_mode = 0;
8230 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8231 if (xaw3d_arrow_scroll)
8233 /* Xaw3d stupidly ignores resize requests while dragging
8234 so we have to make it believe it's not in dragging mode. */
8235 scroll_mode = sb->scrollbar.scroll_mode;
8236 if (scroll_mode == 2)
8237 sb->scrollbar.scroll_mode = 0;
8239 #endif
8240 /* Try to make the scrolling a tad smoother. */
8241 if (!xaw3d_pick_top)
8242 shown = min (shown, old_shown);
8244 XawScrollbarSetThumb (widget, top, shown);
8246 #ifdef HAVE_XAW3D
8247 if (xaw3d_arrow_scroll && scroll_mode == 2)
8248 sb->scrollbar.scroll_mode = scroll_mode;
8249 #endif
8253 #endif /* !USE_MOTIF */
8255 UNBLOCK_INPUT;
8258 #endif /* USE_TOOLKIT_SCROLL_BARS */
8262 /************************************************************************
8263 Scroll bars, general
8264 ************************************************************************/
8266 /* Create a scroll bar and return the scroll bar vector for it. W is
8267 the Emacs window on which to create the scroll bar. TOP, LEFT,
8268 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8269 scroll bar. */
8271 static struct scroll_bar *
8272 x_scroll_bar_create (w, top, left, width, height)
8273 struct window *w;
8274 int top, left, width, height;
8276 struct frame *f = XFRAME (w->frame);
8277 struct scroll_bar *bar
8278 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8280 BLOCK_INPUT;
8282 #if USE_TOOLKIT_SCROLL_BARS
8283 x_create_toolkit_scroll_bar (f, bar);
8284 #else /* not USE_TOOLKIT_SCROLL_BARS */
8286 XSetWindowAttributes a;
8287 unsigned long mask;
8288 Window window;
8290 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8291 if (a.background_pixel == -1)
8292 a.background_pixel = f->output_data.x->background_pixel;
8294 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8295 | ButtonMotionMask | PointerMotionHintMask
8296 | ExposureMask);
8297 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8299 mask = (CWBackPixel | CWEventMask | CWCursor);
8301 /* Clear the area of W that will serve as a scroll bar. This is
8302 for the case that a window has been split horizontally. In
8303 this case, no clear_frame is generated to reduce flickering. */
8304 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8305 left, top, width,
8306 window_box_height (w), False);
8308 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8309 /* Position and size of scroll bar. */
8310 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8311 top,
8312 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8313 height,
8314 /* Border width, depth, class, and visual. */
8316 CopyFromParent,
8317 CopyFromParent,
8318 CopyFromParent,
8319 /* Attributes. */
8320 mask, &a);
8321 SET_SCROLL_BAR_X_WINDOW (bar, window);
8323 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8325 XSETWINDOW (bar->window, w);
8326 XSETINT (bar->top, top);
8327 XSETINT (bar->left, left);
8328 XSETINT (bar->width, width);
8329 XSETINT (bar->height, height);
8330 XSETINT (bar->start, 0);
8331 XSETINT (bar->end, 0);
8332 bar->dragging = Qnil;
8334 /* Add bar to its frame's list of scroll bars. */
8335 bar->next = FRAME_SCROLL_BARS (f);
8336 bar->prev = Qnil;
8337 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8338 if (!NILP (bar->next))
8339 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8341 /* Map the window/widget. */
8342 #if USE_TOOLKIT_SCROLL_BARS
8344 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8345 XtConfigureWidget (scroll_bar,
8346 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8347 top,
8348 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8349 height, 0);
8350 XtMapWidget (scroll_bar);
8352 #else /* not USE_TOOLKIT_SCROLL_BARS */
8353 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8354 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8356 UNBLOCK_INPUT;
8357 return bar;
8361 /* Draw BAR's handle in the proper position.
8363 If the handle is already drawn from START to END, don't bother
8364 redrawing it, unless REBUILD is non-zero; in that case, always
8365 redraw it. (REBUILD is handy for drawing the handle after expose
8366 events.)
8368 Normally, we want to constrain the start and end of the handle to
8369 fit inside its rectangle, but if the user is dragging the scroll
8370 bar handle, we want to let them drag it down all the way, so that
8371 the bar's top is as far down as it goes; otherwise, there's no way
8372 to move to the very end of the buffer. */
8374 #ifndef USE_TOOLKIT_SCROLL_BARS
8376 static void
8377 x_scroll_bar_set_handle (bar, start, end, rebuild)
8378 struct scroll_bar *bar;
8379 int start, end;
8380 int rebuild;
8382 int dragging = ! NILP (bar->dragging);
8383 Window w = SCROLL_BAR_X_WINDOW (bar);
8384 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8385 GC gc = f->output_data.x->normal_gc;
8387 /* If the display is already accurate, do nothing. */
8388 if (! rebuild
8389 && start == XINT (bar->start)
8390 && end == XINT (bar->end))
8391 return;
8393 BLOCK_INPUT;
8396 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8397 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8398 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8400 /* Make sure the values are reasonable, and try to preserve
8401 the distance between start and end. */
8403 int length = end - start;
8405 if (start < 0)
8406 start = 0;
8407 else if (start > top_range)
8408 start = top_range;
8409 end = start + length;
8411 if (end < start)
8412 end = start;
8413 else if (end > top_range && ! dragging)
8414 end = top_range;
8417 /* Store the adjusted setting in the scroll bar. */
8418 XSETINT (bar->start, start);
8419 XSETINT (bar->end, end);
8421 /* Clip the end position, just for display. */
8422 if (end > top_range)
8423 end = top_range;
8425 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8426 below top positions, to make sure the handle is always at least
8427 that many pixels tall. */
8428 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8430 /* Draw the empty space above the handle. Note that we can't clear
8431 zero-height areas; that means "clear to end of window." */
8432 if (0 < start)
8433 XClearArea (FRAME_X_DISPLAY (f), w,
8435 /* x, y, width, height, and exposures. */
8436 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8437 VERTICAL_SCROLL_BAR_TOP_BORDER,
8438 inside_width, start,
8439 False);
8441 /* Change to proper foreground color if one is specified. */
8442 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8443 XSetForeground (FRAME_X_DISPLAY (f), gc,
8444 f->output_data.x->scroll_bar_foreground_pixel);
8446 /* Draw the handle itself. */
8447 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8449 /* x, y, width, height */
8450 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8451 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8452 inside_width, end - start);
8454 /* Restore the foreground color of the GC if we changed it above. */
8455 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8456 XSetForeground (FRAME_X_DISPLAY (f), gc,
8457 f->output_data.x->foreground_pixel);
8459 /* Draw the empty space below the handle. Note that we can't
8460 clear zero-height areas; that means "clear to end of window." */
8461 if (end < inside_height)
8462 XClearArea (FRAME_X_DISPLAY (f), w,
8464 /* x, y, width, height, and exposures. */
8465 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8466 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8467 inside_width, inside_height - end,
8468 False);
8472 UNBLOCK_INPUT;
8475 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8477 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8478 nil. */
8480 static void
8481 x_scroll_bar_remove (bar)
8482 struct scroll_bar *bar;
8484 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8485 BLOCK_INPUT;
8487 #if USE_TOOLKIT_SCROLL_BARS
8488 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8489 #else
8490 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8491 #endif
8493 /* Disassociate this scroll bar from its window. */
8494 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8496 UNBLOCK_INPUT;
8500 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8501 that we are displaying PORTION characters out of a total of WHOLE
8502 characters, starting at POSITION. If WINDOW has no scroll bar,
8503 create one. */
8505 static void
8506 XTset_vertical_scroll_bar (w, portion, whole, position)
8507 struct window *w;
8508 int portion, whole, position;
8510 struct frame *f = XFRAME (w->frame);
8511 struct scroll_bar *bar;
8512 int top, height, left, sb_left, width, sb_width;
8513 int window_x, window_y, window_width, window_height;
8515 /* Get window dimensions. */
8516 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8517 top = window_y;
8518 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8519 height = window_height;
8521 /* Compute the left edge of the scroll bar area. */
8522 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8523 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8524 else
8525 left = XFASTINT (w->left);
8526 left *= CANON_X_UNIT (f);
8527 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8529 /* Compute the width of the scroll bar which might be less than
8530 the width of the area reserved for the scroll bar. */
8531 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8532 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8533 else
8534 sb_width = width;
8536 /* Compute the left edge of the scroll bar. */
8537 #ifdef USE_TOOLKIT_SCROLL_BARS
8538 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8539 sb_left = left + width - sb_width - (width - sb_width) / 2;
8540 else
8541 sb_left = left + (width - sb_width) / 2;
8542 #else
8543 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8544 sb_left = left + width - sb_width;
8545 else
8546 sb_left = left;
8547 #endif
8549 /* Does the scroll bar exist yet? */
8550 if (NILP (w->vertical_scroll_bar))
8552 BLOCK_INPUT;
8553 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8554 left, top, width, height, False);
8555 UNBLOCK_INPUT;
8556 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8558 else
8560 /* It may just need to be moved and resized. */
8561 unsigned int mask = 0;
8563 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8565 BLOCK_INPUT;
8567 if (sb_left != XINT (bar->left))
8568 mask |= CWX;
8569 if (top != XINT (bar->top))
8570 mask |= CWY;
8571 if (sb_width != XINT (bar->width))
8572 mask |= CWWidth;
8573 if (height != XINT (bar->height))
8574 mask |= CWHeight;
8576 #ifdef USE_TOOLKIT_SCROLL_BARS
8578 /* Since toolkit scroll bars are smaller than the space reserved
8579 for them on the frame, we have to clear "under" them. */
8580 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8581 left, top, width, height, False);
8583 /* Move/size the scroll bar widget. */
8584 if (mask)
8585 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
8586 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8587 top,
8588 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8589 height, 0);
8591 #else /* not USE_TOOLKIT_SCROLL_BARS */
8593 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8595 /* Clear areas not covered by the scroll bar. This makes sure a
8596 previous mode line display is cleared after C-x 2 C-x 1, for
8597 example. Non-toolkit scroll bars are as wide as the area
8598 reserved for scroll bars - trim at both sides. */
8599 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8600 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8601 height, False);
8602 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8603 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8604 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8605 height, False);
8608 /* Move/size the scroll bar window. */
8609 if (mask)
8611 XWindowChanges wc;
8613 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8614 wc.y = top;
8615 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8616 wc.height = height;
8617 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8618 mask, &wc);
8621 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8623 /* Remember new settings. */
8624 XSETINT (bar->left, sb_left);
8625 XSETINT (bar->top, top);
8626 XSETINT (bar->width, sb_width);
8627 XSETINT (bar->height, height);
8629 UNBLOCK_INPUT;
8632 #if USE_TOOLKIT_SCROLL_BARS
8633 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8634 #else /* not USE_TOOLKIT_SCROLL_BARS */
8635 /* Set the scroll bar's current state, unless we're currently being
8636 dragged. */
8637 if (NILP (bar->dragging))
8639 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8641 if (whole == 0)
8642 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8643 else
8645 int start = ((double) position * top_range) / whole;
8646 int end = ((double) (position + portion) * top_range) / whole;
8647 x_scroll_bar_set_handle (bar, start, end, 0);
8650 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8652 XSETVECTOR (w->vertical_scroll_bar, bar);
8656 /* The following three hooks are used when we're doing a thorough
8657 redisplay of the frame. We don't explicitly know which scroll bars
8658 are going to be deleted, because keeping track of when windows go
8659 away is a real pain - "Can you say set-window-configuration, boys
8660 and girls?" Instead, we just assert at the beginning of redisplay
8661 that *all* scroll bars are to be removed, and then save a scroll bar
8662 from the fiery pit when we actually redisplay its window. */
8664 /* Arrange for all scroll bars on FRAME to be removed at the next call
8665 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8666 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8668 static void
8669 XTcondemn_scroll_bars (frame)
8670 FRAME_PTR frame;
8672 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8673 while (! NILP (FRAME_SCROLL_BARS (frame)))
8675 Lisp_Object bar;
8676 bar = FRAME_SCROLL_BARS (frame);
8677 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8678 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8679 XSCROLL_BAR (bar)->prev = Qnil;
8680 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8681 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8682 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8687 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8688 Note that WINDOW isn't necessarily condemned at all. */
8690 static void
8691 XTredeem_scroll_bar (window)
8692 struct window *window;
8694 struct scroll_bar *bar;
8695 struct frame *f;
8697 /* We can't redeem this window's scroll bar if it doesn't have one. */
8698 if (NILP (window->vertical_scroll_bar))
8699 abort ();
8701 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8703 /* Unlink it from the condemned list. */
8704 f = XFRAME (WINDOW_FRAME (window));
8705 if (NILP (bar->prev))
8707 /* If the prev pointer is nil, it must be the first in one of
8708 the lists. */
8709 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8710 /* It's not condemned. Everything's fine. */
8711 return;
8712 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8713 window->vertical_scroll_bar))
8714 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8715 else
8716 /* If its prev pointer is nil, it must be at the front of
8717 one or the other! */
8718 abort ();
8720 else
8721 XSCROLL_BAR (bar->prev)->next = bar->next;
8723 if (! NILP (bar->next))
8724 XSCROLL_BAR (bar->next)->prev = bar->prev;
8726 bar->next = FRAME_SCROLL_BARS (f);
8727 bar->prev = Qnil;
8728 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8729 if (! NILP (bar->next))
8730 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8733 /* Remove all scroll bars on FRAME that haven't been saved since the
8734 last call to `*condemn_scroll_bars_hook'. */
8736 static void
8737 XTjudge_scroll_bars (f)
8738 FRAME_PTR f;
8740 Lisp_Object bar, next;
8742 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8744 /* Clear out the condemned list now so we won't try to process any
8745 more events on the hapless scroll bars. */
8746 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8748 for (; ! NILP (bar); bar = next)
8750 struct scroll_bar *b = XSCROLL_BAR (bar);
8752 x_scroll_bar_remove (b);
8754 next = b->next;
8755 b->next = b->prev = Qnil;
8758 /* Now there should be no references to the condemned scroll bars,
8759 and they should get garbage-collected. */
8763 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8764 is a no-op when using toolkit scroll bars.
8766 This may be called from a signal handler, so we have to ignore GC
8767 mark bits. */
8769 static void
8770 x_scroll_bar_expose (bar, event)
8771 struct scroll_bar *bar;
8772 XEvent *event;
8774 #ifndef USE_TOOLKIT_SCROLL_BARS
8776 Window w = SCROLL_BAR_X_WINDOW (bar);
8777 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8778 GC gc = f->output_data.x->normal_gc;
8779 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8781 BLOCK_INPUT;
8783 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8785 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8786 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8788 /* x, y, width, height */
8789 0, 0,
8790 XINT (bar->width) - 1 - width_trim - width_trim,
8791 XINT (bar->height) - 1);
8793 UNBLOCK_INPUT;
8795 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8798 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8799 is set to something other than no_event, it is enqueued.
8801 This may be called from a signal handler, so we have to ignore GC
8802 mark bits. */
8804 #ifndef USE_TOOLKIT_SCROLL_BARS
8806 static void
8807 x_scroll_bar_handle_click (bar, event, emacs_event)
8808 struct scroll_bar *bar;
8809 XEvent *event;
8810 struct input_event *emacs_event;
8812 if (! GC_WINDOWP (bar->window))
8813 abort ();
8815 emacs_event->kind = scroll_bar_click;
8816 emacs_event->code = event->xbutton.button - Button1;
8817 emacs_event->modifiers
8818 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8819 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8820 event->xbutton.state)
8821 | (event->type == ButtonRelease
8822 ? up_modifier
8823 : down_modifier));
8824 emacs_event->frame_or_window = bar->window;
8825 emacs_event->arg = Qnil;
8826 emacs_event->timestamp = event->xbutton.time;
8828 #if 0
8829 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8830 int internal_height
8831 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8832 #endif
8833 int top_range
8834 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8835 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8837 if (y < 0) y = 0;
8838 if (y > top_range) y = top_range;
8840 if (y < XINT (bar->start))
8841 emacs_event->part = scroll_bar_above_handle;
8842 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8843 emacs_event->part = scroll_bar_handle;
8844 else
8845 emacs_event->part = scroll_bar_below_handle;
8847 /* Just because the user has clicked on the handle doesn't mean
8848 they want to drag it. Lisp code needs to be able to decide
8849 whether or not we're dragging. */
8850 #if 0
8851 /* If the user has just clicked on the handle, record where they're
8852 holding it. */
8853 if (event->type == ButtonPress
8854 && emacs_event->part == scroll_bar_handle)
8855 XSETINT (bar->dragging, y - XINT (bar->start));
8856 #endif
8858 /* If the user has released the handle, set it to its final position. */
8859 if (event->type == ButtonRelease
8860 && ! NILP (bar->dragging))
8862 int new_start = y - XINT (bar->dragging);
8863 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8865 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8866 bar->dragging = Qnil;
8869 /* Same deal here as the other #if 0. */
8870 #if 0
8871 /* Clicks on the handle are always reported as occurring at the top of
8872 the handle. */
8873 if (emacs_event->part == scroll_bar_handle)
8874 emacs_event->x = bar->start;
8875 else
8876 XSETINT (emacs_event->x, y);
8877 #else
8878 XSETINT (emacs_event->x, y);
8879 #endif
8881 XSETINT (emacs_event->y, top_range);
8885 /* Handle some mouse motion while someone is dragging the scroll bar.
8887 This may be called from a signal handler, so we have to ignore GC
8888 mark bits. */
8890 static void
8891 x_scroll_bar_note_movement (bar, event)
8892 struct scroll_bar *bar;
8893 XEvent *event;
8895 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8897 last_mouse_movement_time = event->xmotion.time;
8899 f->mouse_moved = 1;
8900 XSETVECTOR (last_mouse_scroll_bar, bar);
8902 /* If we're dragging the bar, display it. */
8903 if (! GC_NILP (bar->dragging))
8905 /* Where should the handle be now? */
8906 int new_start = event->xmotion.y - XINT (bar->dragging);
8908 if (new_start != XINT (bar->start))
8910 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8912 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8917 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8919 /* Return information to the user about the current position of the mouse
8920 on the scroll bar. */
8922 static void
8923 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8924 FRAME_PTR *fp;
8925 Lisp_Object *bar_window;
8926 enum scroll_bar_part *part;
8927 Lisp_Object *x, *y;
8928 unsigned long *time;
8930 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8931 Window w = SCROLL_BAR_X_WINDOW (bar);
8932 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8933 int win_x, win_y;
8934 Window dummy_window;
8935 int dummy_coord;
8936 unsigned int dummy_mask;
8938 BLOCK_INPUT;
8940 /* Get the mouse's position relative to the scroll bar window, and
8941 report that. */
8942 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8944 /* Root, child, root x and root y. */
8945 &dummy_window, &dummy_window,
8946 &dummy_coord, &dummy_coord,
8948 /* Position relative to scroll bar. */
8949 &win_x, &win_y,
8951 /* Mouse buttons and modifier keys. */
8952 &dummy_mask))
8954 else
8956 #if 0
8957 int inside_height
8958 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8959 #endif
8960 int top_range
8961 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8963 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8965 if (! NILP (bar->dragging))
8966 win_y -= XINT (bar->dragging);
8968 if (win_y < 0)
8969 win_y = 0;
8970 if (win_y > top_range)
8971 win_y = top_range;
8973 *fp = f;
8974 *bar_window = bar->window;
8976 if (! NILP (bar->dragging))
8977 *part = scroll_bar_handle;
8978 else if (win_y < XINT (bar->start))
8979 *part = scroll_bar_above_handle;
8980 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8981 *part = scroll_bar_handle;
8982 else
8983 *part = scroll_bar_below_handle;
8985 XSETINT (*x, win_y);
8986 XSETINT (*y, top_range);
8988 f->mouse_moved = 0;
8989 last_mouse_scroll_bar = Qnil;
8992 *time = last_mouse_movement_time;
8994 UNBLOCK_INPUT;
8998 /* The screen has been cleared so we may have changed foreground or
8999 background colors, and the scroll bars may need to be redrawn.
9000 Clear out the scroll bars, and ask for expose events, so we can
9001 redraw them. */
9003 void
9004 x_scroll_bar_clear (f)
9005 FRAME_PTR f;
9007 #ifndef USE_TOOLKIT_SCROLL_BARS
9008 Lisp_Object bar;
9010 /* We can have scroll bars even if this is 0,
9011 if we just turned off scroll bar mode.
9012 But in that case we should not clear them. */
9013 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9014 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9015 bar = XSCROLL_BAR (bar)->next)
9016 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9017 0, 0, 0, 0, True);
9018 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9021 /* This processes Expose events from the menu-bar specific X event
9022 loop in xmenu.c. This allows to redisplay the frame if necessary
9023 when handling menu-bar or pop-up items. */
9026 process_expose_from_menu (event)
9027 XEvent event;
9029 FRAME_PTR f;
9030 struct x_display_info *dpyinfo;
9031 int frame_exposed_p = 0;
9033 BLOCK_INPUT;
9035 dpyinfo = x_display_info_for_display (event.xexpose.display);
9036 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9037 if (f)
9039 if (f->async_visible == 0)
9041 f->async_visible = 1;
9042 f->async_iconified = 0;
9043 f->output_data.x->has_been_visible = 1;
9044 SET_FRAME_GARBAGED (f);
9046 else
9048 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9049 event.xexpose.x, event.xexpose.y,
9050 event.xexpose.width, event.xexpose.height);
9051 frame_exposed_p = 1;
9054 else
9056 struct scroll_bar *bar
9057 = x_window_to_scroll_bar (event.xexpose.window);
9059 if (bar)
9060 x_scroll_bar_expose (bar, &event);
9063 UNBLOCK_INPUT;
9064 return frame_exposed_p;
9067 /* Define a queue to save up SelectionRequest events for later handling. */
9069 struct selection_event_queue
9071 XEvent event;
9072 struct selection_event_queue *next;
9075 static struct selection_event_queue *queue;
9077 /* Nonzero means queue up certain events--don't process them yet. */
9079 static int x_queue_selection_requests;
9081 /* Queue up an X event *EVENT, to be processed later. */
9083 static void
9084 x_queue_event (f, event)
9085 FRAME_PTR f;
9086 XEvent *event;
9088 struct selection_event_queue *queue_tmp
9089 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9091 if (queue_tmp != NULL)
9093 queue_tmp->event = *event;
9094 queue_tmp->next = queue;
9095 queue = queue_tmp;
9099 /* Take all the queued events and put them back
9100 so that they get processed afresh. */
9102 static void
9103 x_unqueue_events (display)
9104 Display *display;
9106 while (queue != NULL)
9108 struct selection_event_queue *queue_tmp = queue;
9109 XPutBackEvent (display, &queue_tmp->event);
9110 queue = queue_tmp->next;
9111 xfree ((char *)queue_tmp);
9115 /* Start queuing SelectionRequest events. */
9117 void
9118 x_start_queuing_selection_requests (display)
9119 Display *display;
9121 x_queue_selection_requests++;
9124 /* Stop queuing SelectionRequest events. */
9126 void
9127 x_stop_queuing_selection_requests (display)
9128 Display *display;
9130 x_queue_selection_requests--;
9131 x_unqueue_events (display);
9134 /* The main X event-reading loop - XTread_socket. */
9136 /* Time stamp of enter window event. This is only used by XTread_socket,
9137 but we have to put it out here, since static variables within functions
9138 sometimes don't work. */
9140 static Time enter_timestamp;
9142 /* This holds the state XLookupString needs to implement dead keys
9143 and other tricks known as "compose processing". _X Window System_
9144 says that a portable program can't use this, but Stephen Gildea assures
9145 me that letting the compiler initialize it to zeros will work okay.
9147 This must be defined outside of XTread_socket, for the same reasons
9148 given for enter_time stamp, above. */
9150 static XComposeStatus compose_status;
9152 /* Record the last 100 characters stored
9153 to help debug the loss-of-chars-during-GC problem. */
9155 static int temp_index;
9156 static short temp_buffer[100];
9158 /* Set this to nonzero to fake an "X I/O error"
9159 on a particular display. */
9161 struct x_display_info *XTread_socket_fake_io_error;
9163 /* When we find no input here, we occasionally do a no-op command
9164 to verify that the X server is still running and we can still talk with it.
9165 We try all the open displays, one by one.
9166 This variable is used for cycling thru the displays. */
9168 static struct x_display_info *next_noop_dpyinfo;
9170 #define SET_SAVED_MENU_EVENT(size) \
9171 do \
9173 if (f->output_data.x->saved_menu_event == 0) \
9174 f->output_data.x->saved_menu_event \
9175 = (XEvent *) xmalloc (sizeof (XEvent)); \
9176 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9177 if (numchars >= 1) \
9179 bufp->kind = menu_bar_activate_event; \
9180 XSETFRAME (bufp->frame_or_window, f); \
9181 bufp->arg = Qnil; \
9182 bufp++; \
9183 count++; \
9184 numchars--; \
9187 while (0)
9189 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9190 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9192 /* Read events coming from the X server.
9193 This routine is called by the SIGIO handler.
9194 We return as soon as there are no more events to be read.
9196 Events representing keys are stored in buffer BUFP,
9197 which can hold up to NUMCHARS characters.
9198 We return the number of characters stored into the buffer,
9199 thus pretending to be `read'.
9201 EXPECTED is nonzero if the caller knows input is available. */
9204 XTread_socket (sd, bufp, numchars, expected)
9205 register int sd;
9206 /* register */ struct input_event *bufp;
9207 /* register */ int numchars;
9208 int expected;
9210 int count = 0;
9211 int nbytes = 0;
9212 XEvent event;
9213 struct frame *f;
9214 int event_found = 0;
9215 struct x_display_info *dpyinfo;
9216 struct coding_system coding;
9218 if (interrupt_input_blocked)
9220 interrupt_input_pending = 1;
9221 return -1;
9224 interrupt_input_pending = 0;
9225 BLOCK_INPUT;
9227 /* So people can tell when we have read the available input. */
9228 input_signal_count++;
9230 if (numchars <= 0)
9231 abort (); /* Don't think this happens. */
9233 ++handling_signal;
9235 /* The input should be decoded if it is from XIM. Currently the
9236 locale of XIM is the same as that of the system. So, we can use
9237 Vlocale_coding_system which is initialized properly at Emacs
9238 startup time. */
9239 setup_coding_system (Vlocale_coding_system, &coding);
9240 coding.src_multibyte = 0;
9241 coding.dst_multibyte = 1;
9242 /* The input is converted to events, thus we can't handle
9243 composition. Anyway, there's no XIM that gives us composition
9244 information. */
9245 coding.composing = COMPOSITION_DISABLED;
9247 /* Find the display we are supposed to read input for.
9248 It's the one communicating on descriptor SD. */
9249 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9251 #if 0 /* This ought to be unnecessary; let's verify it. */
9252 #ifdef FIOSNBIO
9253 /* If available, Xlib uses FIOSNBIO to make the socket
9254 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9255 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9256 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9257 fcntl (dpyinfo->connection, F_SETFL, 0);
9258 #endif /* ! defined (FIOSNBIO) */
9259 #endif
9261 #if 0 /* This code can't be made to work, with multiple displays,
9262 and appears not to be used on any system any more.
9263 Also keyboard.c doesn't turn O_NDELAY on and off
9264 for X connections. */
9265 #ifndef SIGIO
9266 #ifndef HAVE_SELECT
9267 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9269 extern int read_alarm_should_throw;
9270 read_alarm_should_throw = 1;
9271 XPeekEvent (dpyinfo->display, &event);
9272 read_alarm_should_throw = 0;
9274 #endif /* HAVE_SELECT */
9275 #endif /* SIGIO */
9276 #endif
9278 /* For debugging, this gives a way to fake an I/O error. */
9279 if (dpyinfo == XTread_socket_fake_io_error)
9281 XTread_socket_fake_io_error = 0;
9282 x_io_error_quitter (dpyinfo->display);
9285 while (XPending (dpyinfo->display))
9287 XNextEvent (dpyinfo->display, &event);
9289 #ifdef HAVE_X_I18N
9291 /* Filter events for the current X input method.
9292 XFilterEvent returns non-zero if the input method has
9293 consumed the event. We pass the frame's X window to
9294 XFilterEvent because that's the one for which the IC
9295 was created. */
9296 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9297 event.xclient.window);
9298 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9299 break;
9301 #endif
9302 event_found = 1;
9304 switch (event.type)
9306 case ClientMessage:
9308 if (event.xclient.message_type
9309 == dpyinfo->Xatom_wm_protocols
9310 && event.xclient.format == 32)
9312 if (event.xclient.data.l[0]
9313 == dpyinfo->Xatom_wm_take_focus)
9315 /* Use x_any_window_to_frame because this
9316 could be the shell widget window
9317 if the frame has no title bar. */
9318 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9319 #ifdef HAVE_X_I18N
9320 /* Not quite sure this is needed -pd */
9321 if (f && FRAME_XIC (f))
9322 XSetICFocus (FRAME_XIC (f));
9323 #endif
9324 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9325 instructs the WM to set the input focus automatically for
9326 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9327 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9328 it has set the focus. So, XSetInputFocus below is not
9329 needed.
9331 The call to XSetInputFocus below has also caused trouble. In
9332 cases where the XSetInputFocus done by the WM and the one
9333 below are temporally close (on a fast machine), the call
9334 below can generate additional FocusIn events which confuse
9335 Emacs. */
9337 /* Since we set WM_TAKE_FOCUS, we must call
9338 XSetInputFocus explicitly. But not if f is null,
9339 since that might be an event for a deleted frame. */
9340 if (f)
9342 Display *d = event.xclient.display;
9343 /* Catch and ignore errors, in case window has been
9344 iconified by a window manager such as GWM. */
9345 int count = x_catch_errors (d);
9346 XSetInputFocus (d, event.xclient.window,
9347 /* The ICCCM says this is
9348 the only valid choice. */
9349 RevertToParent,
9350 event.xclient.data.l[1]);
9351 /* This is needed to detect the error
9352 if there is an error. */
9353 XSync (d, False);
9354 x_uncatch_errors (d, count);
9356 /* Not certain about handling scroll bars here */
9357 #endif /* 0 */
9359 else if (event.xclient.data.l[0]
9360 == dpyinfo->Xatom_wm_save_yourself)
9362 /* Save state modify the WM_COMMAND property to
9363 something which can reinstate us. This notifies
9364 the session manager, who's looking for such a
9365 PropertyNotify. Can restart processing when
9366 a keyboard or mouse event arrives. */
9367 if (numchars > 0)
9369 f = x_top_window_to_frame (dpyinfo,
9370 event.xclient.window);
9372 /* This is just so we only give real data once
9373 for a single Emacs process. */
9374 if (f == SELECTED_FRAME ())
9375 XSetCommand (FRAME_X_DISPLAY (f),
9376 event.xclient.window,
9377 initial_argv, initial_argc);
9378 else if (f)
9379 XSetCommand (FRAME_X_DISPLAY (f),
9380 event.xclient.window,
9381 0, 0);
9384 else if (event.xclient.data.l[0]
9385 == dpyinfo->Xatom_wm_delete_window)
9387 struct frame *f
9388 = x_any_window_to_frame (dpyinfo,
9389 event.xclient.window);
9391 if (f)
9393 if (numchars == 0)
9394 abort ();
9396 bufp->kind = delete_window_event;
9397 XSETFRAME (bufp->frame_or_window, f);
9398 bufp->arg = Qnil;
9399 bufp++;
9401 count += 1;
9402 numchars -= 1;
9406 else if (event.xclient.message_type
9407 == dpyinfo->Xatom_wm_configure_denied)
9410 else if (event.xclient.message_type
9411 == dpyinfo->Xatom_wm_window_moved)
9413 int new_x, new_y;
9414 struct frame *f
9415 = x_window_to_frame (dpyinfo, event.xclient.window);
9417 new_x = event.xclient.data.s[0];
9418 new_y = event.xclient.data.s[1];
9420 if (f)
9422 f->output_data.x->left_pos = new_x;
9423 f->output_data.x->top_pos = new_y;
9426 #ifdef HACK_EDITRES
9427 else if (event.xclient.message_type
9428 == dpyinfo->Xatom_editres)
9430 struct frame *f
9431 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9432 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9433 &event, NULL);
9435 #endif /* HACK_EDITRES */
9436 else if ((event.xclient.message_type
9437 == dpyinfo->Xatom_DONE)
9438 || (event.xclient.message_type
9439 == dpyinfo->Xatom_PAGE))
9441 /* Ghostview job completed. Kill it. We could
9442 reply with "Next" if we received "Page", but we
9443 currently never do because we are interested in
9444 images, only, which should have 1 page. */
9445 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9446 struct frame *f
9447 = x_window_to_frame (dpyinfo, event.xclient.window);
9448 x_kill_gs_process (pixmap, f);
9449 expose_frame (f, 0, 0, 0, 0);
9451 #ifdef USE_TOOLKIT_SCROLL_BARS
9452 /* Scroll bar callbacks send a ClientMessage from which
9453 we construct an input_event. */
9454 else if (event.xclient.message_type
9455 == dpyinfo->Xatom_Scrollbar)
9457 x_scroll_bar_to_input_event (&event, bufp);
9458 ++bufp, ++count, --numchars;
9459 goto out;
9461 #endif /* USE_TOOLKIT_SCROLL_BARS */
9462 else
9463 goto OTHER;
9465 break;
9467 case SelectionNotify:
9468 #ifdef USE_X_TOOLKIT
9469 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9470 goto OTHER;
9471 #endif /* not USE_X_TOOLKIT */
9472 x_handle_selection_notify (&event.xselection);
9473 break;
9475 case SelectionClear: /* Someone has grabbed ownership. */
9476 #ifdef USE_X_TOOLKIT
9477 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9478 goto OTHER;
9479 #endif /* USE_X_TOOLKIT */
9481 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9483 if (numchars == 0)
9484 abort ();
9486 bufp->kind = selection_clear_event;
9487 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9488 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9489 SELECTION_EVENT_TIME (bufp) = eventp->time;
9490 bufp->frame_or_window = Qnil;
9491 bufp->arg = Qnil;
9492 bufp++;
9494 count += 1;
9495 numchars -= 1;
9497 break;
9499 case SelectionRequest: /* Someone wants our selection. */
9500 #ifdef USE_X_TOOLKIT
9501 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9502 goto OTHER;
9503 #endif /* USE_X_TOOLKIT */
9504 if (x_queue_selection_requests)
9505 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9506 &event);
9507 else
9509 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9511 if (numchars == 0)
9512 abort ();
9514 bufp->kind = selection_request_event;
9515 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9516 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9517 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9518 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9519 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9520 SELECTION_EVENT_TIME (bufp) = eventp->time;
9521 bufp->frame_or_window = Qnil;
9522 bufp->arg = Qnil;
9523 bufp++;
9525 count += 1;
9526 numchars -= 1;
9528 break;
9530 case PropertyNotify:
9531 #ifdef USE_X_TOOLKIT
9532 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9533 goto OTHER;
9534 #endif /* not USE_X_TOOLKIT */
9535 x_handle_property_notify (&event.xproperty);
9536 break;
9538 case ReparentNotify:
9539 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9540 if (f)
9542 int x, y;
9543 f->output_data.x->parent_desc = event.xreparent.parent;
9544 x_real_positions (f, &x, &y);
9545 f->output_data.x->left_pos = x;
9546 f->output_data.x->top_pos = y;
9548 break;
9550 case Expose:
9551 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9552 if (f)
9554 if (f->async_visible == 0)
9556 f->async_visible = 1;
9557 f->async_iconified = 0;
9558 f->output_data.x->has_been_visible = 1;
9559 SET_FRAME_GARBAGED (f);
9561 else
9562 expose_frame (x_window_to_frame (dpyinfo,
9563 event.xexpose.window),
9564 event.xexpose.x, event.xexpose.y,
9565 event.xexpose.width, event.xexpose.height);
9567 else
9569 #ifdef USE_TOOLKIT_SCROLL_BARS
9570 /* Dispatch event to the widget. */
9571 goto OTHER;
9572 #else /* not USE_TOOLKIT_SCROLL_BARS */
9573 struct scroll_bar *bar
9574 = x_window_to_scroll_bar (event.xexpose.window);
9576 if (bar)
9577 x_scroll_bar_expose (bar, &event);
9578 #ifdef USE_X_TOOLKIT
9579 else
9580 goto OTHER;
9581 #endif /* USE_X_TOOLKIT */
9582 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9584 break;
9586 case GraphicsExpose: /* This occurs when an XCopyArea's
9587 source area was obscured or not
9588 available.*/
9589 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9590 if (f)
9592 expose_frame (f,
9593 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9594 event.xgraphicsexpose.width,
9595 event.xgraphicsexpose.height);
9597 #ifdef USE_X_TOOLKIT
9598 else
9599 goto OTHER;
9600 #endif /* USE_X_TOOLKIT */
9601 break;
9603 case NoExpose: /* This occurs when an XCopyArea's
9604 source area was completely
9605 available */
9606 break;
9608 case UnmapNotify:
9609 /* Redo the mouse-highlight after the tooltip has gone. */
9610 if (event.xmap.window == tip_window)
9612 tip_window = 0;
9613 redo_mouse_highlight ();
9616 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9617 if (f) /* F may no longer exist if
9618 the frame was deleted. */
9620 /* While a frame is unmapped, display generation is
9621 disabled; you don't want to spend time updating a
9622 display that won't ever be seen. */
9623 f->async_visible = 0;
9624 /* We can't distinguish, from the event, whether the window
9625 has become iconified or invisible. So assume, if it
9626 was previously visible, than now it is iconified.
9627 But x_make_frame_invisible clears both
9628 the visible flag and the iconified flag;
9629 and that way, we know the window is not iconified now. */
9630 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9632 f->async_iconified = 1;
9634 bufp->kind = iconify_event;
9635 XSETFRAME (bufp->frame_or_window, f);
9636 bufp->arg = Qnil;
9637 bufp++;
9638 count++;
9639 numchars--;
9642 goto OTHER;
9644 case MapNotify:
9645 if (event.xmap.window == tip_window)
9646 /* The tooltip has been drawn already. Avoid
9647 the SET_FRAME_GARBAGED below. */
9648 goto OTHER;
9650 /* We use x_top_window_to_frame because map events can
9651 come for sub-windows and they don't mean that the
9652 frame is visible. */
9653 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9654 if (f)
9656 f->async_visible = 1;
9657 f->async_iconified = 0;
9658 f->output_data.x->has_been_visible = 1;
9660 /* wait_reading_process_input will notice this and update
9661 the frame's display structures. */
9662 SET_FRAME_GARBAGED (f);
9664 if (f->iconified)
9666 bufp->kind = deiconify_event;
9667 XSETFRAME (bufp->frame_or_window, f);
9668 bufp->arg = Qnil;
9669 bufp++;
9670 count++;
9671 numchars--;
9673 else if (! NILP (Vframe_list)
9674 && ! NILP (XCDR (Vframe_list)))
9675 /* Force a redisplay sooner or later
9676 to update the frame titles
9677 in case this is the second frame. */
9678 record_asynch_buffer_change ();
9680 goto OTHER;
9682 case KeyPress:
9683 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9685 #ifdef USE_MOTIF
9686 /* I couldn't find a way to prevent LessTif scroll bars
9687 from consuming key events. */
9688 if (f == 0)
9690 Widget widget = XtWindowToWidget (dpyinfo->display,
9691 event.xkey.window);
9692 if (widget && XmIsScrollBar (widget))
9694 widget = XtParent (widget);
9695 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9698 #endif /* USE_MOTIF */
9700 if (f != 0)
9702 KeySym keysym, orig_keysym;
9703 /* al%imercury@uunet.uu.net says that making this 81
9704 instead of 80 fixed a bug whereby meta chars made
9705 his Emacs hang.
9707 It seems that some version of XmbLookupString has
9708 a bug of not returning XBufferOverflow in
9709 status_return even if the input is too long to
9710 fit in 81 bytes. So, we must prepare sufficient
9711 bytes for copy_buffer. 513 bytes (256 chars for
9712 two-byte character set) seems to be a faily good
9713 approximation. -- 2000.8.10 handa@etl.go.jp */
9714 unsigned char copy_buffer[513];
9715 unsigned char *copy_bufptr = copy_buffer;
9716 int copy_bufsiz = sizeof (copy_buffer);
9717 int modifiers;
9719 event.xkey.state
9720 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9721 extra_keyboard_modifiers);
9722 modifiers = event.xkey.state;
9724 /* This will have to go some day... */
9726 /* make_lispy_event turns chars into control chars.
9727 Don't do it here because XLookupString is too eager. */
9728 event.xkey.state &= ~ControlMask;
9729 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9730 | dpyinfo->super_mod_mask
9731 | dpyinfo->hyper_mod_mask
9732 | dpyinfo->alt_mod_mask);
9734 /* In case Meta is ComposeCharacter,
9735 clear its status. According to Markus Ehrnsperger
9736 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9737 this enables ComposeCharacter to work whether or
9738 not it is combined with Meta. */
9739 if (modifiers & dpyinfo->meta_mod_mask)
9740 bzero (&compose_status, sizeof (compose_status));
9742 #ifdef HAVE_X_I18N
9743 if (FRAME_XIC (f))
9745 Status status_return;
9747 nbytes = XmbLookupString (FRAME_XIC (f),
9748 &event.xkey, copy_bufptr,
9749 copy_bufsiz, &keysym,
9750 &status_return);
9751 if (status_return == XBufferOverflow)
9753 copy_bufsiz = nbytes + 1;
9754 copy_bufptr = (char *) alloca (copy_bufsiz);
9755 nbytes = XmbLookupString (FRAME_XIC (f),
9756 &event.xkey, copy_bufptr,
9757 copy_bufsiz, &keysym,
9758 &status_return);
9761 if (status_return == XLookupNone)
9762 break;
9763 else if (status_return == XLookupChars)
9765 keysym = NoSymbol;
9766 modifiers = 0;
9768 else if (status_return != XLookupKeySym
9769 && status_return != XLookupBoth)
9770 abort ();
9772 else
9773 nbytes = XLookupString (&event.xkey, copy_bufptr,
9774 copy_bufsiz, &keysym,
9775 &compose_status);
9776 #else
9777 nbytes = XLookupString (&event.xkey, copy_bufptr,
9778 copy_bufsiz, &keysym,
9779 &compose_status);
9780 #endif
9782 orig_keysym = keysym;
9784 if (numchars > 1)
9786 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9787 || keysym == XK_Delete
9788 #ifdef XK_ISO_Left_Tab
9789 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9790 #endif
9791 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9792 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9793 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9794 #ifdef HPUX
9795 /* This recognizes the "extended function keys".
9796 It seems there's no cleaner way.
9797 Test IsModifierKey to avoid handling mode_switch
9798 incorrectly. */
9799 || ((unsigned) (keysym) >= XK_Select
9800 && (unsigned)(keysym) < XK_KP_Space)
9801 #endif
9802 #ifdef XK_dead_circumflex
9803 || orig_keysym == XK_dead_circumflex
9804 #endif
9805 #ifdef XK_dead_grave
9806 || orig_keysym == XK_dead_grave
9807 #endif
9808 #ifdef XK_dead_tilde
9809 || orig_keysym == XK_dead_tilde
9810 #endif
9811 #ifdef XK_dead_diaeresis
9812 || orig_keysym == XK_dead_diaeresis
9813 #endif
9814 #ifdef XK_dead_macron
9815 || orig_keysym == XK_dead_macron
9816 #endif
9817 #ifdef XK_dead_degree
9818 || orig_keysym == XK_dead_degree
9819 #endif
9820 #ifdef XK_dead_acute
9821 || orig_keysym == XK_dead_acute
9822 #endif
9823 #ifdef XK_dead_cedilla
9824 || orig_keysym == XK_dead_cedilla
9825 #endif
9826 #ifdef XK_dead_breve
9827 || orig_keysym == XK_dead_breve
9828 #endif
9829 #ifdef XK_dead_ogonek
9830 || orig_keysym == XK_dead_ogonek
9831 #endif
9832 #ifdef XK_dead_caron
9833 || orig_keysym == XK_dead_caron
9834 #endif
9835 #ifdef XK_dead_doubleacute
9836 || orig_keysym == XK_dead_doubleacute
9837 #endif
9838 #ifdef XK_dead_abovedot
9839 || orig_keysym == XK_dead_abovedot
9840 #endif
9841 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9842 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9843 /* Any "vendor-specific" key is ok. */
9844 || (orig_keysym & (1 << 28)))
9845 && ! (IsModifierKey (orig_keysym)
9846 #ifndef HAVE_X11R5
9847 #ifdef XK_Mode_switch
9848 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9849 #endif
9850 #ifdef XK_Num_Lock
9851 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9852 #endif
9853 #endif /* not HAVE_X11R5 */
9856 if (temp_index == sizeof temp_buffer / sizeof (short))
9857 temp_index = 0;
9858 temp_buffer[temp_index++] = keysym;
9859 bufp->kind = non_ascii_keystroke;
9860 bufp->code = keysym;
9861 XSETFRAME (bufp->frame_or_window, f);
9862 bufp->arg = Qnil;
9863 bufp->modifiers
9864 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9865 modifiers);
9866 bufp->timestamp = event.xkey.time;
9867 bufp++;
9868 count++;
9869 numchars--;
9871 else if (numchars > nbytes)
9873 register int i;
9874 register int c;
9875 unsigned char *p, *pend;
9876 int nchars, len;
9878 for (i = 0; i < nbytes; i++)
9880 if (temp_index == (sizeof temp_buffer
9881 / sizeof (short)))
9882 temp_index = 0;
9883 temp_buffer[temp_index++] = copy_bufptr[i];
9886 if (/* If the event is not from XIM, */
9887 event.xkey.keycode != 0
9888 /* or the current locale doesn't request
9889 decoding of the intup data, ... */
9890 || coding.type == coding_type_raw_text
9891 || coding.type == coding_type_no_conversion)
9893 /* ... we can use the input data as is. */
9894 nchars = nbytes;
9896 else
9898 /* We have to decode the input data. */
9899 int require;
9900 unsigned char *p;
9902 require = decoding_buffer_size (&coding, nbytes);
9903 p = (unsigned char *) alloca (require);
9904 coding.mode |= CODING_MODE_LAST_BLOCK;
9905 decode_coding (&coding, copy_bufptr, p,
9906 nbytes, require);
9907 nbytes = coding.produced;
9908 nchars = coding.produced_char;
9909 copy_bufptr = p;
9912 /* Convert the input data to a sequence of
9913 character events. */
9914 for (i = 0; i < nbytes; i += len)
9916 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9917 nbytes - i, len);
9918 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9919 ? ascii_keystroke
9920 : multibyte_char_keystroke);
9921 bufp->code = c;
9922 XSETFRAME (bufp->frame_or_window, f);
9923 bufp->arg = Qnil;
9924 bufp->modifiers
9925 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9926 modifiers);
9927 bufp->timestamp = event.xkey.time;
9928 bufp++;
9931 count += nchars;
9932 numchars -= nchars;
9934 if (keysym == NoSymbol)
9935 break;
9937 else
9938 abort ();
9940 else
9941 abort ();
9943 #ifdef HAVE_X_I18N
9944 /* Don't dispatch this event since XtDispatchEvent calls
9945 XFilterEvent, and two calls in a row may freeze the
9946 client. */
9947 break;
9948 #else
9949 goto OTHER;
9950 #endif
9952 case KeyRelease:
9953 #ifdef HAVE_X_I18N
9954 /* Don't dispatch this event since XtDispatchEvent calls
9955 XFilterEvent, and two calls in a row may freeze the
9956 client. */
9957 break;
9958 #else
9959 goto OTHER;
9960 #endif
9962 /* Here's a possible interpretation of the whole
9963 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9964 you get a FocusIn event, you have to get a FocusOut
9965 event before you relinquish the focus. If you
9966 haven't received a FocusIn event, then a mere
9967 LeaveNotify is enough to free you. */
9969 case EnterNotify:
9971 int from_menu_bar_p = 0;
9973 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9975 #ifdef LESSTIF_VERSION
9976 /* When clicking outside of a menu bar popup to close
9977 it, we get a FocusIn/ EnterNotify sequence of
9978 events. The flag event.xcrossing.focus is not set
9979 in the EnterNotify event of that sequence because
9980 the focus is in the menu bar,
9981 event.xcrossing.window is the frame's X window.
9982 Unconditionally setting the focus frame to null in
9983 this case is not the right thing, because no event
9984 follows that could set the focus frame to the right
9985 value.
9987 This could be a LessTif bug, but I wasn't able to
9988 reproduce the behavior in a simple test program.
9990 (gerd, LessTif 0.88.1). */
9992 if (!event.xcrossing.focus
9993 && f
9994 && f->output_data.x->menubar_widget)
9996 Window focus;
9997 int revert;
9999 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10000 if (focus == XtWindow (f->output_data.x->menubar_widget))
10001 from_menu_bar_p = 1;
10003 #endif /* LESSTIF_VERSION */
10005 if (event.xcrossing.focus || from_menu_bar_p)
10007 /* Avoid nasty pop/raise loops. */
10008 if (f && (!(f->auto_raise)
10009 || !(f->auto_lower)
10010 || (event.xcrossing.time - enter_timestamp) > 500))
10012 x_new_focus_frame (dpyinfo, f);
10013 enter_timestamp = event.xcrossing.time;
10016 else if (f == dpyinfo->x_focus_frame)
10017 x_new_focus_frame (dpyinfo, 0);
10019 /* EnterNotify counts as mouse movement,
10020 so update things that depend on mouse position. */
10021 if (f && !f->output_data.x->busy_p)
10022 note_mouse_movement (f, &event.xmotion);
10023 goto OTHER;
10026 case FocusIn:
10027 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10028 if (event.xfocus.detail != NotifyPointer)
10029 dpyinfo->x_focus_event_frame = f;
10030 if (f)
10032 x_new_focus_frame (dpyinfo, f);
10034 /* Don't stop displaying the initial startup message
10035 for a switch-frame event we don't need. */
10036 if (GC_NILP (Vterminal_frame)
10037 && GC_CONSP (Vframe_list)
10038 && !GC_NILP (XCDR (Vframe_list)))
10040 bufp->kind = FOCUS_IN_EVENT;
10041 XSETFRAME (bufp->frame_or_window, f);
10042 bufp->arg = Qnil;
10043 ++bufp, ++count, --numchars;
10047 #ifdef HAVE_X_I18N
10048 if (f && FRAME_XIC (f))
10049 XSetICFocus (FRAME_XIC (f));
10050 #endif
10052 goto OTHER;
10054 case LeaveNotify:
10055 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10056 if (f)
10058 Lisp_Object frame;
10059 int from_menu_bar_p = 0;
10061 if (f == dpyinfo->mouse_face_mouse_frame)
10063 /* If we move outside the frame, then we're
10064 certainly no longer on any text in the frame. */
10065 clear_mouse_face (dpyinfo);
10066 dpyinfo->mouse_face_mouse_frame = 0;
10069 /* Generate a nil HELP_EVENT to cancel a help-echo.
10070 Do it only if there's something to cancel.
10071 Otherwise, the startup message is cleared when
10072 the mouse leaves the frame. */
10073 if (any_help_event_p)
10075 Lisp_Object frame;
10076 int n;
10078 XSETFRAME (frame, f);
10079 n = gen_help_event (bufp, numchars,
10080 Qnil, frame, Qnil, Qnil, 0);
10081 bufp += n, count += n, numchars -= n;
10084 #ifdef LESSTIF_VERSION
10085 /* Please see the comment at the start of the
10086 EnterNotify case. */
10087 if (!event.xcrossing.focus
10088 && f->output_data.x->menubar_widget)
10090 Window focus;
10091 int revert;
10092 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10093 if (focus == XtWindow (f->output_data.x->menubar_widget))
10094 from_menu_bar_p = 1;
10096 #endif /* LESSTIF_VERSION */
10098 if (event.xcrossing.focus || from_menu_bar_p)
10099 x_mouse_leave (dpyinfo);
10100 else
10102 if (f == dpyinfo->x_focus_event_frame)
10103 dpyinfo->x_focus_event_frame = 0;
10104 if (f == dpyinfo->x_focus_frame)
10105 x_new_focus_frame (dpyinfo, 0);
10108 goto OTHER;
10110 case FocusOut:
10111 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10112 if (event.xfocus.detail != NotifyPointer
10113 && f == dpyinfo->x_focus_event_frame)
10114 dpyinfo->x_focus_event_frame = 0;
10115 if (f && f == dpyinfo->x_focus_frame)
10116 x_new_focus_frame (dpyinfo, 0);
10118 #ifdef HAVE_X_I18N
10119 if (f && FRAME_XIC (f))
10120 XUnsetICFocus (FRAME_XIC (f));
10121 #endif
10123 goto OTHER;
10125 case MotionNotify:
10127 previous_help_echo = help_echo;
10128 help_echo = help_echo_object = help_echo_window = Qnil;
10129 help_echo_pos = -1;
10131 if (dpyinfo->grabbed && last_mouse_frame
10132 && FRAME_LIVE_P (last_mouse_frame))
10133 f = last_mouse_frame;
10134 else
10135 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10137 if (f)
10138 note_mouse_movement (f, &event.xmotion);
10139 else
10141 #ifndef USE_TOOLKIT_SCROLL_BARS
10142 struct scroll_bar *bar
10143 = x_window_to_scroll_bar (event.xmotion.window);
10145 if (bar)
10146 x_scroll_bar_note_movement (bar, &event);
10147 #endif /* USE_TOOLKIT_SCROLL_BARS */
10149 /* If we move outside the frame, then we're
10150 certainly no longer on any text in the frame. */
10151 clear_mouse_face (dpyinfo);
10154 /* If the contents of the global variable help_echo
10155 has changed, generate a HELP_EVENT. */
10156 if (!NILP (help_echo)
10157 || !NILP (previous_help_echo))
10159 Lisp_Object frame;
10160 int n;
10162 if (f)
10163 XSETFRAME (frame, f);
10164 else
10165 frame = Qnil;
10167 any_help_event_p = 1;
10168 n = gen_help_event (bufp, numchars, help_echo, frame,
10169 help_echo_window, help_echo_object,
10170 help_echo_pos);
10171 bufp += n, count += n, numchars -= n;
10174 goto OTHER;
10177 case ConfigureNotify:
10178 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10179 if (f)
10181 #ifndef USE_X_TOOLKIT
10182 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10183 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10185 /* In the toolkit version, change_frame_size
10186 is called by the code that handles resizing
10187 of the EmacsFrame widget. */
10189 /* Even if the number of character rows and columns has
10190 not changed, the font size may have changed, so we need
10191 to check the pixel dimensions as well. */
10192 if (columns != f->width
10193 || rows != f->height
10194 || event.xconfigure.width != f->output_data.x->pixel_width
10195 || event.xconfigure.height != f->output_data.x->pixel_height)
10197 change_frame_size (f, rows, columns, 0, 1, 0);
10198 SET_FRAME_GARBAGED (f);
10199 cancel_mouse_face (f);
10201 #endif
10203 f->output_data.x->pixel_width = event.xconfigure.width;
10204 f->output_data.x->pixel_height = event.xconfigure.height;
10206 /* What we have now is the position of Emacs's own window.
10207 Convert that to the position of the window manager window. */
10208 x_real_positions (f, &f->output_data.x->left_pos,
10209 &f->output_data.x->top_pos);
10211 #ifdef HAVE_X_I18N
10212 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10213 xic_set_statusarea (f);
10214 #endif
10216 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10218 /* Since the WM decorations come below top_pos now,
10219 we must put them below top_pos in the future. */
10220 f->output_data.x->win_gravity = NorthWestGravity;
10221 x_wm_set_size_hint (f, (long) 0, 0);
10223 #ifdef USE_MOTIF
10224 /* Some window managers pass (0,0) as the location of
10225 the window, and the Motif event handler stores it
10226 in the emacs widget, which messes up Motif menus. */
10227 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10229 event.xconfigure.x = f->output_data.x->widget->core.x;
10230 event.xconfigure.y = f->output_data.x->widget->core.y;
10232 #endif /* USE_MOTIF */
10234 goto OTHER;
10236 case ButtonPress:
10237 case ButtonRelease:
10239 /* If we decide we want to generate an event to be seen
10240 by the rest of Emacs, we put it here. */
10241 struct input_event emacs_event;
10242 int tool_bar_p = 0;
10244 emacs_event.kind = no_event;
10245 bzero (&compose_status, sizeof (compose_status));
10247 if (dpyinfo->grabbed
10248 && last_mouse_frame
10249 && FRAME_LIVE_P (last_mouse_frame))
10250 f = last_mouse_frame;
10251 else
10252 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10254 if (f)
10256 /* Is this in the tool-bar? */
10257 if (WINDOWP (f->tool_bar_window)
10258 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10260 Lisp_Object window;
10261 int p, x, y;
10263 x = event.xbutton.x;
10264 y = event.xbutton.y;
10266 /* Set x and y. */
10267 window = window_from_coordinates (f, x, y, &p, 1);
10268 if (EQ (window, f->tool_bar_window))
10270 x_handle_tool_bar_click (f, &event.xbutton);
10271 tool_bar_p = 1;
10275 if (!tool_bar_p)
10276 if (!dpyinfo->x_focus_frame
10277 || f == dpyinfo->x_focus_frame)
10278 construct_mouse_click (&emacs_event, &event, f);
10280 else
10282 #ifndef USE_TOOLKIT_SCROLL_BARS
10283 struct scroll_bar *bar
10284 = x_window_to_scroll_bar (event.xbutton.window);
10286 if (bar)
10287 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10288 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10291 if (event.type == ButtonPress)
10293 dpyinfo->grabbed |= (1 << event.xbutton.button);
10294 last_mouse_frame = f;
10295 /* Ignore any mouse motion that happened
10296 before this event; any subsequent mouse-movement
10297 Emacs events should reflect only motion after
10298 the ButtonPress. */
10299 if (f != 0)
10300 f->mouse_moved = 0;
10302 if (!tool_bar_p)
10303 last_tool_bar_item = -1;
10305 else
10307 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10310 if (numchars >= 1 && emacs_event.kind != no_event)
10312 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10313 bufp++;
10314 count++;
10315 numchars--;
10318 #ifdef USE_X_TOOLKIT
10319 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10320 /* For a down-event in the menu bar,
10321 don't pass it to Xt right now.
10322 Instead, save it away
10323 and we will pass it to Xt from kbd_buffer_get_event.
10324 That way, we can run some Lisp code first. */
10325 if (f && event.type == ButtonPress
10326 /* Verify the event is really within the menu bar
10327 and not just sent to it due to grabbing. */
10328 && event.xbutton.x >= 0
10329 && event.xbutton.x < f->output_data.x->pixel_width
10330 && event.xbutton.y >= 0
10331 && event.xbutton.y < f->output_data.x->menubar_height
10332 && event.xbutton.same_screen)
10334 SET_SAVED_BUTTON_EVENT;
10335 XSETFRAME (last_mouse_press_frame, f);
10337 else if (event.type == ButtonPress)
10339 last_mouse_press_frame = Qnil;
10340 goto OTHER;
10343 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10344 but I am trying to be cautious. */
10345 else if (event.type == ButtonRelease)
10347 if (!NILP (last_mouse_press_frame))
10349 f = XFRAME (last_mouse_press_frame);
10350 if (f->output_data.x)
10351 SET_SAVED_BUTTON_EVENT;
10353 else
10354 goto OTHER;
10356 #endif /* USE_MOTIF */
10357 else
10358 goto OTHER;
10359 #endif /* USE_X_TOOLKIT */
10361 break;
10363 case CirculateNotify:
10364 goto OTHER;
10366 case CirculateRequest:
10367 goto OTHER;
10369 case VisibilityNotify:
10370 goto OTHER;
10372 case MappingNotify:
10373 /* Someone has changed the keyboard mapping - update the
10374 local cache. */
10375 switch (event.xmapping.request)
10377 case MappingModifier:
10378 x_find_modifier_meanings (dpyinfo);
10379 /* This is meant to fall through. */
10380 case MappingKeyboard:
10381 XRefreshKeyboardMapping (&event.xmapping);
10383 goto OTHER;
10385 default:
10386 OTHER:
10387 #ifdef USE_X_TOOLKIT
10388 BLOCK_INPUT;
10389 XtDispatchEvent (&event);
10390 UNBLOCK_INPUT;
10391 #endif /* USE_X_TOOLKIT */
10392 break;
10397 out:;
10399 /* On some systems, an X bug causes Emacs to get no more events
10400 when the window is destroyed. Detect that. (1994.) */
10401 if (! event_found)
10403 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10404 One XNOOP in 100 loops will make Emacs terminate.
10405 B. Bretthauer, 1994 */
10406 x_noop_count++;
10407 if (x_noop_count >= 100)
10409 x_noop_count=0;
10411 if (next_noop_dpyinfo == 0)
10412 next_noop_dpyinfo = x_display_list;
10414 XNoOp (next_noop_dpyinfo->display);
10416 /* Each time we get here, cycle through the displays now open. */
10417 next_noop_dpyinfo = next_noop_dpyinfo->next;
10421 /* If the focus was just given to an auto-raising frame,
10422 raise it now. */
10423 /* ??? This ought to be able to handle more than one such frame. */
10424 if (pending_autoraise_frame)
10426 x_raise_frame (pending_autoraise_frame);
10427 pending_autoraise_frame = 0;
10430 UNBLOCK_INPUT;
10431 --handling_signal;
10432 return count;
10438 /***********************************************************************
10439 Text Cursor
10440 ***********************************************************************/
10442 /* Note if the text cursor of window W has been overwritten by a
10443 drawing operation that outputs N glyphs starting at HPOS in the
10444 line given by output_cursor.vpos. N < 0 means all the rest of the
10445 line after HPOS has been written. */
10447 static void
10448 note_overwritten_text_cursor (w, hpos, n)
10449 struct window *w;
10450 int hpos, n;
10452 if (updated_area == TEXT_AREA
10453 && output_cursor.vpos == w->phys_cursor.vpos
10454 && hpos <= w->phys_cursor.hpos
10455 && (n < 0
10456 || hpos + n > w->phys_cursor.hpos))
10457 w->phys_cursor_on_p = 0;
10461 /* Set clipping for output in glyph row ROW. W is the window in which
10462 we operate. GC is the graphics context to set clipping in.
10463 WHOLE_LINE_P non-zero means include the areas used for truncation
10464 mark display and alike in the clipping rectangle.
10466 ROW may be a text row or, e.g., a mode line. Text rows must be
10467 clipped to the interior of the window dedicated to text display,
10468 mode lines must be clipped to the whole window. */
10470 static void
10471 x_clip_to_row (w, row, gc, whole_line_p)
10472 struct window *w;
10473 struct glyph_row *row;
10474 GC gc;
10475 int whole_line_p;
10477 struct frame *f = XFRAME (WINDOW_FRAME (w));
10478 XRectangle clip_rect;
10479 int window_x, window_y, window_width, window_height;
10481 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10483 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10484 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10485 clip_rect.y = max (clip_rect.y, window_y);
10486 clip_rect.width = window_width;
10487 clip_rect.height = row->visible_height;
10489 /* If clipping to the whole line, including trunc marks, extend
10490 the rectangle to the left and increase its width. */
10491 if (whole_line_p)
10493 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10494 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10497 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10501 /* Draw a hollow box cursor on window W in glyph row ROW. */
10503 static void
10504 x_draw_hollow_cursor (w, row)
10505 struct window *w;
10506 struct glyph_row *row;
10508 struct frame *f = XFRAME (WINDOW_FRAME (w));
10509 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10510 Display *dpy = FRAME_X_DISPLAY (f);
10511 int x, y, wd, h;
10512 XGCValues xgcv;
10513 struct glyph *cursor_glyph;
10514 GC gc;
10516 /* Compute frame-relative coordinates from window-relative
10517 coordinates. */
10518 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10519 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10520 + row->ascent - w->phys_cursor_ascent);
10521 h = row->height - 1;
10523 /* Get the glyph the cursor is on. If we can't tell because
10524 the current matrix is invalid or such, give up. */
10525 cursor_glyph = get_phys_cursor_glyph (w);
10526 if (cursor_glyph == NULL)
10527 return;
10529 /* Compute the width of the rectangle to draw. If on a stretch
10530 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10531 rectangle as wide as the glyph, but use a canonical character
10532 width instead. */
10533 wd = cursor_glyph->pixel_width - 1;
10534 if (cursor_glyph->type == STRETCH_GLYPH
10535 && !x_stretch_cursor_p)
10536 wd = min (CANON_X_UNIT (f), wd);
10538 /* The foreground of cursor_gc is typically the same as the normal
10539 background color, which can cause the cursor box to be invisible. */
10540 xgcv.foreground = f->output_data.x->cursor_pixel;
10541 if (dpyinfo->scratch_cursor_gc)
10542 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10543 else
10544 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10545 GCForeground, &xgcv);
10546 gc = dpyinfo->scratch_cursor_gc;
10548 /* Set clipping, draw the rectangle, and reset clipping again. */
10549 x_clip_to_row (w, row, gc, 0);
10550 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10551 XSetClipMask (dpy, gc, None);
10555 /* Draw a bar cursor on window W in glyph row ROW.
10557 Implementation note: One would like to draw a bar cursor with an
10558 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10559 Unfortunately, I didn't find a font yet that has this property set.
10560 --gerd. */
10562 static void
10563 x_draw_bar_cursor (w, row, width)
10564 struct window *w;
10565 struct glyph_row *row;
10566 int width;
10568 struct frame *f = XFRAME (w->frame);
10569 struct glyph *cursor_glyph;
10570 GC gc;
10571 int x;
10572 unsigned long mask;
10573 XGCValues xgcv;
10574 Display *dpy;
10575 Window window;
10577 /* If cursor is out of bounds, don't draw garbage. This can happen
10578 in mini-buffer windows when switching between echo area glyphs
10579 and mini-buffer. */
10580 cursor_glyph = get_phys_cursor_glyph (w);
10581 if (cursor_glyph == NULL)
10582 return;
10584 /* If on an image, draw like a normal cursor. That's usually better
10585 visible than drawing a bar, esp. if the image is large so that
10586 the bar might not be in the window. */
10587 if (cursor_glyph->type == IMAGE_GLYPH)
10589 struct glyph_row *row;
10590 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10591 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10593 else
10595 xgcv.background = f->output_data.x->cursor_pixel;
10596 xgcv.foreground = f->output_data.x->cursor_pixel;
10597 xgcv.graphics_exposures = 0;
10598 mask = GCForeground | GCBackground | GCGraphicsExposures;
10599 dpy = FRAME_X_DISPLAY (f);
10600 window = FRAME_X_WINDOW (f);
10601 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10603 if (gc)
10604 XChangeGC (dpy, gc, mask, &xgcv);
10605 else
10607 gc = XCreateGC (dpy, window, mask, &xgcv);
10608 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10611 if (width < 0)
10612 width = f->output_data.x->cursor_width;
10614 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10615 x_clip_to_row (w, row, gc, 0);
10616 XFillRectangle (dpy, window, gc,
10618 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10619 min (cursor_glyph->pixel_width, width),
10620 row->height);
10621 XSetClipMask (dpy, gc, None);
10626 /* Clear the cursor of window W to background color, and mark the
10627 cursor as not shown. This is used when the text where the cursor
10628 is is about to be rewritten. */
10630 static void
10631 x_clear_cursor (w)
10632 struct window *w;
10634 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10635 x_update_window_cursor (w, 0);
10639 /* Draw the cursor glyph of window W in glyph row ROW. See the
10640 comment of x_draw_glyphs for the meaning of HL. */
10642 static void
10643 x_draw_phys_cursor_glyph (w, row, hl)
10644 struct window *w;
10645 struct glyph_row *row;
10646 enum draw_glyphs_face hl;
10648 /* If cursor hpos is out of bounds, don't draw garbage. This can
10649 happen in mini-buffer windows when switching between echo area
10650 glyphs and mini-buffer. */
10651 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10653 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10654 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10655 hl, 0, 0, 0);
10657 /* When we erase the cursor, and ROW is overlapped by other
10658 rows, make sure that these overlapping parts of other rows
10659 are redrawn. */
10660 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10662 if (row > w->current_matrix->rows
10663 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10664 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10666 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10667 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10668 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10674 /* Erase the image of a cursor of window W from the screen. */
10676 static void
10677 x_erase_phys_cursor (w)
10678 struct window *w;
10680 struct frame *f = XFRAME (w->frame);
10681 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10682 int hpos = w->phys_cursor.hpos;
10683 int vpos = w->phys_cursor.vpos;
10684 int mouse_face_here_p = 0;
10685 struct glyph_matrix *active_glyphs = w->current_matrix;
10686 struct glyph_row *cursor_row;
10687 struct glyph *cursor_glyph;
10688 enum draw_glyphs_face hl;
10690 /* No cursor displayed or row invalidated => nothing to do on the
10691 screen. */
10692 if (w->phys_cursor_type == NO_CURSOR)
10693 goto mark_cursor_off;
10695 /* VPOS >= active_glyphs->nrows means that window has been resized.
10696 Don't bother to erase the cursor. */
10697 if (vpos >= active_glyphs->nrows)
10698 goto mark_cursor_off;
10700 /* If row containing cursor is marked invalid, there is nothing we
10701 can do. */
10702 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10703 if (!cursor_row->enabled_p)
10704 goto mark_cursor_off;
10706 /* This can happen when the new row is shorter than the old one.
10707 In this case, either x_draw_glyphs or clear_end_of_line
10708 should have cleared the cursor. Note that we wouldn't be
10709 able to erase the cursor in this case because we don't have a
10710 cursor glyph at hand. */
10711 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10712 goto mark_cursor_off;
10714 /* If the cursor is in the mouse face area, redisplay that when
10715 we clear the cursor. */
10716 if (! NILP (dpyinfo->mouse_face_window)
10717 && w == XWINDOW (dpyinfo->mouse_face_window)
10718 && (vpos > dpyinfo->mouse_face_beg_row
10719 || (vpos == dpyinfo->mouse_face_beg_row
10720 && hpos >= dpyinfo->mouse_face_beg_col))
10721 && (vpos < dpyinfo->mouse_face_end_row
10722 || (vpos == dpyinfo->mouse_face_end_row
10723 && hpos < dpyinfo->mouse_face_end_col))
10724 /* Don't redraw the cursor's spot in mouse face if it is at the
10725 end of a line (on a newline). The cursor appears there, but
10726 mouse highlighting does not. */
10727 && cursor_row->used[TEXT_AREA] > hpos)
10728 mouse_face_here_p = 1;
10730 /* Maybe clear the display under the cursor. */
10731 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10733 int x;
10734 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10736 cursor_glyph = get_phys_cursor_glyph (w);
10737 if (cursor_glyph == NULL)
10738 goto mark_cursor_off;
10740 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10742 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10744 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10745 cursor_row->y)),
10746 cursor_glyph->pixel_width,
10747 cursor_row->visible_height,
10748 False);
10751 /* Erase the cursor by redrawing the character underneath it. */
10752 if (mouse_face_here_p)
10753 hl = DRAW_MOUSE_FACE;
10754 else if (cursor_row->inverse_p)
10755 hl = DRAW_INVERSE_VIDEO;
10756 else
10757 hl = DRAW_NORMAL_TEXT;
10758 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10760 mark_cursor_off:
10761 w->phys_cursor_on_p = 0;
10762 w->phys_cursor_type = NO_CURSOR;
10766 /* Display or clear cursor of window W. If ON is zero, clear the
10767 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10768 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10770 void
10771 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10772 struct window *w;
10773 int on, hpos, vpos, x, y;
10775 struct frame *f = XFRAME (w->frame);
10776 int new_cursor_type;
10777 int new_cursor_width;
10778 struct glyph_matrix *current_glyphs;
10779 struct glyph_row *glyph_row;
10780 struct glyph *glyph;
10782 /* This is pointless on invisible frames, and dangerous on garbaged
10783 windows and frames; in the latter case, the frame or window may
10784 be in the midst of changing its size, and x and y may be off the
10785 window. */
10786 if (! FRAME_VISIBLE_P (f)
10787 || FRAME_GARBAGED_P (f)
10788 || vpos >= w->current_matrix->nrows
10789 || hpos >= w->current_matrix->matrix_w)
10790 return;
10792 /* If cursor is off and we want it off, return quickly. */
10793 if (!on && !w->phys_cursor_on_p)
10794 return;
10796 current_glyphs = w->current_matrix;
10797 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10798 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10800 /* If cursor row is not enabled, we don't really know where to
10801 display the cursor. */
10802 if (!glyph_row->enabled_p)
10804 w->phys_cursor_on_p = 0;
10805 return;
10808 xassert (interrupt_input_blocked);
10810 /* Set new_cursor_type to the cursor we want to be displayed. In a
10811 mini-buffer window, we want the cursor only to appear if we are
10812 reading input from this window. For the selected window, we want
10813 the cursor type given by the frame parameter. If explicitly
10814 marked off, draw no cursor. In all other cases, we want a hollow
10815 box cursor. */
10816 new_cursor_width = -1;
10817 if (cursor_in_echo_area
10818 && FRAME_HAS_MINIBUF_P (f)
10819 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10821 if (w == XWINDOW (echo_area_window))
10822 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10823 else
10824 new_cursor_type = HOLLOW_BOX_CURSOR;
10826 else
10828 if (w != XWINDOW (selected_window)
10829 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10831 extern int cursor_in_non_selected_windows;
10833 if (MINI_WINDOW_P (w)
10834 || !cursor_in_non_selected_windows
10835 || NILP (XBUFFER (w->buffer)->cursor_type))
10836 new_cursor_type = NO_CURSOR;
10837 else
10838 new_cursor_type = HOLLOW_BOX_CURSOR;
10840 else if (w->cursor_off_p)
10841 new_cursor_type = NO_CURSOR;
10842 else
10844 struct buffer *b = XBUFFER (w->buffer);
10846 if (EQ (b->cursor_type, Qt))
10847 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10848 else
10849 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10850 &new_cursor_width);
10854 /* If cursor is currently being shown and we don't want it to be or
10855 it is in the wrong place, or the cursor type is not what we want,
10856 erase it. */
10857 if (w->phys_cursor_on_p
10858 && (!on
10859 || w->phys_cursor.x != x
10860 || w->phys_cursor.y != y
10861 || new_cursor_type != w->phys_cursor_type))
10862 x_erase_phys_cursor (w);
10864 /* If the cursor is now invisible and we want it to be visible,
10865 display it. */
10866 if (on && !w->phys_cursor_on_p)
10868 w->phys_cursor_ascent = glyph_row->ascent;
10869 w->phys_cursor_height = glyph_row->height;
10871 /* Set phys_cursor_.* before x_draw_.* is called because some
10872 of them may need the information. */
10873 w->phys_cursor.x = x;
10874 w->phys_cursor.y = glyph_row->y;
10875 w->phys_cursor.hpos = hpos;
10876 w->phys_cursor.vpos = vpos;
10877 w->phys_cursor_type = new_cursor_type;
10878 w->phys_cursor_on_p = 1;
10880 switch (new_cursor_type)
10882 case HOLLOW_BOX_CURSOR:
10883 x_draw_hollow_cursor (w, glyph_row);
10884 break;
10886 case FILLED_BOX_CURSOR:
10887 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10888 break;
10890 case BAR_CURSOR:
10891 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10892 break;
10894 case NO_CURSOR:
10895 break;
10897 default:
10898 abort ();
10901 #ifdef HAVE_X_I18N
10902 if (w == XWINDOW (f->selected_window))
10903 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10904 xic_set_preeditarea (w, x, y);
10905 #endif
10908 #ifndef XFlush
10909 if (updating_frame != f)
10910 XFlush (FRAME_X_DISPLAY (f));
10911 #endif
10915 /* Display the cursor on window W, or clear it. X and Y are window
10916 relative pixel coordinates. HPOS and VPOS are glyph matrix
10917 positions. If W is not the selected window, display a hollow
10918 cursor. ON non-zero means display the cursor at X, Y which
10919 correspond to HPOS, VPOS, otherwise it is cleared. */
10921 void
10922 x_display_cursor (w, on, hpos, vpos, x, y)
10923 struct window *w;
10924 int on, hpos, vpos, x, y;
10926 BLOCK_INPUT;
10927 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10928 UNBLOCK_INPUT;
10932 /* Display the cursor on window W, or clear it, according to ON_P.
10933 Don't change the cursor's position. */
10935 void
10936 x_update_cursor (f, on_p)
10937 struct frame *f;
10939 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10943 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10944 in the window tree rooted at W. */
10946 static void
10947 x_update_cursor_in_window_tree (w, on_p)
10948 struct window *w;
10949 int on_p;
10951 while (w)
10953 if (!NILP (w->hchild))
10954 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10955 else if (!NILP (w->vchild))
10956 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10957 else
10958 x_update_window_cursor (w, on_p);
10960 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10965 /* Switch the display of W's cursor on or off, according to the value
10966 of ON. */
10968 static void
10969 x_update_window_cursor (w, on)
10970 struct window *w;
10971 int on;
10973 /* Don't update cursor in windows whose frame is in the process
10974 of being deleted. */
10975 if (w->current_matrix)
10977 BLOCK_INPUT;
10978 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10979 w->phys_cursor.x, w->phys_cursor.y);
10980 UNBLOCK_INPUT;
10987 /* Icons. */
10989 /* Refresh bitmap kitchen sink icon for frame F
10990 when we get an expose event for it. */
10992 void
10993 refreshicon (f)
10994 struct frame *f;
10996 /* Normally, the window manager handles this function. */
10999 /* Make the x-window of frame F use the gnu icon bitmap. */
11002 x_bitmap_icon (f, file)
11003 struct frame *f;
11004 Lisp_Object file;
11006 int bitmap_id;
11008 if (FRAME_X_WINDOW (f) == 0)
11009 return 1;
11011 /* Free up our existing icon bitmap if any. */
11012 if (f->output_data.x->icon_bitmap > 0)
11013 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11014 f->output_data.x->icon_bitmap = 0;
11016 if (STRINGP (file))
11017 bitmap_id = x_create_bitmap_from_file (f, file);
11018 else
11020 /* Create the GNU bitmap if necessary. */
11021 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11022 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11023 = x_create_bitmap_from_data (f, gnu_bits,
11024 gnu_width, gnu_height);
11026 /* The first time we create the GNU bitmap,
11027 this increments the ref-count one extra time.
11028 As a result, the GNU bitmap is never freed.
11029 That way, we don't have to worry about allocating it again. */
11030 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11032 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11035 x_wm_set_icon_pixmap (f, bitmap_id);
11036 f->output_data.x->icon_bitmap = bitmap_id;
11038 return 0;
11042 /* Make the x-window of frame F use a rectangle with text.
11043 Use ICON_NAME as the text. */
11046 x_text_icon (f, icon_name)
11047 struct frame *f;
11048 char *icon_name;
11050 if (FRAME_X_WINDOW (f) == 0)
11051 return 1;
11053 #ifdef HAVE_X11R4
11055 XTextProperty text;
11056 text.value = (unsigned char *) icon_name;
11057 text.encoding = XA_STRING;
11058 text.format = 8;
11059 text.nitems = strlen (icon_name);
11060 #ifdef USE_X_TOOLKIT
11061 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11062 &text);
11063 #else /* not USE_X_TOOLKIT */
11064 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11065 #endif /* not USE_X_TOOLKIT */
11067 #else /* not HAVE_X11R4 */
11068 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11069 #endif /* not HAVE_X11R4 */
11071 if (f->output_data.x->icon_bitmap > 0)
11072 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11073 f->output_data.x->icon_bitmap = 0;
11074 x_wm_set_icon_pixmap (f, 0);
11076 return 0;
11079 #define X_ERROR_MESSAGE_SIZE 200
11081 /* If non-nil, this should be a string.
11082 It means catch X errors and store the error message in this string. */
11084 static Lisp_Object x_error_message_string;
11086 /* An X error handler which stores the error message in
11087 x_error_message_string. This is called from x_error_handler if
11088 x_catch_errors is in effect. */
11090 static void
11091 x_error_catcher (display, error)
11092 Display *display;
11093 XErrorEvent *error;
11095 XGetErrorText (display, error->error_code,
11096 XSTRING (x_error_message_string)->data,
11097 X_ERROR_MESSAGE_SIZE);
11100 /* Begin trapping X errors for display DPY. Actually we trap X errors
11101 for all displays, but DPY should be the display you are actually
11102 operating on.
11104 After calling this function, X protocol errors no longer cause
11105 Emacs to exit; instead, they are recorded in the string
11106 stored in x_error_message_string.
11108 Calling x_check_errors signals an Emacs error if an X error has
11109 occurred since the last call to x_catch_errors or x_check_errors.
11111 Calling x_uncatch_errors resumes the normal error handling. */
11113 void x_check_errors ();
11114 static Lisp_Object x_catch_errors_unwind ();
11117 x_catch_errors (dpy)
11118 Display *dpy;
11120 int count = specpdl_ptr - specpdl;
11122 /* Make sure any errors from previous requests have been dealt with. */
11123 XSync (dpy, False);
11125 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11127 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11128 XSTRING (x_error_message_string)->data[0] = 0;
11130 return count;
11133 /* Unbind the binding that we made to check for X errors. */
11135 static Lisp_Object
11136 x_catch_errors_unwind (old_val)
11137 Lisp_Object old_val;
11139 x_error_message_string = old_val;
11140 return Qnil;
11143 /* If any X protocol errors have arrived since the last call to
11144 x_catch_errors or x_check_errors, signal an Emacs error using
11145 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11147 void
11148 x_check_errors (dpy, format)
11149 Display *dpy;
11150 char *format;
11152 /* Make sure to catch any errors incurred so far. */
11153 XSync (dpy, False);
11155 if (XSTRING (x_error_message_string)->data[0])
11156 error (format, XSTRING (x_error_message_string)->data);
11159 /* Nonzero if we had any X protocol errors
11160 since we did x_catch_errors on DPY. */
11163 x_had_errors_p (dpy)
11164 Display *dpy;
11166 /* Make sure to catch any errors incurred so far. */
11167 XSync (dpy, False);
11169 return XSTRING (x_error_message_string)->data[0] != 0;
11172 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11174 void
11175 x_clear_errors (dpy)
11176 Display *dpy;
11178 XSTRING (x_error_message_string)->data[0] = 0;
11181 /* Stop catching X protocol errors and let them make Emacs die.
11182 DPY should be the display that was passed to x_catch_errors.
11183 COUNT should be the value that was returned by
11184 the corresponding call to x_catch_errors. */
11186 void
11187 x_uncatch_errors (dpy, count)
11188 Display *dpy;
11189 int count;
11191 unbind_to (count, Qnil);
11194 #if 0
11195 static unsigned int x_wire_count;
11196 x_trace_wire ()
11198 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11200 #endif /* ! 0 */
11203 /* Handle SIGPIPE, which can happen when the connection to a server
11204 simply goes away. SIGPIPE is handled by x_connection_signal.
11205 Don't need to do anything, because the write which caused the
11206 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11207 which will do the appropriate cleanup for us. */
11209 static SIGTYPE
11210 x_connection_signal (signalnum) /* If we don't have an argument, */
11211 int signalnum; /* some compilers complain in signal calls. */
11213 #ifdef USG
11214 /* USG systems forget handlers when they are used;
11215 must reestablish each time */
11216 signal (signalnum, x_connection_signal);
11217 #endif /* USG */
11220 /* Handling X errors. */
11222 /* Handle the loss of connection to display DISPLAY. */
11224 static SIGTYPE
11225 x_connection_closed (display, error_message)
11226 Display *display;
11227 char *error_message;
11229 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11230 Lisp_Object frame, tail;
11232 /* Indicate that this display is dead. */
11234 #if 0 /* Closing the display caused a bus error on OpenWindows. */
11235 #ifdef USE_X_TOOLKIT
11236 XtCloseDisplay (display);
11237 #endif
11238 #endif
11240 if (dpyinfo)
11241 dpyinfo->display = 0;
11243 /* First delete frames whose mini-buffers are on frames
11244 that are on the dead display. */
11245 FOR_EACH_FRAME (tail, frame)
11247 Lisp_Object minibuf_frame;
11248 minibuf_frame
11249 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11250 if (FRAME_X_P (XFRAME (frame))
11251 && FRAME_X_P (XFRAME (minibuf_frame))
11252 && ! EQ (frame, minibuf_frame)
11253 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11254 Fdelete_frame (frame, Qt);
11257 /* Now delete all remaining frames on the dead display.
11258 We are now sure none of these is used as the mini-buffer
11259 for another frame that we need to delete. */
11260 FOR_EACH_FRAME (tail, frame)
11261 if (FRAME_X_P (XFRAME (frame))
11262 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11264 /* Set this to t so that Fdelete_frame won't get confused
11265 trying to find a replacement. */
11266 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11267 Fdelete_frame (frame, Qt);
11270 if (dpyinfo)
11271 x_delete_display (dpyinfo);
11273 if (x_display_list == 0)
11275 fprintf (stderr, "%s\n", error_message);
11276 shut_down_emacs (0, 0, Qnil);
11277 exit (70);
11280 /* Ordinary stack unwind doesn't deal with these. */
11281 #ifdef SIGIO
11282 sigunblock (sigmask (SIGIO));
11283 #endif
11284 sigunblock (sigmask (SIGALRM));
11285 TOTALLY_UNBLOCK_INPUT;
11287 clear_waiting_for_input ();
11288 handling_signal = 0;
11289 error ("%s", error_message);
11292 /* This is the usual handler for X protocol errors.
11293 It kills all frames on the display that we got the error for.
11294 If that was the only one, it prints an error message and kills Emacs. */
11296 static void
11297 x_error_quitter (display, error)
11298 Display *display;
11299 XErrorEvent *error;
11301 char buf[256], buf1[356];
11303 /* Note that there is no real way portable across R3/R4 to get the
11304 original error handler. */
11306 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11307 sprintf (buf1, "X protocol error: %s on protocol request %d",
11308 buf, error->request_code);
11309 x_connection_closed (display, buf1);
11312 /* This is the first-level handler for X protocol errors.
11313 It calls x_error_quitter or x_error_catcher. */
11315 static int
11316 x_error_handler (display, error)
11317 Display *display;
11318 XErrorEvent *error;
11320 if (! NILP (x_error_message_string))
11321 x_error_catcher (display, error);
11322 else
11323 x_error_quitter (display, error);
11324 return 0;
11327 /* This is the handler for X IO errors, always.
11328 It kills all frames on the display that we lost touch with.
11329 If that was the only one, it prints an error message and kills Emacs. */
11331 static int
11332 x_io_error_quitter (display)
11333 Display *display;
11335 char buf[256];
11337 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11338 x_connection_closed (display, buf);
11339 return 0;
11342 /* Changing the font of the frame. */
11344 /* Give frame F the font named FONTNAME as its default font, and
11345 return the full name of that font. FONTNAME may be a wildcard
11346 pattern; in that case, we choose some font that fits the pattern.
11347 The return value shows which font we chose. */
11349 Lisp_Object
11350 x_new_font (f, fontname)
11351 struct frame *f;
11352 register char *fontname;
11354 struct font_info *fontp
11355 = FS_LOAD_FONT (f, 0, fontname, -1);
11357 if (!fontp)
11358 return Qnil;
11360 f->output_data.x->font = (XFontStruct *) (fontp->font);
11361 f->output_data.x->baseline_offset = fontp->baseline_offset;
11362 f->output_data.x->fontset = -1;
11364 /* Compute the scroll bar width in character columns. */
11365 if (f->scroll_bar_pixel_width > 0)
11367 int wid = FONT_WIDTH (f->output_data.x->font);
11368 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11370 else
11372 int wid = FONT_WIDTH (f->output_data.x->font);
11373 f->scroll_bar_cols = (14 + wid - 1) / wid;
11376 /* Now make the frame display the given font. */
11377 if (FRAME_X_WINDOW (f) != 0)
11379 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11380 f->output_data.x->font->fid);
11381 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11382 f->output_data.x->font->fid);
11383 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11384 f->output_data.x->font->fid);
11386 frame_update_line_height (f);
11387 x_set_window_size (f, 0, f->width, f->height);
11389 else
11390 /* If we are setting a new frame's font for the first time,
11391 there are no faces yet, so this font's height is the line height. */
11392 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11394 return build_string (fontp->full_name);
11397 /* Give frame F the fontset named FONTSETNAME as its default font, and
11398 return the full name of that fontset. FONTSETNAME may be a wildcard
11399 pattern; in that case, we choose some fontset that fits the pattern.
11400 The return value shows which fontset we chose. */
11402 Lisp_Object
11403 x_new_fontset (f, fontsetname)
11404 struct frame *f;
11405 char *fontsetname;
11407 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11408 Lisp_Object result;
11410 if (fontset < 0)
11411 return Qnil;
11413 if (f->output_data.x->fontset == fontset)
11414 /* This fontset is already set in frame F. There's nothing more
11415 to do. */
11416 return fontset_name (fontset);
11418 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11420 if (!STRINGP (result))
11421 /* Can't load ASCII font. */
11422 return Qnil;
11424 /* Since x_new_font doesn't update any fontset information, do it now. */
11425 f->output_data.x->fontset = fontset;
11427 #ifdef HAVE_X_I18N
11428 if (FRAME_XIC (f)
11429 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11430 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11431 #endif
11433 return build_string (fontsetname);
11437 /***********************************************************************
11438 X Input Methods
11439 ***********************************************************************/
11441 #ifdef HAVE_X_I18N
11443 #ifdef HAVE_X11R6
11445 /* XIM destroy callback function, which is called whenever the
11446 connection to input method XIM dies. CLIENT_DATA contains a
11447 pointer to the x_display_info structure corresponding to XIM. */
11449 static void
11450 xim_destroy_callback (xim, client_data, call_data)
11451 XIM xim;
11452 XPointer client_data;
11453 XPointer call_data;
11455 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11456 Lisp_Object frame, tail;
11458 BLOCK_INPUT;
11460 /* No need to call XDestroyIC.. */
11461 FOR_EACH_FRAME (tail, frame)
11463 struct frame *f = XFRAME (frame);
11464 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11466 FRAME_XIC (f) = NULL;
11467 if (FRAME_XIC_FONTSET (f))
11469 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11470 FRAME_XIC_FONTSET (f) = NULL;
11475 /* No need to call XCloseIM. */
11476 dpyinfo->xim = NULL;
11477 XFree (dpyinfo->xim_styles);
11478 UNBLOCK_INPUT;
11481 #endif /* HAVE_X11R6 */
11483 /* Open the connection to the XIM server on display DPYINFO.
11484 RESOURCE_NAME is the resource name Emacs uses. */
11486 static void
11487 xim_open_dpy (dpyinfo, resource_name)
11488 struct x_display_info *dpyinfo;
11489 char *resource_name;
11491 #ifdef USE_XIM
11492 XIM xim;
11494 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11495 dpyinfo->xim = xim;
11497 if (xim)
11499 #ifdef HAVE_X11R6
11500 XIMCallback destroy;
11501 #endif
11503 /* Get supported styles and XIM values. */
11504 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11506 #ifdef HAVE_X11R6
11507 destroy.callback = xim_destroy_callback;
11508 destroy.client_data = (XPointer)dpyinfo;
11509 /* This isn't prptotyped in OSF 5.0. */
11510 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11511 #endif
11514 #else /* not USE_XIM */
11515 dpyinfo->xim = NULL;
11516 #endif /* not USE_XIM */
11520 #ifdef HAVE_X11R6_XIM
11522 struct xim_inst_t
11524 struct x_display_info *dpyinfo;
11525 char *resource_name;
11528 /* XIM instantiate callback function, which is called whenever an XIM
11529 server is available. DISPLAY is teh display of the XIM.
11530 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11531 when the callback was registered. */
11533 static void
11534 xim_instantiate_callback (display, client_data, call_data)
11535 Display *display;
11536 XPointer client_data;
11537 XPointer call_data;
11539 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11540 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11542 /* We don't support multiple XIM connections. */
11543 if (dpyinfo->xim)
11544 return;
11546 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11548 /* Create XIC for the existing frames on the same display, as long
11549 as they have no XIC. */
11550 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11552 Lisp_Object tail, frame;
11554 BLOCK_INPUT;
11555 FOR_EACH_FRAME (tail, frame)
11557 struct frame *f = XFRAME (frame);
11559 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11560 if (FRAME_XIC (f) == NULL)
11562 create_frame_xic (f);
11563 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11564 xic_set_statusarea (f);
11565 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11567 struct window *w = XWINDOW (f->selected_window);
11568 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11573 UNBLOCK_INPUT;
11577 #endif /* HAVE_X11R6_XIM */
11580 /* Open a connection to the XIM server on display DPYINFO.
11581 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11582 connection only at the first time. On X11R6, open the connection
11583 in the XIM instantiate callback function. */
11585 static void
11586 xim_initialize (dpyinfo, resource_name)
11587 struct x_display_info *dpyinfo;
11588 char *resource_name;
11590 #ifdef USE_XIM
11591 #ifdef HAVE_X11R6_XIM
11592 struct xim_inst_t *xim_inst;
11593 int len;
11595 dpyinfo->xim = NULL;
11596 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11597 xim_inst->dpyinfo = dpyinfo;
11598 len = strlen (resource_name);
11599 xim_inst->resource_name = (char *) xmalloc (len + 1);
11600 bcopy (resource_name, xim_inst->resource_name, len + 1);
11601 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11602 resource_name, EMACS_CLASS,
11603 xim_instantiate_callback,
11604 /* Fixme: This is XPointer in
11605 XFree86 but (XPointer *) on
11606 Tru64, at least. */
11607 (XPointer) xim_inst);
11608 #else /* not HAVE_X11R6_XIM */
11609 dpyinfo->xim = NULL;
11610 xim_open_dpy (dpyinfo, resource_name);
11611 #endif /* not HAVE_X11R6_XIM */
11613 #else /* not USE_XIM */
11614 dpyinfo->xim = NULL;
11615 #endif /* not USE_XIM */
11619 /* Close the connection to the XIM server on display DPYINFO. */
11621 static void
11622 xim_close_dpy (dpyinfo)
11623 struct x_display_info *dpyinfo;
11625 #ifdef USE_XIM
11626 #ifdef HAVE_X11R6_XIM
11627 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11628 NULL, EMACS_CLASS,
11629 xim_instantiate_callback, NULL);
11630 #endif /* not HAVE_X11R6_XIM */
11631 XCloseIM (dpyinfo->xim);
11632 dpyinfo->xim = NULL;
11633 XFree (dpyinfo->xim_styles);
11634 #endif /* USE_XIM */
11637 #endif /* not HAVE_X11R6_XIM */
11641 /* Calculate the absolute position in frame F
11642 from its current recorded position values and gravity. */
11644 void
11645 x_calc_absolute_position (f)
11646 struct frame *f;
11648 Window child;
11649 int win_x = 0, win_y = 0;
11650 int flags = f->output_data.x->size_hint_flags;
11651 int this_window;
11653 /* We have nothing to do if the current position
11654 is already for the top-left corner. */
11655 if (! ((flags & XNegative) || (flags & YNegative)))
11656 return;
11658 #ifdef USE_X_TOOLKIT
11659 this_window = XtWindow (f->output_data.x->widget);
11660 #else
11661 this_window = FRAME_X_WINDOW (f);
11662 #endif
11664 /* Find the position of the outside upper-left corner of
11665 the inner window, with respect to the outer window.
11666 But do this only if we will need the results. */
11667 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11669 int count;
11671 BLOCK_INPUT;
11672 count = x_catch_errors (FRAME_X_DISPLAY (f));
11673 while (1)
11675 x_clear_errors (FRAME_X_DISPLAY (f));
11676 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11678 /* From-window, to-window. */
11679 this_window,
11680 f->output_data.x->parent_desc,
11682 /* From-position, to-position. */
11683 0, 0, &win_x, &win_y,
11685 /* Child of win. */
11686 &child);
11687 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11689 Window newroot, newparent = 0xdeadbeef;
11690 Window *newchildren;
11691 unsigned int nchildren;
11693 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11694 &newparent, &newchildren, &nchildren))
11695 break;
11697 XFree ((char *) newchildren);
11699 f->output_data.x->parent_desc = newparent;
11701 else
11702 break;
11705 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11706 UNBLOCK_INPUT;
11709 /* Treat negative positions as relative to the leftmost bottommost
11710 position that fits on the screen. */
11711 if (flags & XNegative)
11712 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11713 - 2 * f->output_data.x->border_width - win_x
11714 - PIXEL_WIDTH (f)
11715 + f->output_data.x->left_pos);
11717 if (flags & YNegative)
11719 int menubar_height = 0;
11721 #ifdef USE_X_TOOLKIT
11722 if (f->output_data.x->menubar_widget)
11723 menubar_height
11724 = (f->output_data.x->menubar_widget->core.height
11725 + f->output_data.x->menubar_widget->core.border_width);
11726 #endif
11728 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11729 - 2 * f->output_data.x->border_width
11730 - win_y
11731 - PIXEL_HEIGHT (f)
11732 - menubar_height
11733 + f->output_data.x->top_pos);
11736 /* The left_pos and top_pos
11737 are now relative to the top and left screen edges,
11738 so the flags should correspond. */
11739 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11742 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11743 to really change the position, and 0 when calling from
11744 x_make_frame_visible (in that case, XOFF and YOFF are the current
11745 position values). It is -1 when calling from x_set_frame_parameters,
11746 which means, do adjust for borders but don't change the gravity. */
11748 void
11749 x_set_offset (f, xoff, yoff, change_gravity)
11750 struct frame *f;
11751 register int xoff, yoff;
11752 int change_gravity;
11754 int modified_top, modified_left;
11756 if (change_gravity > 0)
11758 f->output_data.x->top_pos = yoff;
11759 f->output_data.x->left_pos = xoff;
11760 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11761 if (xoff < 0)
11762 f->output_data.x->size_hint_flags |= XNegative;
11763 if (yoff < 0)
11764 f->output_data.x->size_hint_flags |= YNegative;
11765 f->output_data.x->win_gravity = NorthWestGravity;
11767 x_calc_absolute_position (f);
11769 BLOCK_INPUT;
11770 x_wm_set_size_hint (f, (long) 0, 0);
11772 modified_left = f->output_data.x->left_pos;
11773 modified_top = f->output_data.x->top_pos;
11774 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11775 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11776 /* It is a mystery why we need to add the border_width here
11777 when the frame is already visible, but experiment says we do. */
11778 if (change_gravity != 0)
11780 modified_left += f->output_data.x->border_width;
11781 modified_top += f->output_data.x->border_width;
11783 #endif
11785 #ifdef USE_X_TOOLKIT
11786 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11787 modified_left, modified_top);
11788 #else /* not USE_X_TOOLKIT */
11789 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11790 modified_left, modified_top);
11791 #endif /* not USE_X_TOOLKIT */
11792 UNBLOCK_INPUT;
11795 /* Call this to change the size of frame F's x-window.
11796 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11797 for this size change and subsequent size changes.
11798 Otherwise we leave the window gravity unchanged. */
11800 void
11801 x_set_window_size (f, change_gravity, cols, rows)
11802 struct frame *f;
11803 int change_gravity;
11804 int cols, rows;
11806 #ifndef USE_X_TOOLKIT
11807 int pixelwidth, pixelheight;
11808 #endif
11810 BLOCK_INPUT;
11812 #ifdef USE_X_TOOLKIT
11814 /* The x and y position of the widget is clobbered by the
11815 call to XtSetValues within EmacsFrameSetCharSize.
11816 This is a real kludge, but I don't understand Xt so I can't
11817 figure out a correct fix. Can anyone else tell me? -- rms. */
11818 int xpos = f->output_data.x->widget->core.x;
11819 int ypos = f->output_data.x->widget->core.y;
11820 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11821 f->output_data.x->widget->core.x = xpos;
11822 f->output_data.x->widget->core.y = ypos;
11825 #else /* not USE_X_TOOLKIT */
11827 check_frame_size (f, &rows, &cols);
11828 f->output_data.x->vertical_scroll_bar_extra
11829 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11831 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11832 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11833 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11834 f->output_data.x->flags_areas_extra
11835 = FRAME_FLAGS_AREA_WIDTH (f);
11836 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11837 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11839 f->output_data.x->win_gravity = NorthWestGravity;
11840 x_wm_set_size_hint (f, (long) 0, 0);
11842 XSync (FRAME_X_DISPLAY (f), False);
11843 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11844 pixelwidth, pixelheight);
11846 /* Now, strictly speaking, we can't be sure that this is accurate,
11847 but the window manager will get around to dealing with the size
11848 change request eventually, and we'll hear how it went when the
11849 ConfigureNotify event gets here.
11851 We could just not bother storing any of this information here,
11852 and let the ConfigureNotify event set everything up, but that
11853 might be kind of confusing to the Lisp code, since size changes
11854 wouldn't be reported in the frame parameters until some random
11855 point in the future when the ConfigureNotify event arrives.
11857 We pass 1 for DELAY since we can't run Lisp code inside of
11858 a BLOCK_INPUT. */
11859 change_frame_size (f, rows, cols, 0, 1, 0);
11860 PIXEL_WIDTH (f) = pixelwidth;
11861 PIXEL_HEIGHT (f) = pixelheight;
11863 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11864 receive in the ConfigureNotify event; if we get what we asked
11865 for, then the event won't cause the screen to become garbaged, so
11866 we have to make sure to do it here. */
11867 SET_FRAME_GARBAGED (f);
11869 XFlush (FRAME_X_DISPLAY (f));
11871 #endif /* not USE_X_TOOLKIT */
11873 /* If cursor was outside the new size, mark it as off. */
11874 mark_window_cursors_off (XWINDOW (f->root_window));
11876 /* Clear out any recollection of where the mouse highlighting was,
11877 since it might be in a place that's outside the new frame size.
11878 Actually checking whether it is outside is a pain in the neck,
11879 so don't try--just let the highlighting be done afresh with new size. */
11880 cancel_mouse_face (f);
11882 UNBLOCK_INPUT;
11885 /* Mouse warping. */
11887 void
11888 x_set_mouse_position (f, x, y)
11889 struct frame *f;
11890 int x, y;
11892 int pix_x, pix_y;
11894 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11895 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11897 if (pix_x < 0) pix_x = 0;
11898 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11900 if (pix_y < 0) pix_y = 0;
11901 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11903 BLOCK_INPUT;
11905 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11906 0, 0, 0, 0, pix_x, pix_y);
11907 UNBLOCK_INPUT;
11910 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11912 void
11913 x_set_mouse_pixel_position (f, pix_x, pix_y)
11914 struct frame *f;
11915 int pix_x, pix_y;
11917 BLOCK_INPUT;
11919 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11920 0, 0, 0, 0, pix_x, pix_y);
11921 UNBLOCK_INPUT;
11924 /* focus shifting, raising and lowering. */
11926 void
11927 x_focus_on_frame (f)
11928 struct frame *f;
11930 #if 0 /* This proves to be unpleasant. */
11931 x_raise_frame (f);
11932 #endif
11933 #if 0
11934 /* I don't think that the ICCCM allows programs to do things like this
11935 without the interaction of the window manager. Whatever you end up
11936 doing with this code, do it to x_unfocus_frame too. */
11937 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11938 RevertToPointerRoot, CurrentTime);
11939 #endif /* ! 0 */
11942 void
11943 x_unfocus_frame (f)
11944 struct frame *f;
11946 #if 0
11947 /* Look at the remarks in x_focus_on_frame. */
11948 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11949 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11950 RevertToPointerRoot, CurrentTime);
11951 #endif /* ! 0 */
11954 /* Raise frame F. */
11956 void
11957 x_raise_frame (f)
11958 struct frame *f;
11960 if (f->async_visible)
11962 BLOCK_INPUT;
11963 #ifdef USE_X_TOOLKIT
11964 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11965 #else /* not USE_X_TOOLKIT */
11966 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11967 #endif /* not USE_X_TOOLKIT */
11968 XFlush (FRAME_X_DISPLAY (f));
11969 UNBLOCK_INPUT;
11973 /* Lower frame F. */
11975 void
11976 x_lower_frame (f)
11977 struct frame *f;
11979 if (f->async_visible)
11981 BLOCK_INPUT;
11982 #ifdef USE_X_TOOLKIT
11983 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11984 #else /* not USE_X_TOOLKIT */
11985 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11986 #endif /* not USE_X_TOOLKIT */
11987 XFlush (FRAME_X_DISPLAY (f));
11988 UNBLOCK_INPUT;
11992 static void
11993 XTframe_raise_lower (f, raise_flag)
11994 FRAME_PTR f;
11995 int raise_flag;
11997 if (raise_flag)
11998 x_raise_frame (f);
11999 else
12000 x_lower_frame (f);
12003 /* Change of visibility. */
12005 /* This tries to wait until the frame is really visible.
12006 However, if the window manager asks the user where to position
12007 the frame, this will return before the user finishes doing that.
12008 The frame will not actually be visible at that time,
12009 but it will become visible later when the window manager
12010 finishes with it. */
12012 void
12013 x_make_frame_visible (f)
12014 struct frame *f;
12016 Lisp_Object type;
12017 int original_top, original_left;
12018 int retry_count = 2;
12020 retry:
12022 BLOCK_INPUT;
12024 type = x_icon_type (f);
12025 if (!NILP (type))
12026 x_bitmap_icon (f, type);
12028 if (! FRAME_VISIBLE_P (f))
12030 /* We test FRAME_GARBAGED_P here to make sure we don't
12031 call x_set_offset a second time
12032 if we get to x_make_frame_visible a second time
12033 before the window gets really visible. */
12034 if (! FRAME_ICONIFIED_P (f)
12035 && ! f->output_data.x->asked_for_visible)
12036 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12038 f->output_data.x->asked_for_visible = 1;
12040 if (! EQ (Vx_no_window_manager, Qt))
12041 x_wm_set_window_state (f, NormalState);
12042 #ifdef USE_X_TOOLKIT
12043 /* This was XtPopup, but that did nothing for an iconified frame. */
12044 XtMapWidget (f->output_data.x->widget);
12045 #else /* not USE_X_TOOLKIT */
12046 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12047 #endif /* not USE_X_TOOLKIT */
12048 #if 0 /* This seems to bring back scroll bars in the wrong places
12049 if the window configuration has changed. They seem
12050 to come back ok without this. */
12051 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12052 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12053 #endif
12056 XFlush (FRAME_X_DISPLAY (f));
12058 /* Synchronize to ensure Emacs knows the frame is visible
12059 before we do anything else. We do this loop with input not blocked
12060 so that incoming events are handled. */
12062 Lisp_Object frame;
12063 int count;
12064 /* This must be before UNBLOCK_INPUT
12065 since events that arrive in response to the actions above
12066 will set it when they are handled. */
12067 int previously_visible = f->output_data.x->has_been_visible;
12069 original_left = f->output_data.x->left_pos;
12070 original_top = f->output_data.x->top_pos;
12072 /* This must come after we set COUNT. */
12073 UNBLOCK_INPUT;
12075 /* We unblock here so that arriving X events are processed. */
12077 /* Now move the window back to where it was "supposed to be".
12078 But don't do it if the gravity is negative.
12079 When the gravity is negative, this uses a position
12080 that is 3 pixels too low. Perhaps that's really the border width.
12082 Don't do this if the window has never been visible before,
12083 because the window manager may choose the position
12084 and we don't want to override it. */
12086 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12087 && f->output_data.x->win_gravity == NorthWestGravity
12088 && previously_visible)
12090 Drawable rootw;
12091 int x, y;
12092 unsigned int width, height, border, depth;
12094 BLOCK_INPUT;
12096 /* On some window managers (such as FVWM) moving an existing
12097 window, even to the same place, causes the window manager
12098 to introduce an offset. This can cause the window to move
12099 to an unexpected location. Check the geometry (a little
12100 slow here) and then verify that the window is in the right
12101 place. If the window is not in the right place, move it
12102 there, and take the potential window manager hit. */
12103 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12104 &rootw, &x, &y, &width, &height, &border, &depth);
12106 if (original_left != x || original_top != y)
12107 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12108 original_left, original_top);
12110 UNBLOCK_INPUT;
12113 XSETFRAME (frame, f);
12115 /* Wait until the frame is visible. Process X events until a
12116 MapNotify event has been seen, or until we think we won't get a
12117 MapNotify at all.. */
12118 for (count = input_signal_count + 10;
12119 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12121 /* Force processing of queued events. */
12122 x_sync (f);
12124 /* Machines that do polling rather than SIGIO have been
12125 observed to go into a busy-wait here. So we'll fake an
12126 alarm signal to let the handler know that there's something
12127 to be read. We used to raise a real alarm, but it seems
12128 that the handler isn't always enabled here. This is
12129 probably a bug. */
12130 if (input_polling_used ())
12132 /* It could be confusing if a real alarm arrives while
12133 processing the fake one. Turn it off and let the
12134 handler reset it. */
12135 extern void poll_for_input_1 P_ ((void));
12136 int old_poll_suppress_count = poll_suppress_count;
12137 poll_suppress_count = 1;
12138 poll_for_input_1 ();
12139 poll_suppress_count = old_poll_suppress_count;
12142 /* See if a MapNotify event has been processed. */
12143 FRAME_SAMPLE_VISIBILITY (f);
12146 /* 2000-09-28: In
12148 (let ((f (selected-frame)))
12149 (iconify-frame f)
12150 (raise-frame f))
12152 the frame is not raised with various window managers on
12153 FreeBSD, Linux and Solaris. It turns out that, for some
12154 unknown reason, the call to XtMapWidget is completely ignored.
12155 Mapping the widget a second time works. */
12157 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12158 goto retry;
12162 /* Change from mapped state to withdrawn state. */
12164 /* Make the frame visible (mapped and not iconified). */
12166 void
12167 x_make_frame_invisible (f)
12168 struct frame *f;
12170 Window window;
12172 #ifdef USE_X_TOOLKIT
12173 /* Use the frame's outermost window, not the one we normally draw on. */
12174 window = XtWindow (f->output_data.x->widget);
12175 #else /* not USE_X_TOOLKIT */
12176 window = FRAME_X_WINDOW (f);
12177 #endif /* not USE_X_TOOLKIT */
12179 /* Don't keep the highlight on an invisible frame. */
12180 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12181 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12183 #if 0/* This might add unreliability; I don't trust it -- rms. */
12184 if (! f->async_visible && ! f->async_iconified)
12185 return;
12186 #endif
12188 BLOCK_INPUT;
12190 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12191 that the current position of the window is user-specified, rather than
12192 program-specified, so that when the window is mapped again, it will be
12193 placed at the same location, without forcing the user to position it
12194 by hand again (they have already done that once for this window.) */
12195 x_wm_set_size_hint (f, (long) 0, 1);
12197 #ifdef HAVE_X11R4
12199 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12200 DefaultScreen (FRAME_X_DISPLAY (f))))
12202 UNBLOCK_INPUT_RESIGNAL;
12203 error ("Can't notify window manager of window withdrawal");
12205 #else /* ! defined (HAVE_X11R4) */
12207 /* Tell the window manager what we're going to do. */
12208 if (! EQ (Vx_no_window_manager, Qt))
12210 XEvent unmap;
12212 unmap.xunmap.type = UnmapNotify;
12213 unmap.xunmap.window = window;
12214 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12215 unmap.xunmap.from_configure = False;
12216 if (! XSendEvent (FRAME_X_DISPLAY (f),
12217 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12218 False,
12219 SubstructureRedirectMaskSubstructureNotifyMask,
12220 &unmap))
12222 UNBLOCK_INPUT_RESIGNAL;
12223 error ("Can't notify window manager of withdrawal");
12227 /* Unmap the window ourselves. Cheeky! */
12228 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12229 #endif /* ! defined (HAVE_X11R4) */
12231 /* We can't distinguish this from iconification
12232 just by the event that we get from the server.
12233 So we can't win using the usual strategy of letting
12234 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12235 and synchronize with the server to make sure we agree. */
12236 f->visible = 0;
12237 FRAME_ICONIFIED_P (f) = 0;
12238 f->async_visible = 0;
12239 f->async_iconified = 0;
12241 x_sync (f);
12243 UNBLOCK_INPUT;
12246 /* Change window state from mapped to iconified. */
12248 void
12249 x_iconify_frame (f)
12250 struct frame *f;
12252 int result;
12253 Lisp_Object type;
12255 /* Don't keep the highlight on an invisible frame. */
12256 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12257 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12259 if (f->async_iconified)
12260 return;
12262 BLOCK_INPUT;
12264 FRAME_SAMPLE_VISIBILITY (f);
12266 type = x_icon_type (f);
12267 if (!NILP (type))
12268 x_bitmap_icon (f, type);
12270 #ifdef USE_X_TOOLKIT
12272 if (! FRAME_VISIBLE_P (f))
12274 if (! EQ (Vx_no_window_manager, Qt))
12275 x_wm_set_window_state (f, IconicState);
12276 /* This was XtPopup, but that did nothing for an iconified frame. */
12277 XtMapWidget (f->output_data.x->widget);
12278 /* The server won't give us any event to indicate
12279 that an invisible frame was changed to an icon,
12280 so we have to record it here. */
12281 f->iconified = 1;
12282 f->visible = 1;
12283 f->async_iconified = 1;
12284 f->async_visible = 0;
12285 UNBLOCK_INPUT;
12286 return;
12289 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12290 XtWindow (f->output_data.x->widget),
12291 DefaultScreen (FRAME_X_DISPLAY (f)));
12292 UNBLOCK_INPUT;
12294 if (!result)
12295 error ("Can't notify window manager of iconification");
12297 f->async_iconified = 1;
12298 f->async_visible = 0;
12301 BLOCK_INPUT;
12302 XFlush (FRAME_X_DISPLAY (f));
12303 UNBLOCK_INPUT;
12304 #else /* not USE_X_TOOLKIT */
12306 /* Make sure the X server knows where the window should be positioned,
12307 in case the user deiconifies with the window manager. */
12308 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12309 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12311 /* Since we don't know which revision of X we're running, we'll use both
12312 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12314 /* X11R4: send a ClientMessage to the window manager using the
12315 WM_CHANGE_STATE type. */
12317 XEvent message;
12319 message.xclient.window = FRAME_X_WINDOW (f);
12320 message.xclient.type = ClientMessage;
12321 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12322 message.xclient.format = 32;
12323 message.xclient.data.l[0] = IconicState;
12325 if (! XSendEvent (FRAME_X_DISPLAY (f),
12326 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12327 False,
12328 SubstructureRedirectMask | SubstructureNotifyMask,
12329 &message))
12331 UNBLOCK_INPUT_RESIGNAL;
12332 error ("Can't notify window manager of iconification");
12336 /* X11R3: set the initial_state field of the window manager hints to
12337 IconicState. */
12338 x_wm_set_window_state (f, IconicState);
12340 if (!FRAME_VISIBLE_P (f))
12342 /* If the frame was withdrawn, before, we must map it. */
12343 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12346 f->async_iconified = 1;
12347 f->async_visible = 0;
12349 XFlush (FRAME_X_DISPLAY (f));
12350 UNBLOCK_INPUT;
12351 #endif /* not USE_X_TOOLKIT */
12354 /* Destroy the X window of frame F. */
12356 void
12357 x_destroy_window (f)
12358 struct frame *f;
12360 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12362 BLOCK_INPUT;
12364 /* If a display connection is dead, don't try sending more
12365 commands to the X server. */
12366 if (dpyinfo->display != 0)
12368 if (f->output_data.x->icon_desc != 0)
12369 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12370 #ifdef HAVE_X_I18N
12371 if (FRAME_XIC (f))
12372 free_frame_xic (f);
12373 #endif
12374 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
12375 #ifdef USE_X_TOOLKIT
12376 if (f->output_data.x->widget)
12377 XtDestroyWidget (f->output_data.x->widget);
12378 free_frame_menubar (f);
12379 #endif /* USE_X_TOOLKIT */
12381 unload_color (f, f->output_data.x->foreground_pixel);
12382 unload_color (f, f->output_data.x->background_pixel);
12383 unload_color (f, f->output_data.x->cursor_pixel);
12384 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12385 unload_color (f, f->output_data.x->border_pixel);
12386 unload_color (f, f->output_data.x->mouse_pixel);
12387 if (f->output_data.x->scroll_bar_background_pixel != -1)
12388 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12389 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12390 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12391 if (f->output_data.x->white_relief.allocated_p)
12392 unload_color (f, f->output_data.x->white_relief.pixel);
12393 if (f->output_data.x->black_relief.allocated_p)
12394 unload_color (f, f->output_data.x->black_relief.pixel);
12396 free_frame_faces (f);
12397 XFlush (FRAME_X_DISPLAY (f));
12400 if (f->output_data.x->saved_menu_event)
12401 xfree (f->output_data.x->saved_menu_event);
12403 xfree (f->output_data.x);
12404 f->output_data.x = 0;
12405 if (f == dpyinfo->x_focus_frame)
12406 dpyinfo->x_focus_frame = 0;
12407 if (f == dpyinfo->x_focus_event_frame)
12408 dpyinfo->x_focus_event_frame = 0;
12409 if (f == dpyinfo->x_highlight_frame)
12410 dpyinfo->x_highlight_frame = 0;
12412 dpyinfo->reference_count--;
12414 if (f == dpyinfo->mouse_face_mouse_frame)
12416 dpyinfo->mouse_face_beg_row
12417 = dpyinfo->mouse_face_beg_col = -1;
12418 dpyinfo->mouse_face_end_row
12419 = dpyinfo->mouse_face_end_col = -1;
12420 dpyinfo->mouse_face_window = Qnil;
12421 dpyinfo->mouse_face_deferred_gc = 0;
12422 dpyinfo->mouse_face_mouse_frame = 0;
12425 UNBLOCK_INPUT;
12428 /* Setting window manager hints. */
12430 /* Set the normal size hints for the window manager, for frame F.
12431 FLAGS is the flags word to use--or 0 meaning preserve the flags
12432 that the window now has.
12433 If USER_POSITION is nonzero, we set the USPosition
12434 flag (this is useful when FLAGS is 0). */
12436 void
12437 x_wm_set_size_hint (f, flags, user_position)
12438 struct frame *f;
12439 long flags;
12440 int user_position;
12442 XSizeHints size_hints;
12444 #ifdef USE_X_TOOLKIT
12445 Arg al[2];
12446 int ac = 0;
12447 Dimension widget_width, widget_height;
12448 Window window = XtWindow (f->output_data.x->widget);
12449 #else /* not USE_X_TOOLKIT */
12450 Window window = FRAME_X_WINDOW (f);
12451 #endif /* not USE_X_TOOLKIT */
12453 /* Setting PMaxSize caused various problems. */
12454 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12456 size_hints.x = f->output_data.x->left_pos;
12457 size_hints.y = f->output_data.x->top_pos;
12459 #ifdef USE_X_TOOLKIT
12460 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12461 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12462 XtGetValues (f->output_data.x->widget, al, ac);
12463 size_hints.height = widget_height;
12464 size_hints.width = widget_width;
12465 #else /* not USE_X_TOOLKIT */
12466 size_hints.height = PIXEL_HEIGHT (f);
12467 size_hints.width = PIXEL_WIDTH (f);
12468 #endif /* not USE_X_TOOLKIT */
12470 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12471 size_hints.height_inc = f->output_data.x->line_height;
12472 size_hints.max_width
12473 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12474 size_hints.max_height
12475 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12477 /* Calculate the base and minimum sizes.
12479 (When we use the X toolkit, we don't do it here.
12480 Instead we copy the values that the widgets are using, below.) */
12481 #ifndef USE_X_TOOLKIT
12483 int base_width, base_height;
12484 int min_rows = 0, min_cols = 0;
12486 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12487 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12489 check_frame_size (f, &min_rows, &min_cols);
12491 /* The window manager uses the base width hints to calculate the
12492 current number of rows and columns in the frame while
12493 resizing; min_width and min_height aren't useful for this
12494 purpose, since they might not give the dimensions for a
12495 zero-row, zero-column frame.
12497 We use the base_width and base_height members if we have
12498 them; otherwise, we set the min_width and min_height members
12499 to the size for a zero x zero frame. */
12501 #ifdef HAVE_X11R4
12502 size_hints.flags |= PBaseSize;
12503 size_hints.base_width = base_width;
12504 size_hints.base_height = base_height;
12505 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12506 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12507 #else
12508 size_hints.min_width = base_width;
12509 size_hints.min_height = base_height;
12510 #endif
12513 /* If we don't need the old flags, we don't need the old hint at all. */
12514 if (flags)
12516 size_hints.flags |= flags;
12517 goto no_read;
12519 #endif /* not USE_X_TOOLKIT */
12522 XSizeHints hints; /* Sometimes I hate X Windows... */
12523 long supplied_return;
12524 int value;
12526 #ifdef HAVE_X11R4
12527 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12528 &supplied_return);
12529 #else
12530 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12531 #endif
12533 #ifdef USE_X_TOOLKIT
12534 size_hints.base_height = hints.base_height;
12535 size_hints.base_width = hints.base_width;
12536 size_hints.min_height = hints.min_height;
12537 size_hints.min_width = hints.min_width;
12538 #endif
12540 if (flags)
12541 size_hints.flags |= flags;
12542 else
12544 if (value == 0)
12545 hints.flags = 0;
12546 if (hints.flags & PSize)
12547 size_hints.flags |= PSize;
12548 if (hints.flags & PPosition)
12549 size_hints.flags |= PPosition;
12550 if (hints.flags & USPosition)
12551 size_hints.flags |= USPosition;
12552 if (hints.flags & USSize)
12553 size_hints.flags |= USSize;
12557 #ifndef USE_X_TOOLKIT
12558 no_read:
12559 #endif
12561 #ifdef PWinGravity
12562 size_hints.win_gravity = f->output_data.x->win_gravity;
12563 size_hints.flags |= PWinGravity;
12565 if (user_position)
12567 size_hints.flags &= ~ PPosition;
12568 size_hints.flags |= USPosition;
12570 #endif /* PWinGravity */
12572 #ifdef HAVE_X11R4
12573 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12574 #else
12575 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12576 #endif
12579 /* Used for IconicState or NormalState */
12581 void
12582 x_wm_set_window_state (f, state)
12583 struct frame *f;
12584 int state;
12586 #ifdef USE_X_TOOLKIT
12587 Arg al[1];
12589 XtSetArg (al[0], XtNinitialState, state);
12590 XtSetValues (f->output_data.x->widget, al, 1);
12591 #else /* not USE_X_TOOLKIT */
12592 Window window = FRAME_X_WINDOW (f);
12594 f->output_data.x->wm_hints.flags |= StateHint;
12595 f->output_data.x->wm_hints.initial_state = state;
12597 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12598 #endif /* not USE_X_TOOLKIT */
12601 void
12602 x_wm_set_icon_pixmap (f, pixmap_id)
12603 struct frame *f;
12604 int pixmap_id;
12606 Pixmap icon_pixmap;
12608 #ifndef USE_X_TOOLKIT
12609 Window window = FRAME_X_WINDOW (f);
12610 #endif
12612 if (pixmap_id > 0)
12614 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12615 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12617 else
12619 /* It seems there is no way to turn off use of an icon pixmap.
12620 The following line does it, only if no icon has yet been created,
12621 for some window managers. But with mwm it crashes.
12622 Some people say it should clear the IconPixmapHint bit in this case,
12623 but that doesn't work, and the X consortium said it isn't the
12624 right thing at all. Since there is no way to win,
12625 best to explicitly give up. */
12626 #if 0
12627 f->output_data.x->wm_hints.icon_pixmap = None;
12628 #else
12629 return;
12630 #endif
12633 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12636 Arg al[1];
12637 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12638 XtSetValues (f->output_data.x->widget, al, 1);
12641 #else /* not USE_X_TOOLKIT */
12643 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12644 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12646 #endif /* not USE_X_TOOLKIT */
12649 void
12650 x_wm_set_icon_position (f, icon_x, icon_y)
12651 struct frame *f;
12652 int icon_x, icon_y;
12654 #ifdef USE_X_TOOLKIT
12655 Window window = XtWindow (f->output_data.x->widget);
12656 #else
12657 Window window = FRAME_X_WINDOW (f);
12658 #endif
12660 f->output_data.x->wm_hints.flags |= IconPositionHint;
12661 f->output_data.x->wm_hints.icon_x = icon_x;
12662 f->output_data.x->wm_hints.icon_y = icon_y;
12664 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12668 /***********************************************************************
12669 Fonts
12670 ***********************************************************************/
12672 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12674 struct font_info *
12675 x_get_font_info (f, font_idx)
12676 FRAME_PTR f;
12677 int font_idx;
12679 return (FRAME_X_FONT_TABLE (f) + font_idx);
12683 /* Return a list of names of available fonts matching PATTERN on frame
12684 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12685 to be listed. Frame F NULL means we have not yet created any
12686 frame on X, and consult the first display in x_display_list.
12687 MAXNAMES sets a limit on how many fonts to match. */
12689 Lisp_Object
12690 x_list_fonts (f, pattern, size, maxnames)
12691 FRAME_PTR f;
12692 Lisp_Object pattern;
12693 int size;
12694 int maxnames;
12696 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12697 Lisp_Object tem, second_best;
12698 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12699 int try_XLoadQueryFont = 0;
12700 int count;
12702 patterns = Fassoc (pattern, Valternate_fontname_alist);
12703 if (NILP (patterns))
12704 patterns = Fcons (pattern, Qnil);
12706 if (maxnames == 1 && !size)
12707 /* We can return any single font matching PATTERN. */
12708 try_XLoadQueryFont = 1;
12710 for (; CONSP (patterns); patterns = XCDR (patterns))
12712 int num_fonts;
12713 char **names = NULL;
12715 pattern = XCAR (patterns);
12716 /* See if we cached the result for this particular query.
12717 The cache is an alist of the form:
12718 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12720 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12721 key = Fcons (pattern, make_number (maxnames)),
12722 !NILP (list = Fassoc (key, tem))))
12724 list = Fcdr_safe (list);
12725 /* We have a cashed list. Don't have to get the list again. */
12726 goto label_cached;
12729 /* At first, put PATTERN in the cache. */
12731 BLOCK_INPUT;
12732 count = x_catch_errors (dpy);
12734 if (try_XLoadQueryFont)
12736 XFontStruct *font;
12737 unsigned long value;
12739 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12740 if (x_had_errors_p (dpy))
12742 /* This error is perhaps due to insufficient memory on X
12743 server. Let's just ignore it. */
12744 font = NULL;
12745 x_clear_errors (dpy);
12748 if (font
12749 && XGetFontProperty (font, XA_FONT, &value))
12751 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12752 int len = strlen (name);
12753 char *tmp;
12755 /* If DXPC (a Differential X Protocol Compressor)
12756 Ver.3.7 is running, XGetAtomName will return null
12757 string. We must avoid such a name. */
12758 if (len == 0)
12759 try_XLoadQueryFont = 0;
12760 else
12762 num_fonts = 1;
12763 names = (char **) alloca (sizeof (char *));
12764 /* Some systems only allow alloca assigned to a
12765 simple var. */
12766 tmp = (char *) alloca (len + 1); names[0] = tmp;
12767 bcopy (name, names[0], len + 1);
12768 XFree (name);
12771 else
12772 try_XLoadQueryFont = 0;
12774 if (font)
12775 XFreeFont (dpy, font);
12778 if (!try_XLoadQueryFont)
12780 /* We try at least 10 fonts because XListFonts will return
12781 auto-scaled fonts at the head. */
12782 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12783 &num_fonts);
12784 if (x_had_errors_p (dpy))
12786 /* This error is perhaps due to insufficient memory on X
12787 server. Let's just ignore it. */
12788 names = NULL;
12789 x_clear_errors (dpy);
12793 x_uncatch_errors (dpy, count);
12794 UNBLOCK_INPUT;
12796 if (names)
12798 int i;
12800 /* Make a list of all the fonts we got back.
12801 Store that in the font cache for the display. */
12802 for (i = 0; i < num_fonts; i++)
12804 int width = 0;
12805 char *p = names[i];
12806 int average_width = -1, dashes = 0;
12808 /* Count the number of dashes in NAMES[I]. If there are
12809 14 dashes, and the field value following 12th dash
12810 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12811 is usually too ugly to be used for editing. Let's
12812 ignore it. */
12813 while (*p)
12814 if (*p++ == '-')
12816 dashes++;
12817 if (dashes == 7) /* PIXEL_SIZE field */
12818 width = atoi (p);
12819 else if (dashes == 12) /* AVERAGE_WIDTH field */
12820 average_width = atoi (p);
12822 if (dashes < 14 || average_width != 0)
12824 tem = build_string (names[i]);
12825 if (NILP (Fassoc (tem, list)))
12827 if (STRINGP (Vx_pixel_size_width_font_regexp)
12828 && ((fast_c_string_match_ignore_case
12829 (Vx_pixel_size_width_font_regexp, names[i]))
12830 >= 0))
12831 /* We can set the value of PIXEL_SIZE to the
12832 width of this font. */
12833 list = Fcons (Fcons (tem, make_number (width)), list);
12834 else
12835 /* For the moment, width is not known. */
12836 list = Fcons (Fcons (tem, Qnil), list);
12840 if (!try_XLoadQueryFont)
12841 XFreeFontNames (names);
12844 /* Now store the result in the cache. */
12845 if (f != NULL)
12846 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12847 = Fcons (Fcons (key, list),
12848 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12850 label_cached:
12851 if (NILP (list)) continue; /* Try the remaining alternatives. */
12853 newlist = second_best = Qnil;
12854 /* Make a list of the fonts that have the right width. */
12855 for (; CONSP (list); list = XCDR (list))
12857 int found_size;
12859 tem = XCAR (list);
12861 if (!CONSP (tem) || NILP (XCAR (tem)))
12862 continue;
12863 if (!size)
12865 newlist = Fcons (XCAR (tem), newlist);
12866 continue;
12869 if (!INTEGERP (XCDR (tem)))
12871 /* Since we have not yet known the size of this font, we
12872 must try slow function call XLoadQueryFont. */
12873 XFontStruct *thisinfo;
12875 BLOCK_INPUT;
12876 count = x_catch_errors (dpy);
12877 thisinfo = XLoadQueryFont (dpy,
12878 XSTRING (XCAR (tem))->data);
12879 if (x_had_errors_p (dpy))
12881 /* This error is perhaps due to insufficient memory on X
12882 server. Let's just ignore it. */
12883 thisinfo = NULL;
12884 x_clear_errors (dpy);
12886 x_uncatch_errors (dpy, count);
12887 UNBLOCK_INPUT;
12889 if (thisinfo)
12891 XCDR (tem)
12892 = (thisinfo->min_bounds.width == 0
12893 ? make_number (0)
12894 : make_number (thisinfo->max_bounds.width));
12895 XFreeFont (dpy, thisinfo);
12897 else
12898 /* For unknown reason, the previous call of XListFont had
12899 returned a font which can't be opened. Record the size
12900 as 0 not to try to open it again. */
12901 XCDR (tem) = make_number (0);
12904 found_size = XINT (XCDR (tem));
12905 if (found_size == size)
12906 newlist = Fcons (XCAR (tem), newlist);
12907 else if (found_size > 0)
12909 if (NILP (second_best))
12910 second_best = tem;
12911 else if (found_size < size)
12913 if (XINT (XCDR (second_best)) > size
12914 || XINT (XCDR (second_best)) < found_size)
12915 second_best = tem;
12917 else
12919 if (XINT (XCDR (second_best)) > size
12920 && XINT (XCDR (second_best)) > found_size)
12921 second_best = tem;
12925 if (!NILP (newlist))
12926 break;
12927 else if (!NILP (second_best))
12929 newlist = Fcons (XCAR (second_best), Qnil);
12930 break;
12934 return newlist;
12938 #if GLYPH_DEBUG
12940 /* Check that FONT is valid on frame F. It is if it can be found in F's
12941 font table. */
12943 static void
12944 x_check_font (f, font)
12945 struct frame *f;
12946 XFontStruct *font;
12948 int i;
12949 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12951 xassert (font != NULL);
12953 for (i = 0; i < dpyinfo->n_fonts; i++)
12954 if (dpyinfo->font_table[i].name
12955 && font == dpyinfo->font_table[i].font)
12956 break;
12958 xassert (i < dpyinfo->n_fonts);
12961 #endif /* GLYPH_DEBUG != 0 */
12963 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12964 Note: There are (broken) X fonts out there with invalid XFontStruct
12965 min_bounds contents. For example, handa@etl.go.jp reports that
12966 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12967 have font->min_bounds.width == 0. */
12969 static INLINE void
12970 x_font_min_bounds (font, w, h)
12971 XFontStruct *font;
12972 int *w, *h;
12974 *h = FONT_HEIGHT (font);
12975 *w = font->min_bounds.width;
12977 /* Try to handle the case where FONT->min_bounds has invalid
12978 contents. Since the only font known to have invalid min_bounds
12979 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12980 if (*w <= 0)
12981 *w = font->max_bounds.width;
12985 /* Compute the smallest character width and smallest font height over
12986 all fonts available on frame F. Set the members smallest_char_width
12987 and smallest_font_height in F's x_display_info structure to
12988 the values computed. Value is non-zero if smallest_font_height or
12989 smallest_char_width become smaller than they were before. */
12991 static int
12992 x_compute_min_glyph_bounds (f)
12993 struct frame *f;
12995 int i;
12996 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12997 XFontStruct *font;
12998 int old_width = dpyinfo->smallest_char_width;
12999 int old_height = dpyinfo->smallest_font_height;
13001 dpyinfo->smallest_font_height = 100000;
13002 dpyinfo->smallest_char_width = 100000;
13004 for (i = 0; i < dpyinfo->n_fonts; ++i)
13005 if (dpyinfo->font_table[i].name)
13007 struct font_info *fontp = dpyinfo->font_table + i;
13008 int w, h;
13010 font = (XFontStruct *) fontp->font;
13011 xassert (font != (XFontStruct *) ~0);
13012 x_font_min_bounds (font, &w, &h);
13014 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13015 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13018 xassert (dpyinfo->smallest_char_width > 0
13019 && dpyinfo->smallest_font_height > 0);
13021 return (dpyinfo->n_fonts == 1
13022 || dpyinfo->smallest_char_width < old_width
13023 || dpyinfo->smallest_font_height < old_height);
13027 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13028 pointer to the structure font_info while allocating it dynamically.
13029 If SIZE is 0, load any size of font.
13030 If loading is failed, return NULL. */
13032 struct font_info *
13033 x_load_font (f, fontname, size)
13034 struct frame *f;
13035 register char *fontname;
13036 int size;
13038 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13039 Lisp_Object font_names;
13040 int count;
13042 /* Get a list of all the fonts that match this name. Once we
13043 have a list of matching fonts, we compare them against the fonts
13044 we already have by comparing names. */
13045 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13047 if (!NILP (font_names))
13049 Lisp_Object tail;
13050 int i;
13052 for (i = 0; i < dpyinfo->n_fonts; i++)
13053 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13054 if (dpyinfo->font_table[i].name
13055 && (!strcmp (dpyinfo->font_table[i].name,
13056 XSTRING (XCAR (tail))->data)
13057 || !strcmp (dpyinfo->font_table[i].full_name,
13058 XSTRING (XCAR (tail))->data)))
13059 return (dpyinfo->font_table + i);
13062 /* Load the font and add it to the table. */
13064 char *full_name;
13065 XFontStruct *font;
13066 struct font_info *fontp;
13067 unsigned long value;
13068 int i;
13070 /* If we have found fonts by x_list_font, load one of them. If
13071 not, we still try to load a font by the name given as FONTNAME
13072 because XListFonts (called in x_list_font) of some X server has
13073 a bug of not finding a font even if the font surely exists and
13074 is loadable by XLoadQueryFont. */
13075 if (size > 0 && !NILP (font_names))
13076 fontname = (char *) XSTRING (XCAR (font_names))->data;
13078 BLOCK_INPUT;
13079 count = x_catch_errors (FRAME_X_DISPLAY (f));
13080 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13081 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13083 /* This error is perhaps due to insufficient memory on X
13084 server. Let's just ignore it. */
13085 font = NULL;
13086 x_clear_errors (FRAME_X_DISPLAY (f));
13088 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13089 UNBLOCK_INPUT;
13090 if (!font)
13091 return NULL;
13093 /* Find a free slot in the font table. */
13094 for (i = 0; i < dpyinfo->n_fonts; ++i)
13095 if (dpyinfo->font_table[i].name == NULL)
13096 break;
13098 /* If no free slot found, maybe enlarge the font table. */
13099 if (i == dpyinfo->n_fonts
13100 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13102 int sz;
13103 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13104 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13105 dpyinfo->font_table
13106 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13109 fontp = dpyinfo->font_table + i;
13110 if (i == dpyinfo->n_fonts)
13111 ++dpyinfo->n_fonts;
13113 /* Now fill in the slots of *FONTP. */
13114 BLOCK_INPUT;
13115 fontp->font = font;
13116 fontp->font_idx = i;
13117 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13118 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13120 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13121 full_name = 0;
13122 if (XGetFontProperty (font, XA_FONT, &value))
13124 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13125 char *p = name;
13126 int dashes = 0;
13128 /* Count the number of dashes in the "full name".
13129 If it is too few, this isn't really the font's full name,
13130 so don't use it.
13131 In X11R4, the fonts did not come with their canonical names
13132 stored in them. */
13133 while (*p)
13135 if (*p == '-')
13136 dashes++;
13137 p++;
13140 if (dashes >= 13)
13142 full_name = (char *) xmalloc (p - name + 1);
13143 bcopy (name, full_name, p - name + 1);
13146 XFree (name);
13149 if (full_name != 0)
13150 fontp->full_name = full_name;
13151 else
13152 fontp->full_name = fontp->name;
13154 fontp->size = font->max_bounds.width;
13155 fontp->height = FONT_HEIGHT (font);
13157 /* For some font, ascent and descent in max_bounds field is
13158 larger than the above value. */
13159 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
13160 if (max_height > fontp->height)
13161 fontp->height = max_height;
13164 if (NILP (font_names))
13166 /* We come here because of a bug of XListFonts mentioned at
13167 the head of this block. Let's store this information in
13168 the cache for x_list_fonts. */
13169 Lisp_Object lispy_name = build_string (fontname);
13170 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13172 XCDR (dpyinfo->name_list_element)
13173 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
13174 Fcons (Fcons (lispy_full_name,
13175 make_number (fontp->size)),
13176 Qnil)),
13177 XCDR (dpyinfo->name_list_element));
13178 if (full_name)
13179 XCDR (dpyinfo->name_list_element)
13180 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13181 Fcons (Fcons (lispy_full_name,
13182 make_number (fontp->size)),
13183 Qnil)),
13184 XCDR (dpyinfo->name_list_element));
13187 /* The slot `encoding' specifies how to map a character
13188 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13189 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13190 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13191 2:0xA020..0xFF7F). For the moment, we don't know which charset
13192 uses this font. So, we set information in fontp->encoding[1]
13193 which is never used by any charset. If mapping can't be
13194 decided, set FONT_ENCODING_NOT_DECIDED. */
13195 fontp->encoding[1]
13196 = (font->max_byte1 == 0
13197 /* 1-byte font */
13198 ? (font->min_char_or_byte2 < 0x80
13199 ? (font->max_char_or_byte2 < 0x80
13200 ? 0 /* 0x20..0x7F */
13201 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13202 : 1) /* 0xA0..0xFF */
13203 /* 2-byte font */
13204 : (font->min_byte1 < 0x80
13205 ? (font->max_byte1 < 0x80
13206 ? (font->min_char_or_byte2 < 0x80
13207 ? (font->max_char_or_byte2 < 0x80
13208 ? 0 /* 0x2020..0x7F7F */
13209 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13210 : 3) /* 0x20A0..0x7FFF */
13211 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13212 : (font->min_char_or_byte2 < 0x80
13213 ? (font->max_char_or_byte2 < 0x80
13214 ? 2 /* 0xA020..0xFF7F */
13215 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13216 : 1))); /* 0xA0A0..0xFFFF */
13218 fontp->baseline_offset
13219 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13220 ? (long) value : 0);
13221 fontp->relative_compose
13222 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13223 ? (long) value : 0);
13224 fontp->default_ascent
13225 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13226 ? (long) value : 0);
13228 /* Set global flag fonts_changed_p to non-zero if the font loaded
13229 has a character with a smaller width than any other character
13230 before, or if the font loaded has a smalle>r height than any
13231 other font loaded before. If this happens, it will make a
13232 glyph matrix reallocation necessary. */
13233 fonts_changed_p = x_compute_min_glyph_bounds (f);
13234 UNBLOCK_INPUT;
13235 return fontp;
13240 /* Return a pointer to struct font_info of a font named FONTNAME for
13241 frame F. If no such font is loaded, return NULL. */
13243 struct font_info *
13244 x_query_font (f, fontname)
13245 struct frame *f;
13246 register char *fontname;
13248 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13249 int i;
13251 for (i = 0; i < dpyinfo->n_fonts; i++)
13252 if (dpyinfo->font_table[i].name
13253 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13254 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13255 return (dpyinfo->font_table + i);
13256 return NULL;
13260 /* Find a CCL program for a font specified by FONTP, and set the member
13261 `encoder' of the structure. */
13263 void
13264 x_find_ccl_program (fontp)
13265 struct font_info *fontp;
13267 Lisp_Object list, elt;
13269 elt = Qnil;
13270 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13272 elt = XCAR (list);
13273 if (CONSP (elt)
13274 && STRINGP (XCAR (elt))
13275 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13276 >= 0)
13277 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13278 >= 0)))
13279 break;
13282 if (! NILP (list))
13284 struct ccl_program *ccl
13285 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13287 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13288 xfree (ccl);
13289 else
13290 fontp->font_encoder = ccl;
13296 /***********************************************************************
13297 Initialization
13298 ***********************************************************************/
13300 #ifdef USE_X_TOOLKIT
13301 static XrmOptionDescRec emacs_options[] = {
13302 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13303 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13305 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13306 XrmoptionSepArg, NULL},
13307 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13309 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13310 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13311 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13312 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13313 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13314 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13315 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13317 #endif /* USE_X_TOOLKIT */
13319 static int x_initialized;
13321 #ifdef MULTI_KBOARD
13322 /* Test whether two display-name strings agree up to the dot that separates
13323 the screen number from the server number. */
13324 static int
13325 same_x_server (name1, name2)
13326 char *name1, *name2;
13328 int seen_colon = 0;
13329 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13330 int system_name_length = strlen (system_name);
13331 int length_until_period = 0;
13333 while (system_name[length_until_period] != 0
13334 && system_name[length_until_period] != '.')
13335 length_until_period++;
13337 /* Treat `unix' like an empty host name. */
13338 if (! strncmp (name1, "unix:", 5))
13339 name1 += 4;
13340 if (! strncmp (name2, "unix:", 5))
13341 name2 += 4;
13342 /* Treat this host's name like an empty host name. */
13343 if (! strncmp (name1, system_name, system_name_length)
13344 && name1[system_name_length] == ':')
13345 name1 += system_name_length;
13346 if (! strncmp (name2, system_name, system_name_length)
13347 && name2[system_name_length] == ':')
13348 name2 += system_name_length;
13349 /* Treat this host's domainless name like an empty host name. */
13350 if (! strncmp (name1, system_name, length_until_period)
13351 && name1[length_until_period] == ':')
13352 name1 += length_until_period;
13353 if (! strncmp (name2, system_name, length_until_period)
13354 && name2[length_until_period] == ':')
13355 name2 += length_until_period;
13357 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13359 if (*name1 == ':')
13360 seen_colon++;
13361 if (seen_colon && *name1 == '.')
13362 return 1;
13364 return (seen_colon
13365 && (*name1 == '.' || *name1 == '\0')
13366 && (*name2 == '.' || *name2 == '\0'));
13368 #endif
13370 struct x_display_info *
13371 x_term_init (display_name, xrm_option, resource_name)
13372 Lisp_Object display_name;
13373 char *xrm_option;
13374 char *resource_name;
13376 int connection;
13377 Display *dpy;
13378 struct x_display_info *dpyinfo;
13379 XrmDatabase xrdb;
13381 BLOCK_INPUT;
13383 if (!x_initialized)
13385 x_initialize ();
13386 x_initialized = 1;
13389 #ifdef USE_X_TOOLKIT
13390 /* weiner@footloose.sps.mot.com reports that this causes
13391 errors with X11R5:
13392 X protocol error: BadAtom (invalid Atom parameter)
13393 on protocol request 18skiloaf.
13394 So let's not use it until R6. */
13395 #ifdef HAVE_X11XTR6
13396 XtSetLanguageProc (NULL, NULL, NULL);
13397 #endif
13400 int argc = 0;
13401 char *argv[3];
13403 argv[0] = "";
13404 argc = 1;
13405 if (xrm_option)
13407 argv[argc++] = "-xrm";
13408 argv[argc++] = xrm_option;
13410 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13411 resource_name, EMACS_CLASS,
13412 emacs_options, XtNumber (emacs_options),
13413 &argc, argv);
13415 #ifdef HAVE_X11XTR6
13416 /* I think this is to compensate for XtSetLanguageProc. */
13417 fixup_locale ();
13418 #endif
13421 #else /* not USE_X_TOOLKIT */
13422 #ifdef HAVE_X11R5
13423 XSetLocaleModifiers ("");
13424 #endif
13425 dpy = XOpenDisplay (XSTRING (display_name)->data);
13426 #endif /* not USE_X_TOOLKIT */
13428 /* Detect failure. */
13429 if (dpy == 0)
13431 UNBLOCK_INPUT;
13432 return 0;
13435 /* We have definitely succeeded. Record the new connection. */
13437 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13438 bzero (dpyinfo, sizeof *dpyinfo);
13440 #ifdef MULTI_KBOARD
13442 struct x_display_info *share;
13443 Lisp_Object tail;
13445 for (share = x_display_list, tail = x_display_name_list; share;
13446 share = share->next, tail = XCDR (tail))
13447 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13448 XSTRING (display_name)->data))
13449 break;
13450 if (share)
13451 dpyinfo->kboard = share->kboard;
13452 else
13454 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13455 init_kboard (dpyinfo->kboard);
13456 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13458 char *vendor = ServerVendor (dpy);
13459 UNBLOCK_INPUT;
13460 dpyinfo->kboard->Vsystem_key_alist
13461 = call1 (Qvendor_specific_keysyms,
13462 build_string (vendor ? vendor : ""));
13463 BLOCK_INPUT;
13466 dpyinfo->kboard->next_kboard = all_kboards;
13467 all_kboards = dpyinfo->kboard;
13468 /* Don't let the initial kboard remain current longer than necessary.
13469 That would cause problems if a file loaded on startup tries to
13470 prompt in the mini-buffer. */
13471 if (current_kboard == initial_kboard)
13472 current_kboard = dpyinfo->kboard;
13474 dpyinfo->kboard->reference_count++;
13476 #endif
13478 /* Put this display on the chain. */
13479 dpyinfo->next = x_display_list;
13480 x_display_list = dpyinfo;
13482 /* Put it on x_display_name_list as well, to keep them parallel. */
13483 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13484 x_display_name_list);
13485 dpyinfo->name_list_element = XCAR (x_display_name_list);
13487 dpyinfo->display = dpy;
13489 #if 0
13490 XSetAfterFunction (x_current_display, x_trace_wire);
13491 #endif /* ! 0 */
13493 dpyinfo->x_id_name
13494 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13495 + STRING_BYTES (XSTRING (Vsystem_name))
13496 + 2);
13497 sprintf (dpyinfo->x_id_name, "%s@%s",
13498 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13500 /* Figure out which modifier bits mean what. */
13501 x_find_modifier_meanings (dpyinfo);
13503 /* Get the scroll bar cursor. */
13504 dpyinfo->vertical_scroll_bar_cursor
13505 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13507 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13508 resource_name, EMACS_CLASS);
13509 #ifdef HAVE_XRMSETDATABASE
13510 XrmSetDatabase (dpyinfo->display, xrdb);
13511 #else
13512 dpyinfo->display->db = xrdb;
13513 #endif
13514 /* Put the rdb where we can find it in a way that works on
13515 all versions. */
13516 dpyinfo->xrdb = xrdb;
13518 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13519 DefaultScreen (dpyinfo->display));
13520 select_visual (dpyinfo);
13521 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13522 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13523 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13524 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13525 dpyinfo->grabbed = 0;
13526 dpyinfo->reference_count = 0;
13527 dpyinfo->icon_bitmap_id = -1;
13528 dpyinfo->font_table = NULL;
13529 dpyinfo->n_fonts = 0;
13530 dpyinfo->font_table_size = 0;
13531 dpyinfo->bitmaps = 0;
13532 dpyinfo->bitmaps_size = 0;
13533 dpyinfo->bitmaps_last = 0;
13534 dpyinfo->scratch_cursor_gc = 0;
13535 dpyinfo->mouse_face_mouse_frame = 0;
13536 dpyinfo->mouse_face_deferred_gc = 0;
13537 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13538 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13539 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13540 dpyinfo->mouse_face_window = Qnil;
13541 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13542 dpyinfo->mouse_face_defer = 0;
13543 dpyinfo->x_focus_frame = 0;
13544 dpyinfo->x_focus_event_frame = 0;
13545 dpyinfo->x_highlight_frame = 0;
13546 dpyinfo->image_cache = make_image_cache ();
13548 /* See if a private colormap is requested. */
13549 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13551 if (dpyinfo->visual->class == PseudoColor)
13553 Lisp_Object value;
13554 value = display_x_get_resource (dpyinfo,
13555 build_string ("privateColormap"),
13556 build_string ("PrivateColormap"),
13557 Qnil, Qnil);
13558 if (STRINGP (value)
13559 && (!strcmp (XSTRING (value)->data, "true")
13560 || !strcmp (XSTRING (value)->data, "on")))
13561 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13564 else
13565 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13566 dpyinfo->visual, AllocNone);
13569 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13570 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13571 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13572 dpyinfo->resy = pixels * 25.4 / mm;
13573 pixels = DisplayWidth (dpyinfo->display, screen_number);
13574 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13575 dpyinfo->resx = pixels * 25.4 / mm;
13578 dpyinfo->Xatom_wm_protocols
13579 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13580 dpyinfo->Xatom_wm_take_focus
13581 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13582 dpyinfo->Xatom_wm_save_yourself
13583 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13584 dpyinfo->Xatom_wm_delete_window
13585 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13586 dpyinfo->Xatom_wm_change_state
13587 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13588 dpyinfo->Xatom_wm_configure_denied
13589 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13590 dpyinfo->Xatom_wm_window_moved
13591 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13592 dpyinfo->Xatom_editres
13593 = XInternAtom (dpyinfo->display, "Editres", False);
13594 dpyinfo->Xatom_CLIPBOARD
13595 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13596 dpyinfo->Xatom_TIMESTAMP
13597 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13598 dpyinfo->Xatom_TEXT
13599 = XInternAtom (dpyinfo->display, "TEXT", False);
13600 dpyinfo->Xatom_COMPOUND_TEXT
13601 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13602 dpyinfo->Xatom_DELETE
13603 = XInternAtom (dpyinfo->display, "DELETE", False);
13604 dpyinfo->Xatom_MULTIPLE
13605 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13606 dpyinfo->Xatom_INCR
13607 = XInternAtom (dpyinfo->display, "INCR", False);
13608 dpyinfo->Xatom_EMACS_TMP
13609 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13610 dpyinfo->Xatom_TARGETS
13611 = XInternAtom (dpyinfo->display, "TARGETS", False);
13612 dpyinfo->Xatom_NULL
13613 = XInternAtom (dpyinfo->display, "NULL", False);
13614 dpyinfo->Xatom_ATOM_PAIR
13615 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13616 /* For properties of font. */
13617 dpyinfo->Xatom_PIXEL_SIZE
13618 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13619 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13620 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13621 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13622 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13623 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13624 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13626 /* Ghostscript support. */
13627 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13628 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13630 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13631 False);
13633 dpyinfo->cut_buffers_initialized = 0;
13635 connection = ConnectionNumber (dpyinfo->display);
13636 dpyinfo->connection = connection;
13639 char null_bits[1];
13641 null_bits[0] = 0x00;
13643 dpyinfo->null_pixel
13644 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13645 null_bits, 1, 1, (long) 0, (long) 0,
13650 extern int gray_bitmap_width, gray_bitmap_height;
13651 extern unsigned char *gray_bitmap_bits;
13652 dpyinfo->gray
13653 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13654 gray_bitmap_bits,
13655 gray_bitmap_width, gray_bitmap_height,
13656 (unsigned long) 1, (unsigned long) 0, 1);
13659 #ifdef HAVE_X_I18N
13660 xim_initialize (dpyinfo, resource_name);
13661 #endif
13663 #ifdef subprocesses
13664 /* This is only needed for distinguishing keyboard and process input. */
13665 if (connection != 0)
13666 add_keyboard_wait_descriptor (connection);
13667 #endif
13669 #ifndef F_SETOWN_BUG
13670 #ifdef F_SETOWN
13671 #ifdef F_SETOWN_SOCK_NEG
13672 /* stdin is a socket here */
13673 fcntl (connection, F_SETOWN, -getpid ());
13674 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13675 fcntl (connection, F_SETOWN, getpid ());
13676 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13677 #endif /* ! defined (F_SETOWN) */
13678 #endif /* F_SETOWN_BUG */
13680 #ifdef SIGIO
13681 if (interrupt_input)
13682 init_sigio (connection);
13683 #endif /* ! defined (SIGIO) */
13685 #ifdef USE_LUCID
13686 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13687 /* Make sure that we have a valid font for dialog boxes
13688 so that Xt does not crash. */
13690 Display *dpy = dpyinfo->display;
13691 XrmValue d, fr, to;
13692 Font font;
13693 int count;
13695 d.addr = (XPointer)&dpy;
13696 d.size = sizeof (Display *);
13697 fr.addr = XtDefaultFont;
13698 fr.size = sizeof (XtDefaultFont);
13699 to.size = sizeof (Font *);
13700 to.addr = (XPointer)&font;
13701 count = x_catch_errors (dpy);
13702 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13703 abort ();
13704 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13705 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13706 x_uncatch_errors (dpy, count);
13708 #endif
13709 #endif
13711 /* See if we should run in synchronous mode. This is useful
13712 for debugging X code. */
13714 Lisp_Object value;
13715 value = display_x_get_resource (dpyinfo,
13716 build_string ("synchronous"),
13717 build_string ("Synchronous"),
13718 Qnil, Qnil);
13719 if (STRINGP (value)
13720 && (!strcmp (XSTRING (value)->data, "true")
13721 || !strcmp (XSTRING (value)->data, "on")))
13722 XSynchronize (dpyinfo->display, True);
13725 UNBLOCK_INPUT;
13727 return dpyinfo;
13730 /* Get rid of display DPYINFO, assuming all frames are already gone,
13731 and without sending any more commands to the X server. */
13733 void
13734 x_delete_display (dpyinfo)
13735 struct x_display_info *dpyinfo;
13737 delete_keyboard_wait_descriptor (dpyinfo->connection);
13739 /* Discard this display from x_display_name_list and x_display_list.
13740 We can't use Fdelq because that can quit. */
13741 if (! NILP (x_display_name_list)
13742 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13743 x_display_name_list = XCDR (x_display_name_list);
13744 else
13746 Lisp_Object tail;
13748 tail = x_display_name_list;
13749 while (CONSP (tail) && CONSP (XCDR (tail)))
13751 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13753 XCDR (tail) = XCDR (XCDR (tail));
13754 break;
13756 tail = XCDR (tail);
13760 if (next_noop_dpyinfo == dpyinfo)
13761 next_noop_dpyinfo = dpyinfo->next;
13763 if (x_display_list == dpyinfo)
13764 x_display_list = dpyinfo->next;
13765 else
13767 struct x_display_info *tail;
13769 for (tail = x_display_list; tail; tail = tail->next)
13770 if (tail->next == dpyinfo)
13771 tail->next = tail->next->next;
13774 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13775 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13776 XrmDestroyDatabase (dpyinfo->xrdb);
13777 #endif
13778 #endif
13779 #ifdef MULTI_KBOARD
13780 if (--dpyinfo->kboard->reference_count == 0)
13781 delete_kboard (dpyinfo->kboard);
13782 #endif
13783 #ifdef HAVE_X_I18N
13784 if (dpyinfo->xim)
13785 xim_close_dpy (dpyinfo);
13786 #endif
13788 xfree (dpyinfo->font_table);
13789 xfree (dpyinfo->x_id_name);
13790 xfree (dpyinfo->color_cells);
13791 xfree (dpyinfo);
13795 /* Set up use of X before we make the first connection. */
13797 static struct redisplay_interface x_redisplay_interface =
13799 x_produce_glyphs,
13800 x_write_glyphs,
13801 x_insert_glyphs,
13802 x_clear_end_of_line,
13803 x_scroll_run,
13804 x_after_update_window_line,
13805 x_update_window_begin,
13806 x_update_window_end,
13807 XTcursor_to,
13808 x_flush,
13809 x_clear_mouse_face,
13810 x_get_glyph_overhangs,
13811 x_fix_overlapping_area
13814 void
13815 x_initialize ()
13817 rif = &x_redisplay_interface;
13819 clear_frame_hook = x_clear_frame;
13820 ins_del_lines_hook = x_ins_del_lines;
13821 change_line_highlight_hook = x_change_line_highlight;
13822 delete_glyphs_hook = x_delete_glyphs;
13823 ring_bell_hook = XTring_bell;
13824 reset_terminal_modes_hook = XTreset_terminal_modes;
13825 set_terminal_modes_hook = XTset_terminal_modes;
13826 update_begin_hook = x_update_begin;
13827 update_end_hook = x_update_end;
13828 set_terminal_window_hook = XTset_terminal_window;
13829 read_socket_hook = XTread_socket;
13830 frame_up_to_date_hook = XTframe_up_to_date;
13831 reassert_line_highlight_hook = XTreassert_line_highlight;
13832 mouse_position_hook = XTmouse_position;
13833 frame_rehighlight_hook = XTframe_rehighlight;
13834 frame_raise_lower_hook = XTframe_raise_lower;
13835 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13836 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13837 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13838 judge_scroll_bars_hook = XTjudge_scroll_bars;
13839 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13841 scroll_region_ok = 1; /* we'll scroll partial frames */
13842 char_ins_del_ok = 0; /* just as fast to write the line */
13843 line_ins_del_ok = 1; /* we'll just blt 'em */
13844 fast_clear_end_of_line = 1; /* X does this well */
13845 memory_below_frame = 0; /* we don't remember what scrolls
13846 off the bottom */
13847 baud_rate = 19200;
13849 x_noop_count = 0;
13850 last_tool_bar_item = -1;
13851 any_help_event_p = 0;
13853 /* Try to use interrupt input; if we can't, then start polling. */
13854 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13856 #ifdef USE_X_TOOLKIT
13857 XtToolkitInitialize ();
13858 Xt_app_con = XtCreateApplicationContext ();
13859 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13861 /* Install an asynchronous timer that processes Xt timeout events
13862 every 0.1s. This is necessary because some widget sets use
13863 timeouts internally, for example the LessTif menu bar, or the
13864 Xaw3d scroll bar. When Xt timouts aren't processed, these
13865 widgets don't behave normally. */
13867 EMACS_TIME interval;
13868 EMACS_SET_SECS_USECS (interval, 0, 100000);
13869 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13871 #endif
13873 #if USE_TOOLKIT_SCROLL_BARS
13874 xaw3d_arrow_scroll = False;
13875 xaw3d_pick_top = True;
13876 #endif
13878 /* Note that there is no real way portable across R3/R4 to get the
13879 original error handler. */
13880 XSetErrorHandler (x_error_handler);
13881 XSetIOErrorHandler (x_io_error_quitter);
13883 /* Disable Window Change signals; they are handled by X events. */
13884 #ifdef SIGWINCH
13885 signal (SIGWINCH, SIG_DFL);
13886 #endif /* ! defined (SIGWINCH) */
13888 signal (SIGPIPE, x_connection_signal);
13892 void
13893 syms_of_xterm ()
13895 staticpro (&x_error_message_string);
13896 x_error_message_string = Qnil;
13898 staticpro (&x_display_name_list);
13899 x_display_name_list = Qnil;
13901 staticpro (&last_mouse_scroll_bar);
13902 last_mouse_scroll_bar = Qnil;
13904 staticpro (&Qvendor_specific_keysyms);
13905 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13907 staticpro (&last_mouse_press_frame);
13908 last_mouse_press_frame = Qnil;
13910 help_echo = Qnil;
13911 staticpro (&help_echo);
13912 help_echo_object = Qnil;
13913 staticpro (&help_echo_object);
13914 help_echo_window = Qnil;
13915 staticpro (&help_echo_window);
13916 previous_help_echo = Qnil;
13917 staticpro (&previous_help_echo);
13918 help_echo_pos = -1;
13920 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13921 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13922 For example, if a block cursor is over a tab, it will be drawn as\n\
13923 wide as that tab on the display.");
13924 x_stretch_cursor_p = 0;
13926 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13927 "If not nil, Emacs uses toolkit scroll bars.");
13928 #if USE_TOOLKIT_SCROLL_BARS
13929 x_toolkit_scroll_bars_p = 1;
13930 #else
13931 x_toolkit_scroll_bars_p = 0;
13932 #endif
13934 staticpro (&last_mouse_motion_frame);
13935 last_mouse_motion_frame = Qnil;
13938 #endif /* not HAVE_X_WINDOWS */