(cvs-mode-marked): New arg `noquery'.
[emacs.git] / src / xterm.c
blob838e6472c7f9497874cfb06cbdf35a54e71358d9
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)) + 1 - FONT_HEIGHT ((FONT))) / 2 \
1781 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1783 /* Produce glyphs/get display metrics for the display element IT is
1784 loaded with. See the description of struct display_iterator in
1785 dispextern.h for an overview of struct display_iterator. */
1787 static void
1788 x_produce_glyphs (it)
1789 struct it *it;
1791 it->glyph_not_available_p = 0;
1793 if (it->what == IT_CHARACTER)
1795 XChar2b char2b;
1796 XFontStruct *font;
1797 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1798 XCharStruct *pcm;
1799 int font_not_found_p;
1800 struct font_info *font_info;
1801 int boff; /* baseline offset */
1802 /* We may change it->multibyte_p upon unibyte<->multibyte
1803 conversion. So, save the current value now and restore it
1804 later.
1806 Note: It seems that we don't have to record multibyte_p in
1807 struct glyph because the character code itself tells if or
1808 not the character is multibyte. Thus, in the future, we must
1809 consider eliminating the field `multibyte_p' in the struct
1810 glyph.
1812 int saved_multibyte_p = it->multibyte_p;
1814 /* Maybe translate single-byte characters to multibyte, or the
1815 other way. */
1816 it->char_to_display = it->c;
1817 if (!ASCII_BYTE_P (it->c))
1819 if (unibyte_display_via_language_environment
1820 && SINGLE_BYTE_CHAR_P (it->c)
1821 && (it->c >= 0240
1822 || !NILP (Vnonascii_translation_table)))
1824 it->char_to_display = unibyte_char_to_multibyte (it->c);
1825 it->multibyte_p = 1;
1826 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1827 face = FACE_FROM_ID (it->f, it->face_id);
1829 else if (!SINGLE_BYTE_CHAR_P (it->c)
1830 && !it->multibyte_p)
1832 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1833 it->multibyte_p = 0;
1834 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1835 face = FACE_FROM_ID (it->f, it->face_id);
1839 /* Get font to use. Encode IT->char_to_display. */
1840 x_get_char_face_and_encoding (it->f, it->char_to_display,
1841 it->face_id, &char2b,
1842 it->multibyte_p);
1843 font = face->font;
1845 /* When no suitable font found, use the default font. */
1846 font_not_found_p = font == NULL;
1847 if (font_not_found_p)
1849 font = FRAME_FONT (it->f);
1850 boff = it->f->output_data.x->baseline_offset;
1851 font_info = NULL;
1853 else
1855 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1856 boff = font_info->baseline_offset;
1857 if (font_info->vertical_centering)
1858 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1861 if (it->char_to_display >= ' '
1862 && (!it->multibyte_p || it->char_to_display < 128))
1864 /* Either unibyte or ASCII. */
1865 int stretched_p;
1867 it->nglyphs = 1;
1869 pcm = x_per_char_metric (font, &char2b);
1870 it->ascent = font->ascent + boff;
1871 it->descent = font->descent - boff;
1873 if (pcm)
1875 it->phys_ascent = pcm->ascent + boff;
1876 it->phys_descent = pcm->descent - boff;
1877 it->pixel_width = pcm->width;
1879 else
1881 it->glyph_not_available_p = 1;
1882 it->phys_ascent = font->ascent + boff;
1883 it->phys_descent = font->descent - boff;
1884 it->pixel_width = FONT_WIDTH (font);
1887 /* If this is a space inside a region of text with
1888 `space-width' property, change its width. */
1889 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1890 if (stretched_p)
1891 it->pixel_width *= XFLOATINT (it->space_width);
1893 /* If face has a box, add the box thickness to the character
1894 height. If character has a box line to the left and/or
1895 right, add the box line width to the character's width. */
1896 if (face->box != FACE_NO_BOX)
1898 int thick = face->box_line_width;
1900 it->ascent += thick;
1901 it->descent += thick;
1903 if (it->start_of_box_run_p)
1904 it->pixel_width += thick;
1905 if (it->end_of_box_run_p)
1906 it->pixel_width += thick;
1909 /* If face has an overline, add the height of the overline
1910 (1 pixel) and a 1 pixel margin to the character height. */
1911 if (face->overline_p)
1912 it->ascent += 2;
1914 take_vertical_position_into_account (it);
1916 /* If we have to actually produce glyphs, do it. */
1917 if (it->glyph_row)
1919 if (stretched_p)
1921 /* Translate a space with a `space-width' property
1922 into a stretch glyph. */
1923 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1924 x_append_stretch_glyph (it, it->object, it->pixel_width,
1925 it->ascent + it->descent, ascent);
1927 else
1928 x_append_glyph (it);
1930 /* If characters with lbearing or rbearing are displayed
1931 in this line, record that fact in a flag of the
1932 glyph row. This is used to optimize X output code. */
1933 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1934 it->glyph_row->contains_overlapping_glyphs_p = 1;
1937 else if (it->char_to_display == '\n')
1939 /* A newline has no width but we need the height of the line. */
1940 it->pixel_width = 0;
1941 it->nglyphs = 0;
1942 it->ascent = it->phys_ascent = font->ascent + boff;
1943 it->descent = it->phys_descent = font->descent - boff;
1945 if (face->box != FACE_NO_BOX)
1947 int thick = face->box_line_width;
1948 it->ascent += thick;
1949 it->descent += thick;
1952 else if (it->char_to_display == '\t')
1954 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1955 int x = it->current_x + it->continuation_lines_width;
1956 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1958 /* If the distance from the current position to the next tab
1959 stop is less than a canonical character width, use the
1960 tab stop after that. */
1961 if (next_tab_x - x < CANON_X_UNIT (it->f))
1962 next_tab_x += tab_width;
1964 it->pixel_width = next_tab_x - x;
1965 it->nglyphs = 1;
1966 it->ascent = it->phys_ascent = font->ascent + boff;
1967 it->descent = it->phys_descent = font->descent - boff;
1969 if (it->glyph_row)
1971 double ascent = (double) it->ascent / (it->ascent + it->descent);
1972 x_append_stretch_glyph (it, it->object, it->pixel_width,
1973 it->ascent + it->descent, ascent);
1976 else
1978 /* A multi-byte character. Assume that the display width of the
1979 character is the width of the character multiplied by the
1980 width of the font. */
1982 /* If we found a font, this font should give us the right
1983 metrics. If we didn't find a font, use the frame's
1984 default font and calculate the width of the character
1985 from the charset width; this is what old redisplay code
1986 did. */
1987 pcm = x_per_char_metric (font, &char2b);
1988 if (font_not_found_p || !pcm)
1990 int charset = CHAR_CHARSET (it->char_to_display);
1992 it->glyph_not_available_p = 1;
1993 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1994 * CHARSET_WIDTH (charset));
1995 it->phys_ascent = font->ascent + boff;
1996 it->phys_descent = font->descent - boff;
1998 else
2000 it->pixel_width = pcm->width;
2001 it->phys_ascent = pcm->ascent + boff;
2002 it->phys_descent = pcm->descent - boff;
2003 if (it->glyph_row
2004 && (pcm->lbearing < 0
2005 || pcm->rbearing > pcm->width))
2006 it->glyph_row->contains_overlapping_glyphs_p = 1;
2008 it->nglyphs = 1;
2009 it->ascent = font->ascent + boff;
2010 it->descent = font->descent - boff;
2011 if (face->box != FACE_NO_BOX)
2013 int thick = face->box_line_width;
2014 it->ascent += thick;
2015 it->descent += thick;
2017 if (it->start_of_box_run_p)
2018 it->pixel_width += thick;
2019 if (it->end_of_box_run_p)
2020 it->pixel_width += thick;
2023 /* If face has an overline, add the height of the overline
2024 (1 pixel) and a 1 pixel margin to the character height. */
2025 if (face->overline_p)
2026 it->ascent += 2;
2028 take_vertical_position_into_account (it);
2030 if (it->glyph_row)
2031 x_append_glyph (it);
2033 it->multibyte_p = saved_multibyte_p;
2035 else if (it->what == IT_COMPOSITION)
2037 /* Note: A composition is represented as one glyph in the
2038 glyph matrix. There are no padding glyphs. */
2039 XChar2b char2b;
2040 XFontStruct *font;
2041 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2042 XCharStruct *pcm;
2043 int font_not_found_p;
2044 struct font_info *font_info;
2045 int boff; /* baseline offset */
2046 struct composition *cmp = composition_table[it->cmp_id];
2048 /* Maybe translate single-byte characters to multibyte. */
2049 it->char_to_display = it->c;
2050 if (unibyte_display_via_language_environment
2051 && SINGLE_BYTE_CHAR_P (it->c)
2052 && (it->c >= 0240
2053 || (it->c >= 0200
2054 && !NILP (Vnonascii_translation_table))))
2056 it->char_to_display = unibyte_char_to_multibyte (it->c);
2059 /* Get face and font to use. Encode IT->char_to_display. */
2060 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2061 face = FACE_FROM_ID (it->f, it->face_id);
2062 x_get_char_face_and_encoding (it->f, it->char_to_display,
2063 it->face_id, &char2b, it->multibyte_p);
2064 font = face->font;
2066 /* When no suitable font found, use the default font. */
2067 font_not_found_p = font == NULL;
2068 if (font_not_found_p)
2070 font = FRAME_FONT (it->f);
2071 boff = it->f->output_data.x->baseline_offset;
2072 font_info = NULL;
2074 else
2076 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2077 boff = font_info->baseline_offset;
2078 if (font_info->vertical_centering)
2079 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2082 /* There are no padding glyphs, so there is only one glyph to
2083 produce for the composition. Important is that pixel_width,
2084 ascent and descent are the values of what is drawn by
2085 draw_glyphs (i.e. the values of the overall glyphs composed). */
2086 it->nglyphs = 1;
2088 /* If we have not yet calculated pixel size data of glyphs of
2089 the composition for the current face font, calculate them
2090 now. Theoretically, we have to check all fonts for the
2091 glyphs, but that requires much time and memory space. So,
2092 here we check only the font of the first glyph. This leads
2093 to incorrect display very rarely, and C-l (recenter) can
2094 correct the display anyway. */
2095 if (cmp->font != (void *) font)
2097 /* Ascent and descent of the font of the first character of
2098 this composition (adjusted by baseline offset). Ascent
2099 and descent of overall glyphs should not be less than
2100 them respectively. */
2101 int font_ascent = font->ascent + boff;
2102 int font_descent = font->descent - boff;
2103 /* Bounding box of the overall glyphs. */
2104 int leftmost, rightmost, lowest, highest;
2105 int i, width, ascent, descent;
2107 cmp->font = (void *) font;
2109 /* Initialize the bounding box. */
2110 pcm = x_per_char_metric (font, &char2b);
2111 if (pcm)
2113 width = pcm->width;
2114 ascent = pcm->ascent;
2115 descent = pcm->descent;
2117 else
2119 width = FONT_WIDTH (font);
2120 ascent = font->ascent;
2121 descent = font->descent;
2124 rightmost = width;
2125 lowest = - descent + boff;
2126 highest = ascent + boff;
2127 leftmost = 0;
2129 if (font_info
2130 && font_info->default_ascent
2131 && CHAR_TABLE_P (Vuse_default_ascent)
2132 && !NILP (Faref (Vuse_default_ascent,
2133 make_number (it->char_to_display))))
2134 highest = font_info->default_ascent + boff;
2136 /* Draw the first glyph at the normal position. It may be
2137 shifted to right later if some other glyphs are drawn at
2138 the left. */
2139 cmp->offsets[0] = 0;
2140 cmp->offsets[1] = boff;
2142 /* Set cmp->offsets for the remaining glyphs. */
2143 for (i = 1; i < cmp->glyph_len; i++)
2145 int left, right, btm, top;
2146 int ch = COMPOSITION_GLYPH (cmp, i);
2147 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2149 face = FACE_FROM_ID (it->f, face_id);
2150 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2151 it->multibyte_p);
2152 font = face->font;
2153 if (font == NULL)
2155 font = FRAME_FONT (it->f);
2156 boff = it->f->output_data.x->baseline_offset;
2157 font_info = NULL;
2159 else
2161 font_info
2162 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2163 boff = font_info->baseline_offset;
2164 if (font_info->vertical_centering)
2165 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2168 pcm = x_per_char_metric (font, &char2b);
2169 if (pcm)
2171 width = pcm->width;
2172 ascent = pcm->ascent;
2173 descent = pcm->descent;
2175 else
2177 width = FONT_WIDTH (font);
2178 ascent = font->ascent;
2179 descent = font->descent;
2182 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2184 /* Relative composition with or without
2185 alternate chars. */
2186 left = (leftmost + rightmost - width) / 2;
2187 btm = - descent + boff;
2188 if (font_info && font_info->relative_compose
2189 && (! CHAR_TABLE_P (Vignore_relative_composition)
2190 || NILP (Faref (Vignore_relative_composition,
2191 make_number (ch)))))
2194 if (- descent >= font_info->relative_compose)
2195 /* One extra pixel between two glyphs. */
2196 btm = highest + 1;
2197 else if (ascent <= 0)
2198 /* One extra pixel between two glyphs. */
2199 btm = lowest - 1 - ascent - descent;
2202 else
2204 /* A composition rule is specified by an integer
2205 value that encodes global and new reference
2206 points (GREF and NREF). GREF and NREF are
2207 specified by numbers as below:
2209 0---1---2 -- ascent
2213 9--10--11 -- center
2215 ---3---4---5--- baseline
2217 6---7---8 -- descent
2219 int rule = COMPOSITION_RULE (cmp, i);
2220 int gref, nref, grefx, grefy, nrefx, nrefy;
2222 COMPOSITION_DECODE_RULE (rule, gref, nref);
2223 grefx = gref % 3, nrefx = nref % 3;
2224 grefy = gref / 3, nrefy = nref / 3;
2226 left = (leftmost
2227 + grefx * (rightmost - leftmost) / 2
2228 - nrefx * width / 2);
2229 btm = ((grefy == 0 ? highest
2230 : grefy == 1 ? 0
2231 : grefy == 2 ? lowest
2232 : (highest + lowest) / 2)
2233 - (nrefy == 0 ? ascent + descent
2234 : nrefy == 1 ? descent - boff
2235 : nrefy == 2 ? 0
2236 : (ascent + descent) / 2));
2239 cmp->offsets[i * 2] = left;
2240 cmp->offsets[i * 2 + 1] = btm + descent;
2242 /* Update the bounding box of the overall glyphs. */
2243 right = left + width;
2244 top = btm + descent + ascent;
2245 if (left < leftmost)
2246 leftmost = left;
2247 if (right > rightmost)
2248 rightmost = right;
2249 if (top > highest)
2250 highest = top;
2251 if (btm < lowest)
2252 lowest = btm;
2255 /* If there are glyphs whose x-offsets are negative,
2256 shift all glyphs to the right and make all x-offsets
2257 non-negative. */
2258 if (leftmost < 0)
2260 for (i = 0; i < cmp->glyph_len; i++)
2261 cmp->offsets[i * 2] -= leftmost;
2262 rightmost -= leftmost;
2265 cmp->pixel_width = rightmost;
2266 cmp->ascent = highest;
2267 cmp->descent = - lowest;
2268 if (cmp->ascent < font_ascent)
2269 cmp->ascent = font_ascent;
2270 if (cmp->descent < font_descent)
2271 cmp->descent = font_descent;
2274 it->pixel_width = cmp->pixel_width;
2275 it->ascent = it->phys_ascent = cmp->ascent;
2276 it->descent = it->phys_descent = cmp->descent;
2278 if (face->box != FACE_NO_BOX)
2280 int thick = face->box_line_width;
2281 it->ascent += thick;
2282 it->descent += thick;
2284 if (it->start_of_box_run_p)
2285 it->pixel_width += thick;
2286 if (it->end_of_box_run_p)
2287 it->pixel_width += thick;
2290 /* If face has an overline, add the height of the overline
2291 (1 pixel) and a 1 pixel margin to the character height. */
2292 if (face->overline_p)
2293 it->ascent += 2;
2295 take_vertical_position_into_account (it);
2297 if (it->glyph_row)
2298 x_append_composite_glyph (it);
2300 else if (it->what == IT_IMAGE)
2301 x_produce_image_glyph (it);
2302 else if (it->what == IT_STRETCH)
2303 x_produce_stretch_glyph (it);
2305 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2306 because this isn't true for images with `:ascent 100'. */
2307 xassert (it->ascent >= 0 && it->descent >= 0);
2308 if (it->area == TEXT_AREA)
2309 it->current_x += it->pixel_width;
2311 it->descent += it->extra_line_spacing;
2313 it->max_ascent = max (it->max_ascent, it->ascent);
2314 it->max_descent = max (it->max_descent, it->descent);
2315 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2316 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2320 /* Estimate the pixel height of the mode or top line on frame F.
2321 FACE_ID specifies what line's height to estimate. */
2324 x_estimate_mode_line_height (f, face_id)
2325 struct frame *f;
2326 enum face_id face_id;
2328 int height = 1;
2330 /* This function is called so early when Emacs starts that the face
2331 cache and mode line face are not yet initialized. */
2332 if (FRAME_FACE_CACHE (f))
2334 struct face *face = FACE_FROM_ID (f, face_id);
2335 if (face)
2336 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2339 return height;
2343 /***********************************************************************
2344 Glyph display
2345 ***********************************************************************/
2347 /* A sequence of glyphs to be drawn in the same face.
2349 This data structure is not really completely X specific, so it
2350 could possibly, at least partially, be useful for other systems. It
2351 is currently not part of the external redisplay interface because
2352 it's not clear what other systems will need. */
2354 struct glyph_string
2356 /* X-origin of the string. */
2357 int x;
2359 /* Y-origin and y-position of the base line of this string. */
2360 int y, ybase;
2362 /* The width of the string, not including a face extension. */
2363 int width;
2365 /* The width of the string, including a face extension. */
2366 int background_width;
2368 /* The height of this string. This is the height of the line this
2369 string is drawn in, and can be different from the height of the
2370 font the string is drawn in. */
2371 int height;
2373 /* Number of pixels this string overwrites in front of its x-origin.
2374 This number is zero if the string has an lbearing >= 0; it is
2375 -lbearing, if the string has an lbearing < 0. */
2376 int left_overhang;
2378 /* Number of pixels this string overwrites past its right-most
2379 nominal x-position, i.e. x + width. Zero if the string's
2380 rbearing is <= its nominal width, rbearing - width otherwise. */
2381 int right_overhang;
2383 /* The frame on which the glyph string is drawn. */
2384 struct frame *f;
2386 /* The window on which the glyph string is drawn. */
2387 struct window *w;
2389 /* X display and window for convenience. */
2390 Display *display;
2391 Window window;
2393 /* The glyph row for which this string was built. It determines the
2394 y-origin and height of the string. */
2395 struct glyph_row *row;
2397 /* The area within row. */
2398 enum glyph_row_area area;
2400 /* Characters to be drawn, and number of characters. */
2401 XChar2b *char2b;
2402 int nchars;
2404 /* A face-override for drawing cursors, mouse face and similar. */
2405 enum draw_glyphs_face hl;
2407 /* Face in which this string is to be drawn. */
2408 struct face *face;
2410 /* Font in which this string is to be drawn. */
2411 XFontStruct *font;
2413 /* Font info for this string. */
2414 struct font_info *font_info;
2416 /* Non-null means this string describes (part of) a composition.
2417 All characters from char2b are drawn composed. */
2418 struct composition *cmp;
2420 /* Index of this glyph string's first character in the glyph
2421 definition of CMP. If this is zero, this glyph string describes
2422 the first character of a composition. */
2423 int gidx;
2425 /* 1 means this glyph strings face has to be drawn to the right end
2426 of the window's drawing area. */
2427 unsigned extends_to_end_of_line_p : 1;
2429 /* 1 means the background of this string has been drawn. */
2430 unsigned background_filled_p : 1;
2432 /* 1 means glyph string must be drawn with 16-bit functions. */
2433 unsigned two_byte_p : 1;
2435 /* 1 means that the original font determined for drawing this glyph
2436 string could not be loaded. The member `font' has been set to
2437 the frame's default font in this case. */
2438 unsigned font_not_found_p : 1;
2440 /* 1 means that the face in which this glyph string is drawn has a
2441 stipple pattern. */
2442 unsigned stippled_p : 1;
2444 /* 1 means only the foreground of this glyph string must be drawn,
2445 and we should use the physical height of the line this glyph
2446 string appears in as clip rect. */
2447 unsigned for_overlaps_p : 1;
2449 /* The GC to use for drawing this glyph string. */
2450 GC gc;
2452 /* A pointer to the first glyph in the string. This glyph
2453 corresponds to char2b[0]. Needed to draw rectangles if
2454 font_not_found_p is 1. */
2455 struct glyph *first_glyph;
2457 /* Image, if any. */
2458 struct image *img;
2460 struct glyph_string *next, *prev;
2464 #if 0
2466 static void
2467 x_dump_glyph_string (s)
2468 struct glyph_string *s;
2470 fprintf (stderr, "glyph string\n");
2471 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2472 s->x, s->y, s->width, s->height);
2473 fprintf (stderr, " ybase = %d\n", s->ybase);
2474 fprintf (stderr, " hl = %d\n", s->hl);
2475 fprintf (stderr, " left overhang = %d, right = %d\n",
2476 s->left_overhang, s->right_overhang);
2477 fprintf (stderr, " nchars = %d\n", s->nchars);
2478 fprintf (stderr, " extends to end of line = %d\n",
2479 s->extends_to_end_of_line_p);
2480 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2481 fprintf (stderr, " bg width = %d\n", s->background_width);
2484 #endif /* GLYPH_DEBUG */
2488 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2489 struct glyph_string **,
2490 struct glyph_string *,
2491 struct glyph_string *));
2492 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2493 struct glyph_string **,
2494 struct glyph_string *,
2495 struct glyph_string *));
2496 static void x_append_glyph_string P_ ((struct glyph_string **,
2497 struct glyph_string **,
2498 struct glyph_string *));
2499 static int x_left_overwritten P_ ((struct glyph_string *));
2500 static int x_left_overwriting P_ ((struct glyph_string *));
2501 static int x_right_overwritten P_ ((struct glyph_string *));
2502 static int x_right_overwriting P_ ((struct glyph_string *));
2503 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2504 int));
2505 static void x_init_glyph_string P_ ((struct glyph_string *,
2506 XChar2b *, struct window *,
2507 struct glyph_row *,
2508 enum glyph_row_area, int,
2509 enum draw_glyphs_face));
2510 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2511 enum glyph_row_area, int, int,
2512 enum draw_glyphs_face, int *, int *, int));
2513 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2514 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2515 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2516 int));
2517 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2518 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2519 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2520 static void x_draw_glyph_string P_ ((struct glyph_string *));
2521 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2522 static void x_set_cursor_gc P_ ((struct glyph_string *));
2523 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2524 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2525 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2526 int *, int *));
2527 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2528 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2529 unsigned long *, double, int));
2530 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2531 double, int, unsigned long));
2532 static void x_setup_relief_colors P_ ((struct glyph_string *));
2533 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2534 static void x_draw_image_relief P_ ((struct glyph_string *));
2535 static void x_draw_image_foreground P_ ((struct glyph_string *));
2536 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2537 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2538 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2539 int, int, int));
2540 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2541 int, int, int, int, XRectangle *));
2542 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2543 int, int, int, XRectangle *));
2544 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2545 enum glyph_row_area));
2546 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2547 struct glyph_row *,
2548 enum glyph_row_area, int, int));
2550 #if GLYPH_DEBUG
2551 static void x_check_font P_ ((struct frame *, XFontStruct *));
2552 #endif
2555 /* Append the list of glyph strings with head H and tail T to the list
2556 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2558 static INLINE void
2559 x_append_glyph_string_lists (head, tail, h, t)
2560 struct glyph_string **head, **tail;
2561 struct glyph_string *h, *t;
2563 if (h)
2565 if (*head)
2566 (*tail)->next = h;
2567 else
2568 *head = h;
2569 h->prev = *tail;
2570 *tail = t;
2575 /* Prepend the list of glyph strings with head H and tail T to the
2576 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2577 result. */
2579 static INLINE void
2580 x_prepend_glyph_string_lists (head, tail, h, t)
2581 struct glyph_string **head, **tail;
2582 struct glyph_string *h, *t;
2584 if (h)
2586 if (*head)
2587 (*head)->prev = t;
2588 else
2589 *tail = t;
2590 t->next = *head;
2591 *head = h;
2596 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2597 Set *HEAD and *TAIL to the resulting list. */
2599 static INLINE void
2600 x_append_glyph_string (head, tail, s)
2601 struct glyph_string **head, **tail;
2602 struct glyph_string *s;
2604 s->next = s->prev = NULL;
2605 x_append_glyph_string_lists (head, tail, s, s);
2609 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2610 face. */
2612 static void
2613 x_set_cursor_gc (s)
2614 struct glyph_string *s;
2616 if (s->font == FRAME_FONT (s->f)
2617 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2618 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2619 && !s->cmp)
2620 s->gc = s->f->output_data.x->cursor_gc;
2621 else
2623 /* Cursor on non-default face: must merge. */
2624 XGCValues xgcv;
2625 unsigned long mask;
2627 xgcv.background = s->f->output_data.x->cursor_pixel;
2628 xgcv.foreground = s->face->background;
2630 /* If the glyph would be invisible, try a different foreground. */
2631 if (xgcv.foreground == xgcv.background)
2632 xgcv.foreground = s->face->foreground;
2633 if (xgcv.foreground == xgcv.background)
2634 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2635 if (xgcv.foreground == xgcv.background)
2636 xgcv.foreground = s->face->foreground;
2638 /* Make sure the cursor is distinct from text in this face. */
2639 if (xgcv.background == s->face->background
2640 && xgcv.foreground == s->face->foreground)
2642 xgcv.background = s->face->foreground;
2643 xgcv.foreground = s->face->background;
2646 IF_DEBUG (x_check_font (s->f, s->font));
2647 xgcv.font = s->font->fid;
2648 xgcv.graphics_exposures = False;
2649 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2651 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2652 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2653 mask, &xgcv);
2654 else
2655 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2656 = XCreateGC (s->display, s->window, mask, &xgcv);
2658 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2663 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2665 static void
2666 x_set_mouse_face_gc (s)
2667 struct glyph_string *s;
2669 int face_id;
2670 struct face *face;
2672 /* What face has to be used for the mouse face? */
2673 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2674 face = FACE_FROM_ID (s->f, face_id);
2675 if (s->first_glyph->type == CHAR_GLYPH)
2676 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2677 else
2678 face_id = FACE_FOR_CHAR (s->f, face, 0);
2679 s->face = FACE_FROM_ID (s->f, face_id);
2680 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2682 /* If font in this face is same as S->font, use it. */
2683 if (s->font == s->face->font)
2684 s->gc = s->face->gc;
2685 else
2687 /* Otherwise construct scratch_cursor_gc with values from FACE
2688 but font FONT. */
2689 XGCValues xgcv;
2690 unsigned long mask;
2692 xgcv.background = s->face->background;
2693 xgcv.foreground = s->face->foreground;
2694 IF_DEBUG (x_check_font (s->f, s->font));
2695 xgcv.font = s->font->fid;
2696 xgcv.graphics_exposures = False;
2697 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2699 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2700 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2701 mask, &xgcv);
2702 else
2703 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2704 = XCreateGC (s->display, s->window, mask, &xgcv);
2706 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2709 xassert (s->gc != 0);
2713 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2714 Faces to use in the mode line have already been computed when the
2715 matrix was built, so there isn't much to do, here. */
2717 static INLINE void
2718 x_set_mode_line_face_gc (s)
2719 struct glyph_string *s;
2721 s->gc = s->face->gc;
2725 /* Set S->gc of glyph string S for drawing that glyph string. Set
2726 S->stippled_p to a non-zero value if the face of S has a stipple
2727 pattern. */
2729 static INLINE void
2730 x_set_glyph_string_gc (s)
2731 struct glyph_string *s;
2733 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2735 if (s->hl == DRAW_NORMAL_TEXT)
2737 s->gc = s->face->gc;
2738 s->stippled_p = s->face->stipple != 0;
2740 else if (s->hl == DRAW_INVERSE_VIDEO)
2742 x_set_mode_line_face_gc (s);
2743 s->stippled_p = s->face->stipple != 0;
2745 else if (s->hl == DRAW_CURSOR)
2747 x_set_cursor_gc (s);
2748 s->stippled_p = 0;
2750 else if (s->hl == DRAW_MOUSE_FACE)
2752 x_set_mouse_face_gc (s);
2753 s->stippled_p = s->face->stipple != 0;
2755 else if (s->hl == DRAW_IMAGE_RAISED
2756 || s->hl == DRAW_IMAGE_SUNKEN)
2758 s->gc = s->face->gc;
2759 s->stippled_p = s->face->stipple != 0;
2761 else
2763 s->gc = s->face->gc;
2764 s->stippled_p = s->face->stipple != 0;
2767 /* GC must have been set. */
2768 xassert (s->gc != 0);
2772 /* Return in *R the clipping rectangle for glyph string S. */
2774 static void
2775 x_get_glyph_string_clip_rect (s, r)
2776 struct glyph_string *s;
2777 XRectangle *r;
2779 if (s->row->full_width_p)
2781 /* Draw full-width. X coordinates are relative to S->w->left. */
2782 int canon_x = CANON_X_UNIT (s->f);
2784 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2785 r->width = XFASTINT (s->w->width) * canon_x;
2787 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2789 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2790 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2791 r->x -= width;
2794 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2796 /* Unless displaying a mode or menu bar line, which are always
2797 fully visible, clip to the visible part of the row. */
2798 if (s->w->pseudo_window_p)
2799 r->height = s->row->visible_height;
2800 else
2801 r->height = s->height;
2803 else
2805 /* This is a text line that may be partially visible. */
2806 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2807 r->width = window_box_width (s->w, s->area);
2808 r->height = s->row->visible_height;
2811 /* Don't use S->y for clipping because it doesn't take partially
2812 visible lines into account. For example, it can be negative for
2813 partially visible lines at the top of a window. */
2814 if (!s->row->full_width_p
2815 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2816 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2817 else
2818 r->y = max (0, s->row->y);
2820 /* If drawing a tool-bar window, draw it over the internal border
2821 at the top of the window. */
2822 if (s->w == XWINDOW (s->f->tool_bar_window))
2823 r->y -= s->f->output_data.x->internal_border_width;
2825 /* If S draws overlapping rows, it's sufficient to use the top and
2826 bottom of the window for clipping because this glyph string
2827 intentionally draws over other lines. */
2828 if (s->for_overlaps_p)
2830 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2831 r->height = window_text_bottom_y (s->w) - r->y;
2834 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2838 /* Set clipping for output of glyph string S. S may be part of a mode
2839 line or menu if we don't have X toolkit support. */
2841 static INLINE void
2842 x_set_glyph_string_clipping (s)
2843 struct glyph_string *s;
2845 XRectangle r;
2846 x_get_glyph_string_clip_rect (s, &r);
2847 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2851 /* Compute left and right overhang of glyph string S. If S is a glyph
2852 string for a composition, assume overhangs don't exist. */
2854 static INLINE void
2855 x_compute_glyph_string_overhangs (s)
2856 struct glyph_string *s;
2858 if (s->cmp == NULL
2859 && s->first_glyph->type == CHAR_GLYPH)
2861 XCharStruct cs;
2862 int direction, font_ascent, font_descent;
2863 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2864 &font_ascent, &font_descent, &cs);
2865 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2866 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2871 /* Compute overhangs and x-positions for glyph string S and its
2872 predecessors, or successors. X is the starting x-position for S.
2873 BACKWARD_P non-zero means process predecessors. */
2875 static void
2876 x_compute_overhangs_and_x (s, x, backward_p)
2877 struct glyph_string *s;
2878 int x;
2879 int backward_p;
2881 if (backward_p)
2883 while (s)
2885 x_compute_glyph_string_overhangs (s);
2886 x -= s->width;
2887 s->x = x;
2888 s = s->prev;
2891 else
2893 while (s)
2895 x_compute_glyph_string_overhangs (s);
2896 s->x = x;
2897 x += s->width;
2898 s = s->next;
2904 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2905 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2906 assumed to be zero. */
2908 static void
2909 x_get_glyph_overhangs (glyph, f, left, right)
2910 struct glyph *glyph;
2911 struct frame *f;
2912 int *left, *right;
2914 *left = *right = 0;
2916 if (glyph->type == CHAR_GLYPH)
2918 XFontStruct *font;
2919 struct face *face;
2920 struct font_info *font_info;
2921 XChar2b char2b;
2922 XCharStruct *pcm;
2924 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2925 font = face->font;
2926 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2927 if (font
2928 && (pcm = x_per_char_metric (font, &char2b)))
2930 if (pcm->rbearing > pcm->width)
2931 *right = pcm->rbearing - pcm->width;
2932 if (pcm->lbearing < 0)
2933 *left = -pcm->lbearing;
2939 /* Return the index of the first glyph preceding glyph string S that
2940 is overwritten by S because of S's left overhang. Value is -1
2941 if no glyphs are overwritten. */
2943 static int
2944 x_left_overwritten (s)
2945 struct glyph_string *s;
2947 int k;
2949 if (s->left_overhang)
2951 int x = 0, i;
2952 struct glyph *glyphs = s->row->glyphs[s->area];
2953 int first = s->first_glyph - glyphs;
2955 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2956 x -= glyphs[i].pixel_width;
2958 k = i + 1;
2960 else
2961 k = -1;
2963 return k;
2967 /* Return the index of the first glyph preceding glyph string S that
2968 is overwriting S because of its right overhang. Value is -1 if no
2969 glyph in front of S overwrites S. */
2971 static int
2972 x_left_overwriting (s)
2973 struct glyph_string *s;
2975 int i, k, x;
2976 struct glyph *glyphs = s->row->glyphs[s->area];
2977 int first = s->first_glyph - glyphs;
2979 k = -1;
2980 x = 0;
2981 for (i = first - 1; i >= 0; --i)
2983 int left, right;
2984 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2985 if (x + right > 0)
2986 k = i;
2987 x -= glyphs[i].pixel_width;
2990 return k;
2994 /* Return the index of the last glyph following glyph string S that is
2995 not overwritten by S because of S's right overhang. Value is -1 if
2996 no such glyph is found. */
2998 static int
2999 x_right_overwritten (s)
3000 struct glyph_string *s;
3002 int k = -1;
3004 if (s->right_overhang)
3006 int x = 0, i;
3007 struct glyph *glyphs = s->row->glyphs[s->area];
3008 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3009 int end = s->row->used[s->area];
3011 for (i = first; i < end && s->right_overhang > x; ++i)
3012 x += glyphs[i].pixel_width;
3014 k = i;
3017 return k;
3021 /* Return the index of the last glyph following glyph string S that
3022 overwrites S because of its left overhang. Value is negative
3023 if no such glyph is found. */
3025 static int
3026 x_right_overwriting (s)
3027 struct glyph_string *s;
3029 int i, k, x;
3030 int end = s->row->used[s->area];
3031 struct glyph *glyphs = s->row->glyphs[s->area];
3032 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3034 k = -1;
3035 x = 0;
3036 for (i = first; i < end; ++i)
3038 int left, right;
3039 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3040 if (x - left < 0)
3041 k = i;
3042 x += glyphs[i].pixel_width;
3045 return k;
3049 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3051 static INLINE void
3052 x_clear_glyph_string_rect (s, x, y, w, h)
3053 struct glyph_string *s;
3054 int x, y, w, h;
3056 XGCValues xgcv;
3057 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3058 XSetForeground (s->display, s->gc, xgcv.background);
3059 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3060 XSetForeground (s->display, s->gc, xgcv.foreground);
3064 /* Draw the background of glyph_string S. If S->background_filled_p
3065 is non-zero don't draw it. FORCE_P non-zero means draw the
3066 background even if it wouldn't be drawn normally. This is used
3067 when a string preceding S draws into the background of S, or S
3068 contains the first component of a composition. */
3070 static void
3071 x_draw_glyph_string_background (s, force_p)
3072 struct glyph_string *s;
3073 int force_p;
3075 /* Nothing to do if background has already been drawn or if it
3076 shouldn't be drawn in the first place. */
3077 if (!s->background_filled_p)
3079 if (s->stippled_p)
3081 /* Fill background with a stipple pattern. */
3082 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3083 XFillRectangle (s->display, s->window, s->gc, s->x,
3084 s->y + s->face->box_line_width,
3085 s->background_width,
3086 s->height - 2 * s->face->box_line_width);
3087 XSetFillStyle (s->display, s->gc, FillSolid);
3088 s->background_filled_p = 1;
3090 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3091 || s->font_not_found_p
3092 || s->extends_to_end_of_line_p
3093 || force_p)
3095 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3096 s->background_width,
3097 s->height - 2 * s->face->box_line_width);
3098 s->background_filled_p = 1;
3104 /* Draw the foreground of glyph string S. */
3106 static void
3107 x_draw_glyph_string_foreground (s)
3108 struct glyph_string *s;
3110 int i, x;
3112 /* If first glyph of S has a left box line, start drawing the text
3113 of S to the right of that box line. */
3114 if (s->face->box != FACE_NO_BOX
3115 && s->first_glyph->left_box_line_p)
3116 x = s->x + s->face->box_line_width;
3117 else
3118 x = s->x;
3120 /* Draw characters of S as rectangles if S's font could not be
3121 loaded. */
3122 if (s->font_not_found_p)
3124 for (i = 0; i < s->nchars; ++i)
3126 struct glyph *g = s->first_glyph + i;
3127 XDrawRectangle (s->display, s->window,
3128 s->gc, x, s->y, g->pixel_width - 1,
3129 s->height - 1);
3130 x += g->pixel_width;
3133 else
3135 char *char1b = (char *) s->char2b;
3136 int boff = s->font_info->baseline_offset;
3138 if (s->font_info->vertical_centering)
3139 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3141 /* If we can use 8-bit functions, condense S->char2b. */
3142 if (!s->two_byte_p)
3143 for (i = 0; i < s->nchars; ++i)
3144 char1b[i] = s->char2b[i].byte2;
3146 /* Draw text with XDrawString if background has already been
3147 filled. Otherwise, use XDrawImageString. (Note that
3148 XDrawImageString is usually faster than XDrawString.) Always
3149 use XDrawImageString when drawing the cursor so that there is
3150 no chance that characters under a box cursor are invisible. */
3151 if (s->for_overlaps_p
3152 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3154 /* Draw characters with 16-bit or 8-bit functions. */
3155 if (s->two_byte_p)
3156 XDrawString16 (s->display, s->window, s->gc, x,
3157 s->ybase - boff, s->char2b, s->nchars);
3158 else
3159 XDrawString (s->display, s->window, s->gc, x,
3160 s->ybase - boff, char1b, s->nchars);
3162 else
3164 if (s->two_byte_p)
3165 XDrawImageString16 (s->display, s->window, s->gc, x,
3166 s->ybase - boff, s->char2b, s->nchars);
3167 else
3168 XDrawImageString (s->display, s->window, s->gc, x,
3169 s->ybase - boff, char1b, s->nchars);
3174 /* Draw the foreground of composite glyph string S. */
3176 static void
3177 x_draw_composite_glyph_string_foreground (s)
3178 struct glyph_string *s;
3180 int i, x;
3182 /* If first glyph of S has a left box line, start drawing the text
3183 of S to the right of that box line. */
3184 if (s->face->box != FACE_NO_BOX
3185 && s->first_glyph->left_box_line_p)
3186 x = s->x + s->face->box_line_width;
3187 else
3188 x = s->x;
3190 /* S is a glyph string for a composition. S->gidx is the index of
3191 the first character drawn for glyphs of this composition.
3192 S->gidx == 0 means we are drawing the very first character of
3193 this composition. */
3195 /* Draw a rectangle for the composition if the font for the very
3196 first character of the composition could not be loaded. */
3197 if (s->font_not_found_p)
3199 if (s->gidx == 0)
3200 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3201 s->width - 1, s->height - 1);
3203 else
3205 for (i = 0; i < s->nchars; i++, ++s->gidx)
3206 XDrawString16 (s->display, s->window, s->gc,
3207 x + s->cmp->offsets[s->gidx * 2],
3208 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3209 s->char2b + i, 1);
3214 #ifdef USE_X_TOOLKIT
3216 static struct frame *x_frame_of_widget P_ ((Widget));
3219 /* Return the frame on which widget WIDGET is used.. Abort if frame
3220 cannot be determined. */
3222 static struct frame *
3223 x_frame_of_widget (widget)
3224 Widget widget;
3226 struct x_display_info *dpyinfo;
3227 Lisp_Object tail;
3228 struct frame *f;
3230 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3232 /* Find the top-level shell of the widget. Note that this function
3233 can be called when the widget is not yet realized, so XtWindow
3234 (widget) == 0. That's the reason we can't simply use
3235 x_any_window_to_frame. */
3236 while (!XtIsTopLevelShell (widget))
3237 widget = XtParent (widget);
3239 /* Look for a frame with that top-level widget. Allocate the color
3240 on that frame to get the right gamma correction value. */
3241 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3242 if (GC_FRAMEP (XCAR (tail))
3243 && (f = XFRAME (XCAR (tail)),
3244 (f->output_data.nothing != 1
3245 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3246 && f->output_data.x->widget == widget)
3247 return f;
3249 abort ();
3253 /* Allocate the color COLOR->pixel on the screen and display of
3254 widget WIDGET in colormap CMAP. If an exact match cannot be
3255 allocated, try the nearest color available. Value is non-zero
3256 if successful. This is called from lwlib. */
3259 x_alloc_nearest_color_for_widget (widget, cmap, color)
3260 Widget widget;
3261 Colormap cmap;
3262 XColor *color;
3264 struct frame *f = x_frame_of_widget (widget);
3265 return x_alloc_nearest_color (f, cmap, color);
3269 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3270 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3271 If this produces the same color as PIXEL, try a color where all RGB
3272 values have DELTA added. Return the allocated color in *PIXEL.
3273 DISPLAY is the X display, CMAP is the colormap to operate on.
3274 Value is non-zero if successful. */
3277 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3278 Widget widget;
3279 Display *display;
3280 Colormap cmap;
3281 unsigned long *pixel;
3282 double factor;
3283 int delta;
3285 struct frame *f = x_frame_of_widget (widget);
3286 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3290 #endif /* USE_X_TOOLKIT */
3293 /* Value is an array of XColor structures for the contents of the
3294 color map of frame F. Set *NCELLS to the size of the array.
3295 Note that this probably shouldn't be called for large color maps,
3296 say a 24-bit TrueColor map. */
3298 static const XColor *
3299 x_color_cells (f, ncells)
3300 struct frame *f;
3301 int *ncells;
3303 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3305 if (dpyinfo->color_cells == NULL)
3307 Display *display = FRAME_X_DISPLAY (f);
3308 Screen *screen = FRAME_X_SCREEN (f);
3309 int i;
3311 dpyinfo->ncolor_cells
3312 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3313 dpyinfo->color_cells
3314 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3315 * sizeof *dpyinfo->color_cells);
3317 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3318 dpyinfo->color_cells[i].pixel = i;
3320 XQueryColors (display, FRAME_X_COLORMAP (f),
3321 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3324 *ncells = dpyinfo->ncolor_cells;
3325 return dpyinfo->color_cells;
3329 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3330 colors in COLORS. Use cached information, if available. */
3332 void
3333 x_query_colors (f, colors, ncolors)
3334 struct frame *f;
3335 XColor *colors;
3336 int ncolors;
3338 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3340 if (dpyinfo->color_cells)
3342 int i;
3343 for (i = 0; i < ncolors; ++i)
3345 unsigned long pixel = colors[i].pixel;
3346 xassert (pixel < dpyinfo->ncolor_cells);
3347 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3348 colors[i] = dpyinfo->color_cells[pixel];
3351 else
3352 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3356 /* On frame F, translate pixel color to RGB values for the color in
3357 COLOR. Use cached information, if available. */
3359 void
3360 x_query_color (f, color)
3361 struct frame *f;
3362 XColor *color;
3364 x_query_colors (f, color, 1);
3368 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3369 CMAP. If an exact match can't be allocated, try the nearest color
3370 available. Value is non-zero if successful. Set *COLOR to the
3371 color allocated. */
3374 x_alloc_nearest_color (f, cmap, color)
3375 struct frame *f;
3376 Colormap cmap;
3377 XColor *color;
3379 Display *display = FRAME_X_DISPLAY (f);
3380 Screen *screen = FRAME_X_SCREEN (f);
3381 int rc;
3383 gamma_correct (f, color);
3384 rc = XAllocColor (display, cmap, color);
3385 if (rc == 0)
3387 /* If we got to this point, the colormap is full, so we're going
3388 to try to get the next closest color. The algorithm used is
3389 a least-squares matching, which is what X uses for closest
3390 color matching with StaticColor visuals. */
3391 int nearest, i;
3392 unsigned long nearest_delta = ~0;
3393 int ncells;
3394 const XColor *cells = x_color_cells (f, &ncells);
3396 for (nearest = i = 0; i < ncells; ++i)
3398 long dred = (color->red >> 8) - (cells[i].red >> 8);
3399 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3400 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3401 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3403 if (delta < nearest_delta)
3405 nearest = i;
3406 nearest_delta = delta;
3410 color->red = cells[nearest].red;
3411 color->green = cells[nearest].green;
3412 color->blue = cells[nearest].blue;
3413 rc = XAllocColor (display, cmap, color);
3415 else
3417 /* If allocation succeeded, and the allocated pixel color is not
3418 equal to a cached pixel color recorded earlier, there was a
3419 change in the colormap, so clear the color cache. */
3420 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3421 XColor *cached_color;
3423 if (dpyinfo->color_cells
3424 && (cached_color = &dpyinfo->color_cells[color->pixel],
3425 (cached_color->red != color->red
3426 || cached_color->blue != color->blue
3427 || cached_color->green != color->green)))
3429 xfree (dpyinfo->color_cells);
3430 dpyinfo->color_cells = NULL;
3431 dpyinfo->ncolor_cells = 0;
3435 #ifdef DEBUG_X_COLORS
3436 if (rc)
3437 register_color (color->pixel);
3438 #endif /* DEBUG_X_COLORS */
3440 return rc;
3444 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3445 It's necessary to do this instead of just using PIXEL directly to
3446 get color reference counts right. */
3448 unsigned long
3449 x_copy_color (f, pixel)
3450 struct frame *f;
3451 unsigned long pixel;
3453 XColor color;
3455 color.pixel = pixel;
3456 BLOCK_INPUT;
3457 x_query_color (f, &color);
3458 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3459 UNBLOCK_INPUT;
3460 #ifdef DEBUG_X_COLORS
3461 register_color (pixel);
3462 #endif
3463 return color.pixel;
3467 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3468 It's necessary to do this instead of just using PIXEL directly to
3469 get color reference counts right. */
3471 unsigned long
3472 x_copy_dpy_color (dpy, cmap, pixel)
3473 Display *dpy;
3474 Colormap cmap;
3475 unsigned long pixel;
3477 XColor color;
3479 color.pixel = pixel;
3480 BLOCK_INPUT;
3481 XQueryColor (dpy, cmap, &color);
3482 XAllocColor (dpy, cmap, &color);
3483 UNBLOCK_INPUT;
3484 #ifdef DEBUG_X_COLORS
3485 register_color (pixel);
3486 #endif
3487 return color.pixel;
3491 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3492 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3493 If this produces the same color as PIXEL, try a color where all RGB
3494 values have DELTA added. Return the allocated color in *PIXEL.
3495 DISPLAY is the X display, CMAP is the colormap to operate on.
3496 Value is non-zero if successful. */
3498 static int
3499 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3500 struct frame *f;
3501 Display *display;
3502 Colormap cmap;
3503 unsigned long *pixel;
3504 double factor;
3505 int delta;
3507 XColor color, new;
3508 int success_p;
3510 /* Get RGB color values. */
3511 color.pixel = *pixel;
3512 x_query_color (f, &color);
3514 /* Change RGB values by specified FACTOR. Avoid overflow! */
3515 xassert (factor >= 0);
3516 new.red = min (0xffff, factor * color.red);
3517 new.green = min (0xffff, factor * color.green);
3518 new.blue = min (0xffff, factor * color.blue);
3520 /* Try to allocate the color. */
3521 success_p = x_alloc_nearest_color (f, cmap, &new);
3522 if (success_p)
3524 if (new.pixel == *pixel)
3526 /* If we end up with the same color as before, try adding
3527 delta to the RGB values. */
3528 x_free_colors (f, &new.pixel, 1);
3530 new.red = min (0xffff, delta + color.red);
3531 new.green = min (0xffff, delta + color.green);
3532 new.blue = min (0xffff, delta + color.blue);
3533 success_p = x_alloc_nearest_color (f, cmap, &new);
3535 else
3536 success_p = 1;
3537 *pixel = new.pixel;
3540 return success_p;
3544 /* Set up the foreground color for drawing relief lines of glyph
3545 string S. RELIEF is a pointer to a struct relief containing the GC
3546 with which lines will be drawn. Use a color that is FACTOR or
3547 DELTA lighter or darker than the relief's background which is found
3548 in S->f->output_data.x->relief_background. If such a color cannot
3549 be allocated, use DEFAULT_PIXEL, instead. */
3551 static void
3552 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3553 struct frame *f;
3554 struct relief *relief;
3555 double factor;
3556 int delta;
3557 unsigned long default_pixel;
3559 XGCValues xgcv;
3560 struct x_output *di = f->output_data.x;
3561 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3562 unsigned long pixel;
3563 unsigned long background = di->relief_background;
3564 Colormap cmap = FRAME_X_COLORMAP (f);
3565 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3566 Display *dpy = FRAME_X_DISPLAY (f);
3568 xgcv.graphics_exposures = False;
3569 xgcv.line_width = 1;
3571 /* Free previously allocated color. The color cell will be reused
3572 when it has been freed as many times as it was allocated, so this
3573 doesn't affect faces using the same colors. */
3574 if (relief->gc
3575 && relief->allocated_p)
3577 x_free_colors (f, &relief->pixel, 1);
3578 relief->allocated_p = 0;
3581 /* Allocate new color. */
3582 xgcv.foreground = default_pixel;
3583 pixel = background;
3584 if (dpyinfo->n_planes != 1
3585 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3587 relief->allocated_p = 1;
3588 xgcv.foreground = relief->pixel = pixel;
3591 if (relief->gc == 0)
3593 xgcv.stipple = dpyinfo->gray;
3594 mask |= GCStipple;
3595 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3597 else
3598 XChangeGC (dpy, relief->gc, mask, &xgcv);
3602 /* Set up colors for the relief lines around glyph string S. */
3604 static void
3605 x_setup_relief_colors (s)
3606 struct glyph_string *s;
3608 struct x_output *di = s->f->output_data.x;
3609 unsigned long color;
3611 if (s->face->use_box_color_for_shadows_p)
3612 color = s->face->box_color;
3613 else
3615 XGCValues xgcv;
3617 /* Get the background color of the face. */
3618 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3619 color = xgcv.background;
3622 if (di->white_relief.gc == 0
3623 || color != di->relief_background)
3625 di->relief_background = color;
3626 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3627 WHITE_PIX_DEFAULT (s->f));
3628 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3629 BLACK_PIX_DEFAULT (s->f));
3634 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3635 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3636 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3637 relief. LEFT_P non-zero means draw a relief on the left side of
3638 the rectangle. RIGHT_P non-zero means draw a relief on the right
3639 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3640 when drawing. */
3642 static void
3643 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3644 raised_p, left_p, right_p, clip_rect)
3645 struct frame *f;
3646 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3647 XRectangle *clip_rect;
3649 int i;
3650 GC gc;
3652 if (raised_p)
3653 gc = f->output_data.x->white_relief.gc;
3654 else
3655 gc = f->output_data.x->black_relief.gc;
3656 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3658 /* Top. */
3659 for (i = 0; i < width; ++i)
3660 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3661 left_x + i * left_p, top_y + i,
3662 right_x + 1 - i * right_p, top_y + i);
3664 /* Left. */
3665 if (left_p)
3666 for (i = 0; i < width; ++i)
3667 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3668 left_x + i, top_y + i, left_x + i, bottom_y - i);
3670 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3671 if (raised_p)
3672 gc = f->output_data.x->black_relief.gc;
3673 else
3674 gc = f->output_data.x->white_relief.gc;
3675 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3677 /* Bottom. */
3678 for (i = 0; i < width; ++i)
3679 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3680 left_x + i * left_p, bottom_y - i,
3681 right_x + 1 - i * right_p, bottom_y - i);
3683 /* Right. */
3684 if (right_p)
3685 for (i = 0; i < width; ++i)
3686 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3687 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3689 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3693 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3694 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3695 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3696 left side of the rectangle. RIGHT_P non-zero means draw a line
3697 on the right side of the rectangle. CLIP_RECT is the clipping
3698 rectangle to use when drawing. */
3700 static void
3701 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3702 left_p, right_p, clip_rect)
3703 struct glyph_string *s;
3704 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3705 XRectangle *clip_rect;
3707 XGCValues xgcv;
3709 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3710 XSetForeground (s->display, s->gc, s->face->box_color);
3711 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3713 /* Top. */
3714 XFillRectangle (s->display, s->window, s->gc,
3715 left_x, top_y, right_x - left_x + 1, width);
3717 /* Left. */
3718 if (left_p)
3719 XFillRectangle (s->display, s->window, s->gc,
3720 left_x, top_y, width, bottom_y - top_y + 1);
3722 /* Bottom. */
3723 XFillRectangle (s->display, s->window, s->gc,
3724 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3726 /* Right. */
3727 if (right_p)
3728 XFillRectangle (s->display, s->window, s->gc,
3729 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3731 XSetForeground (s->display, s->gc, xgcv.foreground);
3732 XSetClipMask (s->display, s->gc, None);
3736 /* Draw a box around glyph string S. */
3738 static void
3739 x_draw_glyph_string_box (s)
3740 struct glyph_string *s;
3742 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3743 int left_p, right_p;
3744 struct glyph *last_glyph;
3745 XRectangle clip_rect;
3747 last_x = window_box_right (s->w, s->area);
3748 if (s->row->full_width_p
3749 && !s->w->pseudo_window_p)
3751 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3752 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3753 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3756 /* The glyph that may have a right box line. */
3757 last_glyph = (s->cmp || s->img
3758 ? s->first_glyph
3759 : s->first_glyph + s->nchars - 1);
3761 width = s->face->box_line_width;
3762 raised_p = s->face->box == FACE_RAISED_BOX;
3763 left_x = s->x;
3764 right_x = ((s->row->full_width_p
3765 ? last_x - 1
3766 : min (last_x, s->x + s->background_width) - 1));
3767 top_y = s->y;
3768 bottom_y = top_y + s->height - 1;
3770 left_p = (s->first_glyph->left_box_line_p
3771 || (s->hl == DRAW_MOUSE_FACE
3772 && (s->prev == NULL
3773 || s->prev->hl != s->hl)));
3774 right_p = (last_glyph->right_box_line_p
3775 || (s->hl == DRAW_MOUSE_FACE
3776 && (s->next == NULL
3777 || s->next->hl != s->hl)));
3779 x_get_glyph_string_clip_rect (s, &clip_rect);
3781 if (s->face->box == FACE_SIMPLE_BOX)
3782 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3783 left_p, right_p, &clip_rect);
3784 else
3786 x_setup_relief_colors (s);
3787 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3788 width, raised_p, left_p, right_p, &clip_rect);
3793 /* Draw foreground of image glyph string S. */
3795 static void
3796 x_draw_image_foreground (s)
3797 struct glyph_string *s;
3799 int x;
3800 int y = s->ybase - image_ascent (s->img, s->face);
3802 /* If first glyph of S has a left box line, start drawing it to the
3803 right of that line. */
3804 if (s->face->box != FACE_NO_BOX
3805 && s->first_glyph->left_box_line_p)
3806 x = s->x + s->face->box_line_width;
3807 else
3808 x = s->x;
3810 /* If there is a margin around the image, adjust x- and y-position
3811 by that margin. */
3812 if (s->img->margin)
3814 x += s->img->margin;
3815 y += s->img->margin;
3818 if (s->img->pixmap)
3820 if (s->img->mask)
3822 /* We can't set both a clip mask and use XSetClipRectangles
3823 because the latter also sets a clip mask. We also can't
3824 trust on the shape extension to be available
3825 (XShapeCombineRegion). So, compute the rectangle to draw
3826 manually. */
3827 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3828 | GCFunction);
3829 XGCValues xgcv;
3830 XRectangle clip_rect, image_rect, r;
3832 xgcv.clip_mask = s->img->mask;
3833 xgcv.clip_x_origin = x;
3834 xgcv.clip_y_origin = y;
3835 xgcv.function = GXcopy;
3836 XChangeGC (s->display, s->gc, mask, &xgcv);
3838 x_get_glyph_string_clip_rect (s, &clip_rect);
3839 image_rect.x = x;
3840 image_rect.y = y;
3841 image_rect.width = s->img->width;
3842 image_rect.height = s->img->height;
3843 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3844 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3845 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3847 else
3849 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3850 XGCValues xgcv;
3851 XRectangle clip_rect, image_rect, r;
3853 x_get_glyph_string_clip_rect (s, &clip_rect);
3854 image_rect.x = x;
3855 image_rect.y = y;
3856 image_rect.width = s->img->width;
3857 image_rect.height = s->img->height;
3858 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3859 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3860 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3862 /* When the image has a mask, we can expect that at
3863 least part of a mouse highlight or a block cursor will
3864 be visible. If the image doesn't have a mask, make
3865 a block cursor visible by drawing a rectangle around
3866 the image. I believe it's looking better if we do
3867 nothing here for mouse-face. */
3868 if (s->hl == DRAW_CURSOR)
3869 XDrawRectangle (s->display, s->window, s->gc, x, y,
3870 s->img->width - 1, s->img->height - 1);
3873 else
3874 /* Draw a rectangle if image could not be loaded. */
3875 XDrawRectangle (s->display, s->window, s->gc, x, y,
3876 s->img->width - 1, s->img->height - 1);
3880 /* Draw a relief around the image glyph string S. */
3882 static void
3883 x_draw_image_relief (s)
3884 struct glyph_string *s;
3886 int x0, y0, x1, y1, thick, raised_p;
3887 XRectangle r;
3888 int x;
3889 int y = s->ybase - image_ascent (s->img, s->face);
3891 /* If first glyph of S has a left box line, start drawing it to the
3892 right of that line. */
3893 if (s->face->box != FACE_NO_BOX
3894 && s->first_glyph->left_box_line_p)
3895 x = s->x + s->face->box_line_width;
3896 else
3897 x = s->x;
3899 /* If there is a margin around the image, adjust x- and y-position
3900 by that margin. */
3901 if (s->img->margin)
3903 x += s->img->margin;
3904 y += s->img->margin;
3907 if (s->hl == DRAW_IMAGE_SUNKEN
3908 || s->hl == DRAW_IMAGE_RAISED)
3910 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3911 raised_p = s->hl == DRAW_IMAGE_RAISED;
3913 else
3915 thick = abs (s->img->relief);
3916 raised_p = s->img->relief > 0;
3919 x0 = x - thick;
3920 y0 = y - thick;
3921 x1 = x + s->img->width + thick - 1;
3922 y1 = y + s->img->height + thick - 1;
3924 x_setup_relief_colors (s);
3925 x_get_glyph_string_clip_rect (s, &r);
3926 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3930 /* Draw the foreground of image glyph string S to PIXMAP. */
3932 static void
3933 x_draw_image_foreground_1 (s, pixmap)
3934 struct glyph_string *s;
3935 Pixmap pixmap;
3937 int x;
3938 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3940 /* If first glyph of S has a left box line, start drawing it to the
3941 right of that line. */
3942 if (s->face->box != FACE_NO_BOX
3943 && s->first_glyph->left_box_line_p)
3944 x = s->face->box_line_width;
3945 else
3946 x = 0;
3948 /* If there is a margin around the image, adjust x- and y-position
3949 by that margin. */
3950 if (s->img->margin)
3952 x += s->img->margin;
3953 y += s->img->margin;
3956 if (s->img->pixmap)
3958 if (s->img->mask)
3960 /* We can't set both a clip mask and use XSetClipRectangles
3961 because the latter also sets a clip mask. We also can't
3962 trust on the shape extension to be available
3963 (XShapeCombineRegion). So, compute the rectangle to draw
3964 manually. */
3965 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3966 | GCFunction);
3967 XGCValues xgcv;
3969 xgcv.clip_mask = s->img->mask;
3970 xgcv.clip_x_origin = x;
3971 xgcv.clip_y_origin = y;
3972 xgcv.function = GXcopy;
3973 XChangeGC (s->display, s->gc, mask, &xgcv);
3975 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3976 0, 0, s->img->width, s->img->height, x, y);
3977 XSetClipMask (s->display, s->gc, None);
3979 else
3981 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3982 0, 0, s->img->width, s->img->height, x, y);
3984 /* When the image has a mask, we can expect that at
3985 least part of a mouse highlight or a block cursor will
3986 be visible. If the image doesn't have a mask, make
3987 a block cursor visible by drawing a rectangle around
3988 the image. I believe it's looking better if we do
3989 nothing here for mouse-face. */
3990 if (s->hl == DRAW_CURSOR)
3991 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3992 s->img->width - 1, s->img->height - 1);
3995 else
3996 /* Draw a rectangle if image could not be loaded. */
3997 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3998 s->img->width - 1, s->img->height - 1);
4002 /* Draw part of the background of glyph string S. X, Y, W, and H
4003 give the rectangle to draw. */
4005 static void
4006 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4007 struct glyph_string *s;
4008 int x, y, w, h;
4010 if (s->stippled_p)
4012 /* Fill background with a stipple pattern. */
4013 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4014 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4015 XSetFillStyle (s->display, s->gc, FillSolid);
4017 else
4018 x_clear_glyph_string_rect (s, x, y, w, h);
4022 /* Draw image glyph string S.
4024 s->y
4025 s->x +-------------------------
4026 | s->face->box
4028 | +-------------------------
4029 | | s->img->margin
4031 | | +-------------------
4032 | | | the image
4036 static void
4037 x_draw_image_glyph_string (s)
4038 struct glyph_string *s;
4040 int x, y;
4041 int box_line_width = s->face->box_line_width;
4042 int margin = s->img->margin;
4043 int height;
4044 Pixmap pixmap = None;
4046 height = s->height - 2 * box_line_width;
4048 /* Fill background with face under the image. Do it only if row is
4049 taller than image or if image has a clip mask to reduce
4050 flickering. */
4051 s->stippled_p = s->face->stipple != 0;
4052 if (height > s->img->height
4053 || margin
4054 || s->img->mask
4055 || s->img->pixmap == 0
4056 || s->width != s->background_width)
4058 if (box_line_width && s->first_glyph->left_box_line_p)
4059 x = s->x + box_line_width;
4060 else
4061 x = s->x;
4063 y = s->y + box_line_width;
4065 if (s->img->mask)
4067 /* Create a pixmap as large as the glyph string. Fill it
4068 with the background color. Copy the image to it, using
4069 its mask. Copy the temporary pixmap to the display. */
4070 Screen *screen = FRAME_X_SCREEN (s->f);
4071 int depth = DefaultDepthOfScreen (screen);
4073 /* Create a pixmap as large as the glyph string. */
4074 pixmap = XCreatePixmap (s->display, s->window,
4075 s->background_width,
4076 s->height, depth);
4078 /* Don't clip in the following because we're working on the
4079 pixmap. */
4080 XSetClipMask (s->display, s->gc, None);
4082 /* Fill the pixmap with the background color/stipple. */
4083 if (s->stippled_p)
4085 /* Fill background with a stipple pattern. */
4086 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4087 XFillRectangle (s->display, pixmap, s->gc,
4088 0, 0, s->background_width, s->height);
4089 XSetFillStyle (s->display, s->gc, FillSolid);
4091 else
4093 XGCValues xgcv;
4094 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4095 &xgcv);
4096 XSetForeground (s->display, s->gc, xgcv.background);
4097 XFillRectangle (s->display, pixmap, s->gc,
4098 0, 0, s->background_width, s->height);
4099 XSetForeground (s->display, s->gc, xgcv.foreground);
4102 else
4103 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4105 s->background_filled_p = 1;
4108 /* Draw the foreground. */
4109 if (pixmap != None)
4111 x_draw_image_foreground_1 (s, pixmap);
4112 x_set_glyph_string_clipping (s);
4113 XCopyArea (s->display, pixmap, s->window, s->gc,
4114 0, 0, s->background_width, s->height, s->x, s->y);
4115 XFreePixmap (s->display, pixmap);
4117 else
4118 x_draw_image_foreground (s);
4120 /* If we must draw a relief around the image, do it. */
4121 if (s->img->relief
4122 || s->hl == DRAW_IMAGE_RAISED
4123 || s->hl == DRAW_IMAGE_SUNKEN)
4124 x_draw_image_relief (s);
4128 /* Draw stretch glyph string S. */
4130 static void
4131 x_draw_stretch_glyph_string (s)
4132 struct glyph_string *s;
4134 xassert (s->first_glyph->type == STRETCH_GLYPH);
4135 s->stippled_p = s->face->stipple != 0;
4137 if (s->hl == DRAW_CURSOR
4138 && !x_stretch_cursor_p)
4140 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4141 as wide as the stretch glyph. */
4142 int width = min (CANON_X_UNIT (s->f), s->background_width);
4144 /* Draw cursor. */
4145 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4147 /* Clear rest using the GC of the original non-cursor face. */
4148 if (width < s->background_width)
4150 GC gc = s->face->gc;
4151 int x = s->x + width, y = s->y;
4152 int w = s->background_width - width, h = s->height;
4153 XRectangle r;
4155 x_get_glyph_string_clip_rect (s, &r);
4156 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4158 if (s->face->stipple)
4160 /* Fill background with a stipple pattern. */
4161 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4162 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4163 XSetFillStyle (s->display, gc, FillSolid);
4165 else
4167 XGCValues xgcv;
4168 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4169 XSetForeground (s->display, gc, xgcv.background);
4170 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4171 XSetForeground (s->display, gc, xgcv.foreground);
4175 else
4176 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4177 s->height);
4179 s->background_filled_p = 1;
4183 /* Draw glyph string S. */
4185 static void
4186 x_draw_glyph_string (s)
4187 struct glyph_string *s;
4189 /* If S draws into the background of its successor, draw the
4190 background of the successor first so that S can draw into it.
4191 This makes S->next use XDrawString instead of XDrawImageString. */
4192 if (s->next && s->right_overhang && !s->for_overlaps_p)
4194 xassert (s->next->img == NULL);
4195 x_set_glyph_string_gc (s->next);
4196 x_set_glyph_string_clipping (s->next);
4197 x_draw_glyph_string_background (s->next, 1);
4200 /* Set up S->gc, set clipping and draw S. */
4201 x_set_glyph_string_gc (s);
4202 x_set_glyph_string_clipping (s);
4204 switch (s->first_glyph->type)
4206 case IMAGE_GLYPH:
4207 x_draw_image_glyph_string (s);
4208 break;
4210 case STRETCH_GLYPH:
4211 x_draw_stretch_glyph_string (s);
4212 break;
4214 case CHAR_GLYPH:
4215 if (s->for_overlaps_p)
4216 s->background_filled_p = 1;
4217 else
4218 x_draw_glyph_string_background (s, 0);
4219 x_draw_glyph_string_foreground (s);
4220 break;
4222 case COMPOSITE_GLYPH:
4223 if (s->for_overlaps_p || s->gidx > 0)
4224 s->background_filled_p = 1;
4225 else
4226 x_draw_glyph_string_background (s, 1);
4227 x_draw_composite_glyph_string_foreground (s);
4228 break;
4230 default:
4231 abort ();
4234 if (!s->for_overlaps_p)
4236 /* Draw underline. */
4237 if (s->face->underline_p)
4239 unsigned long tem, h;
4240 int y;
4242 /* Get the underline thickness. Default is 1 pixel. */
4243 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4244 h = 1;
4246 /* Get the underline position. This is the recommended
4247 vertical offset in pixels from the baseline to the top of
4248 the underline. This is a signed value according to the
4249 specs, and its default is
4251 ROUND ((maximum descent) / 2), with
4252 ROUND(x) = floor (x + 0.5) */
4254 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4255 y = s->ybase + (long) tem;
4256 else if (s->face->font)
4257 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4258 else
4259 y = s->height - h;
4261 if (s->face->underline_defaulted_p)
4262 XFillRectangle (s->display, s->window, s->gc,
4263 s->x, y, s->width, h);
4264 else
4266 XGCValues xgcv;
4267 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4268 XSetForeground (s->display, s->gc, s->face->underline_color);
4269 XFillRectangle (s->display, s->window, s->gc,
4270 s->x, y, s->width, h);
4271 XSetForeground (s->display, s->gc, xgcv.foreground);
4275 /* Draw overline. */
4276 if (s->face->overline_p)
4278 unsigned long dy = 0, h = 1;
4280 if (s->face->overline_color_defaulted_p)
4281 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4282 s->width, h);
4283 else
4285 XGCValues xgcv;
4286 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4287 XSetForeground (s->display, s->gc, s->face->overline_color);
4288 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4289 s->width, h);
4290 XSetForeground (s->display, s->gc, xgcv.foreground);
4294 /* Draw strike-through. */
4295 if (s->face->strike_through_p)
4297 unsigned long h = 1;
4298 unsigned long dy = (s->height - h) / 2;
4300 if (s->face->strike_through_color_defaulted_p)
4301 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4302 s->width, h);
4303 else
4305 XGCValues xgcv;
4306 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4307 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4308 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4309 s->width, h);
4310 XSetForeground (s->display, s->gc, xgcv.foreground);
4314 /* Draw relief. */
4315 if (s->face->box != FACE_NO_BOX)
4316 x_draw_glyph_string_box (s);
4319 /* Reset clipping. */
4320 XSetClipMask (s->display, s->gc, None);
4324 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4325 struct face **, int));
4328 /* Fill glyph string S with composition components specified by S->cmp.
4330 FACES is an array of faces for all components of this composition.
4331 S->gidx is the index of the first component for S.
4332 OVERLAPS_P non-zero means S should draw the foreground only, and
4333 use its physical height for clipping.
4335 Value is the index of a component not in S. */
4337 static int
4338 x_fill_composite_glyph_string (s, faces, overlaps_p)
4339 struct glyph_string *s;
4340 struct face **faces;
4341 int overlaps_p;
4343 int i;
4345 xassert (s);
4347 s->for_overlaps_p = overlaps_p;
4349 s->face = faces[s->gidx];
4350 s->font = s->face->font;
4351 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4353 /* For all glyphs of this composition, starting at the offset
4354 S->gidx, until we reach the end of the definition or encounter a
4355 glyph that requires the different face, add it to S. */
4356 ++s->nchars;
4357 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4358 ++s->nchars;
4360 /* All glyph strings for the same composition has the same width,
4361 i.e. the width set for the first component of the composition. */
4363 s->width = s->first_glyph->pixel_width;
4365 /* If the specified font could not be loaded, use the frame's
4366 default font, but record the fact that we couldn't load it in
4367 the glyph string so that we can draw rectangles for the
4368 characters of the glyph string. */
4369 if (s->font == NULL)
4371 s->font_not_found_p = 1;
4372 s->font = FRAME_FONT (s->f);
4375 /* Adjust base line for subscript/superscript text. */
4376 s->ybase += s->first_glyph->voffset;
4378 xassert (s->face && s->face->gc);
4380 /* This glyph string must always be drawn with 16-bit functions. */
4381 s->two_byte_p = 1;
4383 return s->gidx + s->nchars;
4387 /* Fill glyph string S from a sequence of character glyphs.
4389 FACE_ID is the face id of the string. START is the index of the
4390 first glyph to consider, END is the index of the last + 1.
4391 OVERLAPS_P non-zero means S should draw the foreground only, and
4392 use its physical height for clipping.
4394 Value is the index of the first glyph not in S. */
4396 static int
4397 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4398 struct glyph_string *s;
4399 int face_id;
4400 int start, end, overlaps_p;
4402 struct glyph *glyph, *last;
4403 int voffset;
4404 int glyph_not_available_p;
4406 xassert (s->f == XFRAME (s->w->frame));
4407 xassert (s->nchars == 0);
4408 xassert (start >= 0 && end > start);
4410 s->for_overlaps_p = overlaps_p,
4411 glyph = s->row->glyphs[s->area] + start;
4412 last = s->row->glyphs[s->area] + end;
4413 voffset = glyph->voffset;
4415 glyph_not_available_p = glyph->glyph_not_available_p;
4417 while (glyph < last
4418 && glyph->type == CHAR_GLYPH
4419 && glyph->voffset == voffset
4420 /* Same face id implies same font, nowadays. */
4421 && glyph->face_id == face_id
4422 && glyph->glyph_not_available_p == glyph_not_available_p)
4424 int two_byte_p;
4426 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4427 s->char2b + s->nchars,
4428 &two_byte_p);
4429 s->two_byte_p = two_byte_p;
4430 ++s->nchars;
4431 xassert (s->nchars <= end - start);
4432 s->width += glyph->pixel_width;
4433 ++glyph;
4436 s->font = s->face->font;
4437 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4439 /* If the specified font could not be loaded, use the frame's font,
4440 but record the fact that we couldn't load it in
4441 S->font_not_found_p so that we can draw rectangles for the
4442 characters of the glyph string. */
4443 if (s->font == NULL || glyph_not_available_p)
4445 s->font_not_found_p = 1;
4446 s->font = FRAME_FONT (s->f);
4449 /* Adjust base line for subscript/superscript text. */
4450 s->ybase += voffset;
4452 xassert (s->face && s->face->gc);
4453 return glyph - s->row->glyphs[s->area];
4457 /* Fill glyph string S from image glyph S->first_glyph. */
4459 static void
4460 x_fill_image_glyph_string (s)
4461 struct glyph_string *s;
4463 xassert (s->first_glyph->type == IMAGE_GLYPH);
4464 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4465 xassert (s->img);
4466 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4467 s->font = s->face->font;
4468 s->width = s->first_glyph->pixel_width;
4470 /* Adjust base line for subscript/superscript text. */
4471 s->ybase += s->first_glyph->voffset;
4475 /* Fill glyph string S from a sequence of stretch glyphs.
4477 ROW is the glyph row in which the glyphs are found, AREA is the
4478 area within the row. START is the index of the first glyph to
4479 consider, END is the index of the last + 1.
4481 Value is the index of the first glyph not in S. */
4483 static int
4484 x_fill_stretch_glyph_string (s, row, area, start, end)
4485 struct glyph_string *s;
4486 struct glyph_row *row;
4487 enum glyph_row_area area;
4488 int start, end;
4490 struct glyph *glyph, *last;
4491 int voffset, face_id;
4493 xassert (s->first_glyph->type == STRETCH_GLYPH);
4495 glyph = s->row->glyphs[s->area] + start;
4496 last = s->row->glyphs[s->area] + end;
4497 face_id = glyph->face_id;
4498 s->face = FACE_FROM_ID (s->f, face_id);
4499 s->font = s->face->font;
4500 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4501 s->width = glyph->pixel_width;
4502 voffset = glyph->voffset;
4504 for (++glyph;
4505 (glyph < last
4506 && glyph->type == STRETCH_GLYPH
4507 && glyph->voffset == voffset
4508 && glyph->face_id == face_id);
4509 ++glyph)
4510 s->width += glyph->pixel_width;
4512 /* Adjust base line for subscript/superscript text. */
4513 s->ybase += voffset;
4515 xassert (s->face && s->face->gc);
4516 return glyph - s->row->glyphs[s->area];
4520 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4521 of XChar2b structures for S; it can't be allocated in
4522 x_init_glyph_string because it must be allocated via `alloca'. W
4523 is the window on which S is drawn. ROW and AREA are the glyph row
4524 and area within the row from which S is constructed. START is the
4525 index of the first glyph structure covered by S. HL is a
4526 face-override for drawing S. */
4528 static void
4529 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4530 struct glyph_string *s;
4531 XChar2b *char2b;
4532 struct window *w;
4533 struct glyph_row *row;
4534 enum glyph_row_area area;
4535 int start;
4536 enum draw_glyphs_face hl;
4538 bzero (s, sizeof *s);
4539 s->w = w;
4540 s->f = XFRAME (w->frame);
4541 s->display = FRAME_X_DISPLAY (s->f);
4542 s->window = FRAME_X_WINDOW (s->f);
4543 s->char2b = char2b;
4544 s->hl = hl;
4545 s->row = row;
4546 s->area = area;
4547 s->first_glyph = row->glyphs[area] + start;
4548 s->height = row->height;
4549 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4551 /* Display the internal border below the tool-bar window. */
4552 if (s->w == XWINDOW (s->f->tool_bar_window))
4553 s->y -= s->f->output_data.x->internal_border_width;
4555 s->ybase = s->y + row->ascent;
4559 /* Set background width of glyph string S. START is the index of the
4560 first glyph following S. LAST_X is the right-most x-position + 1
4561 in the drawing area. */
4563 static INLINE void
4564 x_set_glyph_string_background_width (s, start, last_x)
4565 struct glyph_string *s;
4566 int start;
4567 int last_x;
4569 /* If the face of this glyph string has to be drawn to the end of
4570 the drawing area, set S->extends_to_end_of_line_p. */
4571 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4573 if (start == s->row->used[s->area]
4574 && s->hl == DRAW_NORMAL_TEXT
4575 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4576 || s->face->background != default_face->background
4577 || s->face->stipple != default_face->stipple))
4578 s->extends_to_end_of_line_p = 1;
4580 /* If S extends its face to the end of the line, set its
4581 background_width to the distance to the right edge of the drawing
4582 area. */
4583 if (s->extends_to_end_of_line_p)
4584 s->background_width = last_x - s->x + 1;
4585 else
4586 s->background_width = s->width;
4590 /* Add a glyph string for a stretch glyph to the list of strings
4591 between HEAD and TAIL. START is the index of the stretch glyph in
4592 row area AREA of glyph row ROW. END is the index of the last glyph
4593 in that glyph row area. X is the current output position assigned
4594 to the new glyph string constructed. HL overrides that face of the
4595 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4596 is the right-most x-position of the drawing area. */
4598 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4599 and below -- keep them on one line. */
4600 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4601 do \
4603 s = (struct glyph_string *) alloca (sizeof *s); \
4604 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4605 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4606 x_append_glyph_string (&HEAD, &TAIL, s); \
4607 s->x = (X); \
4609 while (0)
4612 /* Add a glyph string for an image glyph to the list of strings
4613 between HEAD and TAIL. START is the index of the image glyph in
4614 row area AREA of glyph row ROW. END is the index of the last glyph
4615 in that glyph row area. X is the current output position assigned
4616 to the new glyph string constructed. HL overrides that face of the
4617 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4618 is the right-most x-position of the drawing area. */
4620 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4621 do \
4623 s = (struct glyph_string *) alloca (sizeof *s); \
4624 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4625 x_fill_image_glyph_string (s); \
4626 x_append_glyph_string (&HEAD, &TAIL, s); \
4627 ++START; \
4628 s->x = (X); \
4630 while (0)
4633 /* Add a glyph string for a sequence of character glyphs to the list
4634 of strings between HEAD and TAIL. START is the index of the first
4635 glyph in row area AREA of glyph row ROW that is part of the new
4636 glyph string. END is the index of the last glyph in that glyph row
4637 area. X is the current output position assigned to the new glyph
4638 string constructed. HL overrides that face of the glyph; e.g. it
4639 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4640 right-most x-position of the drawing area. */
4642 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4643 do \
4645 int c, face_id; \
4646 XChar2b *char2b; \
4648 c = (ROW)->glyphs[AREA][START].u.ch; \
4649 face_id = (ROW)->glyphs[AREA][START].face_id; \
4651 s = (struct glyph_string *) alloca (sizeof *s); \
4652 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4653 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4654 x_append_glyph_string (&HEAD, &TAIL, s); \
4655 s->x = (X); \
4656 START = x_fill_glyph_string (s, face_id, START, END, \
4657 OVERLAPS_P); \
4659 while (0)
4662 /* Add a glyph string for a composite sequence to the list of strings
4663 between HEAD and TAIL. START is the index of the first glyph in
4664 row area AREA of glyph row ROW that is part of the new glyph
4665 string. END is the index of the last glyph in that glyph row area.
4666 X is the current output position assigned to the new glyph string
4667 constructed. HL overrides that face of the glyph; e.g. it is
4668 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4669 x-position of the drawing area. */
4671 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4672 do { \
4673 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4674 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4675 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4676 struct composition *cmp = composition_table[cmp_id]; \
4677 int glyph_len = cmp->glyph_len; \
4678 XChar2b *char2b; \
4679 struct face **faces; \
4680 struct glyph_string *first_s = NULL; \
4681 int n; \
4683 base_face = base_face->ascii_face; \
4684 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4685 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4686 /* At first, fill in `char2b' and `faces'. */ \
4687 for (n = 0; n < glyph_len; n++) \
4689 int c = COMPOSITION_GLYPH (cmp, n); \
4690 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4691 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4692 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4693 this_face_id, char2b + n, 1); \
4696 /* Make glyph_strings for each glyph sequence that is drawable by \
4697 the same face, and append them to HEAD/TAIL. */ \
4698 for (n = 0; n < cmp->glyph_len;) \
4700 s = (struct glyph_string *) alloca (sizeof *s); \
4701 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4702 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4703 s->cmp = cmp; \
4704 s->gidx = n; \
4705 s->x = (X); \
4707 if (n == 0) \
4708 first_s = s; \
4710 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4713 ++START; \
4714 s = first_s; \
4715 } while (0)
4718 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4719 of AREA of glyph row ROW on window W between indices START and END.
4720 HL overrides the face for drawing glyph strings, e.g. it is
4721 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4722 x-positions of the drawing area.
4724 This is an ugly monster macro construct because we must use alloca
4725 to allocate glyph strings (because x_draw_glyphs can be called
4726 asynchronously). */
4728 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4729 do \
4731 HEAD = TAIL = NULL; \
4732 while (START < END) \
4734 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4735 switch (first_glyph->type) \
4737 case CHAR_GLYPH: \
4738 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4739 TAIL, HL, X, LAST_X, \
4740 OVERLAPS_P); \
4741 break; \
4743 case COMPOSITE_GLYPH: \
4744 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4745 HEAD, TAIL, HL, X, LAST_X,\
4746 OVERLAPS_P); \
4747 break; \
4749 case STRETCH_GLYPH: \
4750 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4751 HEAD, TAIL, HL, X, LAST_X); \
4752 break; \
4754 case IMAGE_GLYPH: \
4755 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4756 TAIL, HL, X, LAST_X); \
4757 break; \
4759 default: \
4760 abort (); \
4763 x_set_glyph_string_background_width (s, START, LAST_X); \
4764 (X) += s->width; \
4767 while (0)
4770 /* Draw glyphs between START and END in AREA of ROW on window W,
4771 starting at x-position X. X is relative to AREA in W. HL is a
4772 face-override with the following meaning:
4774 DRAW_NORMAL_TEXT draw normally
4775 DRAW_CURSOR draw in cursor face
4776 DRAW_MOUSE_FACE draw in mouse face.
4777 DRAW_INVERSE_VIDEO draw in mode line face
4778 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4779 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4781 If REAL_START is non-null, return in *REAL_START the real starting
4782 position for display. This can be different from START in case
4783 overlapping glyphs must be displayed. If REAL_END is non-null,
4784 return in *REAL_END the real end position for display. This can be
4785 different from END in case overlapping glyphs must be displayed.
4787 If OVERLAPS_P is non-zero, draw only the foreground of characters
4788 and clip to the physical height of ROW.
4790 Value is the x-position reached, relative to AREA of W. */
4792 static int
4793 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4794 overlaps_p)
4795 struct window *w;
4796 int x;
4797 struct glyph_row *row;
4798 enum glyph_row_area area;
4799 int start, end;
4800 enum draw_glyphs_face hl;
4801 int *real_start, *real_end;
4802 int overlaps_p;
4804 struct glyph_string *head, *tail;
4805 struct glyph_string *s;
4806 int last_x, area_width;
4807 int x_reached;
4808 int i, j;
4810 /* Let's rather be paranoid than getting a SEGV. */
4811 end = min (end, row->used[area]);
4812 start = max (0, start);
4813 start = min (end, start);
4814 if (real_start)
4815 *real_start = start;
4816 if (real_end)
4817 *real_end = end;
4819 /* Translate X to frame coordinates. Set last_x to the right
4820 end of the drawing area. */
4821 if (row->full_width_p)
4823 /* X is relative to the left edge of W, without scroll bars
4824 or flag areas. */
4825 struct frame *f = XFRAME (w->frame);
4826 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4827 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4829 x += window_left_x;
4830 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4831 last_x = window_left_x + area_width;
4833 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4835 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4836 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4837 last_x += width;
4838 else
4839 x -= width;
4842 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4843 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4845 else
4847 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4848 area_width = window_box_width (w, area);
4849 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4852 /* Build a doubly-linked list of glyph_string structures between
4853 head and tail from what we have to draw. Note that the macro
4854 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4855 the reason we use a separate variable `i'. */
4856 i = start;
4857 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4858 overlaps_p);
4859 if (tail)
4860 x_reached = tail->x + tail->background_width;
4861 else
4862 x_reached = x;
4864 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4865 the row, redraw some glyphs in front or following the glyph
4866 strings built above. */
4867 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4869 int dummy_x = 0;
4870 struct glyph_string *h, *t;
4872 /* Compute overhangs for all glyph strings. */
4873 for (s = head; s; s = s->next)
4874 x_compute_glyph_string_overhangs (s);
4876 /* Prepend glyph strings for glyphs in front of the first glyph
4877 string that are overwritten because of the first glyph
4878 string's left overhang. The background of all strings
4879 prepended must be drawn because the first glyph string
4880 draws over it. */
4881 i = x_left_overwritten (head);
4882 if (i >= 0)
4884 j = i;
4885 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4886 DRAW_NORMAL_TEXT, dummy_x, last_x,
4887 overlaps_p);
4888 start = i;
4889 if (real_start)
4890 *real_start = start;
4891 x_compute_overhangs_and_x (t, head->x, 1);
4892 x_prepend_glyph_string_lists (&head, &tail, h, t);
4895 /* Prepend glyph strings for glyphs in front of the first glyph
4896 string that overwrite that glyph string because of their
4897 right overhang. For these strings, only the foreground must
4898 be drawn, because it draws over the glyph string at `head'.
4899 The background must not be drawn because this would overwrite
4900 right overhangs of preceding glyphs for which no glyph
4901 strings exist. */
4902 i = x_left_overwriting (head);
4903 if (i >= 0)
4905 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4906 DRAW_NORMAL_TEXT, dummy_x, last_x,
4907 overlaps_p);
4908 for (s = h; s; s = s->next)
4909 s->background_filled_p = 1;
4910 if (real_start)
4911 *real_start = i;
4912 x_compute_overhangs_and_x (t, head->x, 1);
4913 x_prepend_glyph_string_lists (&head, &tail, h, t);
4916 /* Append glyphs strings for glyphs following the last glyph
4917 string tail that are overwritten by tail. The background of
4918 these strings has to be drawn because tail's foreground draws
4919 over it. */
4920 i = x_right_overwritten (tail);
4921 if (i >= 0)
4923 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4924 DRAW_NORMAL_TEXT, x, last_x,
4925 overlaps_p);
4926 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4927 x_append_glyph_string_lists (&head, &tail, h, t);
4928 if (real_end)
4929 *real_end = i;
4932 /* Append glyph strings for glyphs following the last glyph
4933 string tail that overwrite tail. The foreground of such
4934 glyphs has to be drawn because it writes into the background
4935 of tail. The background must not be drawn because it could
4936 paint over the foreground of following glyphs. */
4937 i = x_right_overwriting (tail);
4938 if (i >= 0)
4940 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4941 DRAW_NORMAL_TEXT, x, last_x,
4942 overlaps_p);
4943 for (s = h; s; s = s->next)
4944 s->background_filled_p = 1;
4945 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4946 x_append_glyph_string_lists (&head, &tail, h, t);
4947 if (real_end)
4948 *real_end = i;
4952 /* Draw all strings. */
4953 for (s = head; s; s = s->next)
4954 x_draw_glyph_string (s);
4956 /* Value is the x-position up to which drawn, relative to AREA of W.
4957 This doesn't include parts drawn because of overhangs. */
4958 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4959 if (!row->full_width_p)
4961 if (area > LEFT_MARGIN_AREA)
4962 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4963 if (area > TEXT_AREA)
4964 x_reached -= window_box_width (w, TEXT_AREA);
4967 return x_reached;
4971 /* Fix the display of area AREA of overlapping row ROW in window W. */
4973 static void
4974 x_fix_overlapping_area (w, row, area)
4975 struct window *w;
4976 struct glyph_row *row;
4977 enum glyph_row_area area;
4979 int i, x;
4981 BLOCK_INPUT;
4983 if (area == LEFT_MARGIN_AREA)
4984 x = 0;
4985 else if (area == TEXT_AREA)
4986 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4987 else
4988 x = (window_box_width (w, LEFT_MARGIN_AREA)
4989 + window_box_width (w, TEXT_AREA));
4991 for (i = 0; i < row->used[area];)
4993 if (row->glyphs[area][i].overlaps_vertically_p)
4995 int start = i, start_x = x;
4999 x += row->glyphs[area][i].pixel_width;
5000 ++i;
5002 while (i < row->used[area]
5003 && row->glyphs[area][i].overlaps_vertically_p);
5005 x_draw_glyphs (w, start_x, row, area, start, i,
5006 (row->inverse_p
5007 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5008 NULL, NULL, 1);
5010 else
5012 x += row->glyphs[area][i].pixel_width;
5013 ++i;
5017 UNBLOCK_INPUT;
5021 /* Output LEN glyphs starting at START at the nominal cursor position.
5022 Advance the nominal cursor over the text. The global variable
5023 updated_window contains the window being updated, updated_row is
5024 the glyph row being updated, and updated_area is the area of that
5025 row being updated. */
5027 static void
5028 x_write_glyphs (start, len)
5029 struct glyph *start;
5030 int len;
5032 int x, hpos, real_start, real_end;
5034 xassert (updated_window && updated_row);
5035 BLOCK_INPUT;
5037 /* Write glyphs. */
5039 hpos = start - updated_row->glyphs[updated_area];
5040 x = x_draw_glyphs (updated_window, output_cursor.x,
5041 updated_row, updated_area,
5042 hpos, hpos + len,
5043 (updated_row->inverse_p
5044 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5045 &real_start, &real_end, 0);
5047 /* If we drew over the cursor, note that it is not visible any more. */
5048 note_overwritten_text_cursor (updated_window, real_start,
5049 real_end - real_start);
5051 UNBLOCK_INPUT;
5053 /* Advance the output cursor. */
5054 output_cursor.hpos += len;
5055 output_cursor.x = x;
5059 /* Insert LEN glyphs from START at the nominal cursor position. */
5061 static void
5062 x_insert_glyphs (start, len)
5063 struct glyph *start;
5064 register int len;
5066 struct frame *f;
5067 struct window *w;
5068 int line_height, shift_by_width, shifted_region_width;
5069 struct glyph_row *row;
5070 struct glyph *glyph;
5071 int frame_x, frame_y, hpos, real_start, real_end;
5073 xassert (updated_window && updated_row);
5074 BLOCK_INPUT;
5075 w = updated_window;
5076 f = XFRAME (WINDOW_FRAME (w));
5078 /* Get the height of the line we are in. */
5079 row = updated_row;
5080 line_height = row->height;
5082 /* Get the width of the glyphs to insert. */
5083 shift_by_width = 0;
5084 for (glyph = start; glyph < start + len; ++glyph)
5085 shift_by_width += glyph->pixel_width;
5087 /* Get the width of the region to shift right. */
5088 shifted_region_width = (window_box_width (w, updated_area)
5089 - output_cursor.x
5090 - shift_by_width);
5092 /* Shift right. */
5093 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5094 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5095 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5096 f->output_data.x->normal_gc,
5097 frame_x, frame_y,
5098 shifted_region_width, line_height,
5099 frame_x + shift_by_width, frame_y);
5101 /* Write the glyphs. */
5102 hpos = start - row->glyphs[updated_area];
5103 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5104 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5105 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5107 /* Advance the output cursor. */
5108 output_cursor.hpos += len;
5109 output_cursor.x += shift_by_width;
5110 UNBLOCK_INPUT;
5114 /* Delete N glyphs at the nominal cursor position. Not implemented
5115 for X frames. */
5117 static void
5118 x_delete_glyphs (n)
5119 register int n;
5121 abort ();
5125 /* Erase the current text line from the nominal cursor position
5126 (inclusive) to pixel column TO_X (exclusive). The idea is that
5127 everything from TO_X onward is already erased.
5129 TO_X is a pixel position relative to updated_area of
5130 updated_window. TO_X == -1 means clear to the end of this area. */
5132 static void
5133 x_clear_end_of_line (to_x)
5134 int to_x;
5136 struct frame *f;
5137 struct window *w = updated_window;
5138 int max_x, min_y, max_y;
5139 int from_x, from_y, to_y;
5141 xassert (updated_window && updated_row);
5142 f = XFRAME (w->frame);
5144 if (updated_row->full_width_p)
5146 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5147 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5148 && !w->pseudo_window_p)
5149 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5151 else
5152 max_x = window_box_width (w, updated_area);
5153 max_y = window_text_bottom_y (w);
5155 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5156 of window. For TO_X > 0, truncate to end of drawing area. */
5157 if (to_x == 0)
5158 return;
5159 else if (to_x < 0)
5160 to_x = max_x;
5161 else
5162 to_x = min (to_x, max_x);
5164 to_y = min (max_y, output_cursor.y + updated_row->height);
5166 /* Notice if the cursor will be cleared by this operation. */
5167 if (!updated_row->full_width_p)
5168 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5170 from_x = output_cursor.x;
5172 /* Translate to frame coordinates. */
5173 if (updated_row->full_width_p)
5175 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5176 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5178 else
5180 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5181 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5184 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5185 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5186 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5188 /* Prevent inadvertently clearing to end of the X window. */
5189 if (to_x > from_x && to_y > from_y)
5191 BLOCK_INPUT;
5192 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5193 from_x, from_y, to_x - from_x, to_y - from_y,
5194 False);
5195 UNBLOCK_INPUT;
5200 /* Clear entire frame. If updating_frame is non-null, clear that
5201 frame. Otherwise clear the selected frame. */
5203 static void
5204 x_clear_frame ()
5206 struct frame *f;
5208 if (updating_frame)
5209 f = updating_frame;
5210 else
5211 f = SELECTED_FRAME ();
5213 /* Clearing the frame will erase any cursor, so mark them all as no
5214 longer visible. */
5215 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5216 output_cursor.hpos = output_cursor.vpos = 0;
5217 output_cursor.x = -1;
5219 /* We don't set the output cursor here because there will always
5220 follow an explicit cursor_to. */
5221 BLOCK_INPUT;
5222 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5224 /* We have to clear the scroll bars, too. If we have changed
5225 colors or something like that, then they should be notified. */
5226 x_scroll_bar_clear (f);
5228 XFlush (FRAME_X_DISPLAY (f));
5229 UNBLOCK_INPUT;
5234 /* Invert the middle quarter of the frame for .15 sec. */
5236 /* We use the select system call to do the waiting, so we have to make
5237 sure it's available. If it isn't, we just won't do visual bells. */
5239 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5242 /* Subtract the `struct timeval' values X and Y, storing the result in
5243 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5245 static int
5246 timeval_subtract (result, x, y)
5247 struct timeval *result, x, y;
5249 /* Perform the carry for the later subtraction by updating y. This
5250 is safer because on some systems the tv_sec member is unsigned. */
5251 if (x.tv_usec < y.tv_usec)
5253 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5254 y.tv_usec -= 1000000 * nsec;
5255 y.tv_sec += nsec;
5258 if (x.tv_usec - y.tv_usec > 1000000)
5260 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5261 y.tv_usec += 1000000 * nsec;
5262 y.tv_sec -= nsec;
5265 /* Compute the time remaining to wait. tv_usec is certainly
5266 positive. */
5267 result->tv_sec = x.tv_sec - y.tv_sec;
5268 result->tv_usec = x.tv_usec - y.tv_usec;
5270 /* Return indication of whether the result should be considered
5271 negative. */
5272 return x.tv_sec < y.tv_sec;
5275 void
5276 XTflash (f)
5277 struct frame *f;
5279 BLOCK_INPUT;
5282 GC gc;
5284 /* Create a GC that will use the GXxor function to flip foreground
5285 pixels into background pixels. */
5287 XGCValues values;
5289 values.function = GXxor;
5290 values.foreground = (f->output_data.x->foreground_pixel
5291 ^ f->output_data.x->background_pixel);
5293 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5294 GCFunction | GCForeground, &values);
5298 /* Get the height not including a menu bar widget. */
5299 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5300 /* Height of each line to flash. */
5301 int flash_height = FRAME_LINE_HEIGHT (f);
5302 /* These will be the left and right margins of the rectangles. */
5303 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5304 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5306 int width;
5308 /* Don't flash the area between a scroll bar and the frame
5309 edge it is next to. */
5310 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5312 case vertical_scroll_bar_left:
5313 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5314 break;
5316 case vertical_scroll_bar_right:
5317 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5318 break;
5320 default:
5321 break;
5324 width = flash_right - flash_left;
5326 /* If window is tall, flash top and bottom line. */
5327 if (height > 3 * FRAME_LINE_HEIGHT (f))
5329 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5330 flash_left,
5331 (FRAME_INTERNAL_BORDER_WIDTH (f)
5332 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5333 width, flash_height);
5334 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5335 flash_left,
5336 (height - flash_height
5337 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5338 width, flash_height);
5340 else
5341 /* If it is short, flash it all. */
5342 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5343 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5344 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5346 x_flush (f);
5349 struct timeval wakeup;
5351 EMACS_GET_TIME (wakeup);
5353 /* Compute time to wait until, propagating carry from usecs. */
5354 wakeup.tv_usec += 150000;
5355 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5356 wakeup.tv_usec %= 1000000;
5358 /* Keep waiting until past the time wakeup. */
5359 while (1)
5361 struct timeval timeout;
5363 EMACS_GET_TIME (timeout);
5365 /* In effect, timeout = wakeup - timeout.
5366 Break if result would be negative. */
5367 if (timeval_subtract (&timeout, wakeup, timeout))
5368 break;
5370 /* Try to wait that long--but we might wake up sooner. */
5371 select (0, NULL, NULL, NULL, &timeout);
5375 /* If window is tall, flash top and bottom line. */
5376 if (height > 3 * FRAME_LINE_HEIGHT (f))
5378 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5379 flash_left,
5380 (FRAME_INTERNAL_BORDER_WIDTH (f)
5381 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5382 width, flash_height);
5383 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5384 flash_left,
5385 (height - flash_height
5386 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5387 width, flash_height);
5389 else
5390 /* If it is short, flash it all. */
5391 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5392 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5393 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5395 XFreeGC (FRAME_X_DISPLAY (f), gc);
5396 x_flush (f);
5400 UNBLOCK_INPUT;
5403 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5406 /* Make audible bell. */
5408 void
5409 XTring_bell ()
5411 struct frame *f = SELECTED_FRAME ();
5413 if (FRAME_X_DISPLAY (f))
5415 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5416 if (visible_bell)
5417 XTflash (f);
5418 else
5419 #endif
5421 BLOCK_INPUT;
5422 XBell (FRAME_X_DISPLAY (f), 0);
5423 XFlush (FRAME_X_DISPLAY (f));
5424 UNBLOCK_INPUT;
5430 /* Specify how many text lines, from the top of the window,
5431 should be affected by insert-lines and delete-lines operations.
5432 This, and those operations, are used only within an update
5433 that is bounded by calls to x_update_begin and x_update_end. */
5435 static void
5436 XTset_terminal_window (n)
5437 register int n;
5439 /* This function intentionally left blank. */
5444 /***********************************************************************
5445 Line Dance
5446 ***********************************************************************/
5448 /* Perform an insert-lines or delete-lines operation, inserting N
5449 lines or deleting -N lines at vertical position VPOS. */
5451 static void
5452 x_ins_del_lines (vpos, n)
5453 int vpos, n;
5455 abort ();
5459 /* Scroll part of the display as described by RUN. */
5461 static void
5462 x_scroll_run (w, run)
5463 struct window *w;
5464 struct run *run;
5466 struct frame *f = XFRAME (w->frame);
5467 int x, y, width, height, from_y, to_y, bottom_y;
5469 /* Get frame-relative bounding box of the text display area of W,
5470 without mode lines. Include in this box the flags areas to the
5471 left and right of W. */
5472 window_box (w, -1, &x, &y, &width, &height);
5473 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5474 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5476 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5477 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5478 bottom_y = y + height;
5480 if (to_y < from_y)
5482 /* Scrolling up. Make sure we don't copy part of the mode
5483 line at the bottom. */
5484 if (from_y + run->height > bottom_y)
5485 height = bottom_y - from_y;
5486 else
5487 height = run->height;
5489 else
5491 /* Scolling down. Make sure we don't copy over the mode line.
5492 at the bottom. */
5493 if (to_y + run->height > bottom_y)
5494 height = bottom_y - to_y;
5495 else
5496 height = run->height;
5499 BLOCK_INPUT;
5501 /* Cursor off. Will be switched on again in x_update_window_end. */
5502 updated_window = w;
5503 x_clear_cursor (w);
5505 XCopyArea (FRAME_X_DISPLAY (f),
5506 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5507 f->output_data.x->normal_gc,
5508 x, from_y,
5509 width, height,
5510 x, to_y);
5512 UNBLOCK_INPUT;
5517 /***********************************************************************
5518 Exposure Events
5519 ***********************************************************************/
5521 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5522 corner of the exposed rectangle. W and H are width and height of
5523 the exposed area. All are pixel values. W or H zero means redraw
5524 the entire frame. */
5526 static void
5527 expose_frame (f, x, y, w, h)
5528 struct frame *f;
5529 int x, y, w, h;
5531 XRectangle r;
5533 TRACE ((stderr, "expose_frame "));
5535 /* No need to redraw if frame will be redrawn soon. */
5536 if (FRAME_GARBAGED_P (f))
5538 TRACE ((stderr, " garbaged\n"));
5539 return;
5542 /* If basic faces haven't been realized yet, there is no point in
5543 trying to redraw anything. This can happen when we get an expose
5544 event while Emacs is starting, e.g. by moving another window. */
5545 if (FRAME_FACE_CACHE (f) == NULL
5546 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5548 TRACE ((stderr, " no faces\n"));
5549 return;
5552 if (w == 0 || h == 0)
5554 r.x = r.y = 0;
5555 r.width = CANON_X_UNIT (f) * f->width;
5556 r.height = CANON_Y_UNIT (f) * f->height;
5558 else
5560 r.x = x;
5561 r.y = y;
5562 r.width = w;
5563 r.height = h;
5566 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5567 expose_window_tree (XWINDOW (f->root_window), &r);
5569 if (WINDOWP (f->tool_bar_window))
5571 struct window *w = XWINDOW (f->tool_bar_window);
5572 XRectangle window_rect;
5573 XRectangle intersection_rect;
5574 int window_x, window_y, window_width, window_height;
5577 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5578 window_rect.x = window_x;
5579 window_rect.y = window_y;
5580 window_rect.width = window_width;
5581 window_rect.height = window_height;
5583 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5584 expose_window (w, &intersection_rect);
5587 #ifndef USE_X_TOOLKIT
5588 if (WINDOWP (f->menu_bar_window))
5590 struct window *w = XWINDOW (f->menu_bar_window);
5591 XRectangle window_rect;
5592 XRectangle intersection_rect;
5593 int window_x, window_y, window_width, window_height;
5596 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5597 window_rect.x = window_x;
5598 window_rect.y = window_y;
5599 window_rect.width = window_width;
5600 window_rect.height = window_height;
5602 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5603 expose_window (w, &intersection_rect);
5605 #endif /* not USE_X_TOOLKIT */
5609 /* Redraw (parts) of all windows in the window tree rooted at W that
5610 intersect R. R contains frame pixel coordinates. */
5612 static void
5613 expose_window_tree (w, r)
5614 struct window *w;
5615 XRectangle *r;
5617 while (w)
5619 if (!NILP (w->hchild))
5620 expose_window_tree (XWINDOW (w->hchild), r);
5621 else if (!NILP (w->vchild))
5622 expose_window_tree (XWINDOW (w->vchild), r);
5623 else
5625 XRectangle window_rect;
5626 XRectangle intersection_rect;
5627 struct frame *f = XFRAME (w->frame);
5628 int window_x, window_y, window_width, window_height;
5630 /* Frame-relative pixel rectangle of W. */
5631 window_box (w, -1, &window_x, &window_y, &window_width,
5632 &window_height);
5633 window_rect.x
5634 = (window_x
5635 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5636 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5637 window_rect.y = window_y;
5638 window_rect.width
5639 = (window_width
5640 + FRAME_X_FLAGS_AREA_WIDTH (f)
5641 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5642 window_rect.height
5643 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5645 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5646 expose_window (w, &intersection_rect);
5649 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5654 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5655 which intersects rectangle R. R is in window-relative coordinates. */
5657 static void
5658 expose_area (w, row, r, area)
5659 struct window *w;
5660 struct glyph_row *row;
5661 XRectangle *r;
5662 enum glyph_row_area area;
5664 int x;
5665 struct glyph *first = row->glyphs[area];
5666 struct glyph *end = row->glyphs[area] + row->used[area];
5667 struct glyph *last;
5668 int first_x;
5670 /* Set x to the window-relative start position for drawing glyphs of
5671 AREA. The first glyph of the text area can be partially visible.
5672 The first glyphs of other areas cannot. */
5673 if (area == LEFT_MARGIN_AREA)
5674 x = 0;
5675 else if (area == TEXT_AREA)
5676 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5677 else
5678 x = (window_box_width (w, LEFT_MARGIN_AREA)
5679 + window_box_width (w, TEXT_AREA));
5681 if (area == TEXT_AREA && row->fill_line_p)
5682 /* If row extends face to end of line write the whole line. */
5683 x_draw_glyphs (w, x, row, area,
5684 0, row->used[area],
5685 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5686 NULL, NULL, 0);
5687 else
5689 /* Find the first glyph that must be redrawn. */
5690 while (first < end
5691 && x + first->pixel_width < r->x)
5693 x += first->pixel_width;
5694 ++first;
5697 /* Find the last one. */
5698 last = first;
5699 first_x = x;
5700 while (last < end
5701 && x < r->x + r->width)
5703 x += last->pixel_width;
5704 ++last;
5707 /* Repaint. */
5708 if (last > first)
5709 x_draw_glyphs (w, first_x, row, area,
5710 first - row->glyphs[area],
5711 last - row->glyphs[area],
5712 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5713 NULL, NULL, 0);
5718 /* Redraw the parts of the glyph row ROW on window W intersecting
5719 rectangle R. R is in window-relative coordinates. */
5721 static void
5722 expose_line (w, row, r)
5723 struct window *w;
5724 struct glyph_row *row;
5725 XRectangle *r;
5727 xassert (row->enabled_p);
5729 if (row->mode_line_p || w->pseudo_window_p)
5730 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5731 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5732 NULL, NULL, 0);
5733 else
5735 if (row->used[LEFT_MARGIN_AREA])
5736 expose_area (w, row, r, LEFT_MARGIN_AREA);
5737 if (row->used[TEXT_AREA])
5738 expose_area (w, row, r, TEXT_AREA);
5739 if (row->used[RIGHT_MARGIN_AREA])
5740 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5741 x_draw_row_bitmaps (w, row);
5746 /* Return non-zero if W's cursor intersects rectangle R. */
5748 static int
5749 x_phys_cursor_in_rect_p (w, r)
5750 struct window *w;
5751 XRectangle *r;
5753 XRectangle cr, result;
5754 struct glyph *cursor_glyph;
5756 cursor_glyph = get_phys_cursor_glyph (w);
5757 if (cursor_glyph)
5759 cr.x = w->phys_cursor.x;
5760 cr.y = w->phys_cursor.y;
5761 cr.width = cursor_glyph->pixel_width;
5762 cr.height = w->phys_cursor_height;
5763 return x_intersect_rectangles (&cr, r, &result);
5765 else
5766 return 0;
5770 /* Redraw a rectangle of window W. R is a rectangle in window
5771 relative coordinates. Call this function with input blocked. */
5773 static void
5774 expose_window (w, r)
5775 struct window *w;
5776 XRectangle *r;
5778 struct glyph_row *row;
5779 int y;
5780 int yb = window_text_bottom_y (w);
5781 int cursor_cleared_p;
5783 /* If window is not yet fully initialized, do nothing. This can
5784 happen when toolkit scroll bars are used and a window is split.
5785 Reconfiguring the scroll bar will generate an expose for a newly
5786 created window. */
5787 if (w->current_matrix == NULL)
5788 return;
5790 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5791 r->x, r->y, r->width, r->height));
5793 /* Convert to window coordinates. */
5794 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5795 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5797 /* Turn off the cursor. */
5798 if (!w->pseudo_window_p
5799 && x_phys_cursor_in_rect_p (w, r))
5801 x_clear_cursor (w);
5802 cursor_cleared_p = 1;
5804 else
5805 cursor_cleared_p = 0;
5807 /* Find the first row intersecting the rectangle R. */
5808 row = w->current_matrix->rows;
5809 y = 0;
5810 while (row->enabled_p
5811 && y < yb
5812 && y + row->height < r->y)
5814 y += row->height;
5815 ++row;
5818 /* Display the text in the rectangle, one text line at a time. */
5819 while (row->enabled_p
5820 && y < yb
5821 && y < r->y + r->height)
5823 expose_line (w, row, r);
5824 y += row->height;
5825 ++row;
5828 /* Display the mode line if there is one. */
5829 if (WINDOW_WANTS_MODELINE_P (w)
5830 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5831 row->enabled_p)
5832 && row->y < r->y + r->height)
5833 expose_line (w, row, r);
5835 if (!w->pseudo_window_p)
5837 /* Draw border between windows. */
5838 x_draw_vertical_border (w);
5840 /* Turn the cursor on again. */
5841 if (cursor_cleared_p)
5842 x_update_window_cursor (w, 1);
5847 /* Determine the intersection of two rectangles R1 and R2. Return
5848 the intersection in *RESULT. Value is non-zero if RESULT is not
5849 empty. */
5851 static int
5852 x_intersect_rectangles (r1, r2, result)
5853 XRectangle *r1, *r2, *result;
5855 XRectangle *left, *right;
5856 XRectangle *upper, *lower;
5857 int intersection_p = 0;
5859 /* Rearrange so that R1 is the left-most rectangle. */
5860 if (r1->x < r2->x)
5861 left = r1, right = r2;
5862 else
5863 left = r2, right = r1;
5865 /* X0 of the intersection is right.x0, if this is inside R1,
5866 otherwise there is no intersection. */
5867 if (right->x <= left->x + left->width)
5869 result->x = right->x;
5871 /* The right end of the intersection is the minimum of the
5872 the right ends of left and right. */
5873 result->width = (min (left->x + left->width, right->x + right->width)
5874 - result->x);
5876 /* Same game for Y. */
5877 if (r1->y < r2->y)
5878 upper = r1, lower = r2;
5879 else
5880 upper = r2, lower = r1;
5882 /* The upper end of the intersection is lower.y0, if this is inside
5883 of upper. Otherwise, there is no intersection. */
5884 if (lower->y <= upper->y + upper->height)
5886 result->y = lower->y;
5888 /* The lower end of the intersection is the minimum of the lower
5889 ends of upper and lower. */
5890 result->height = (min (lower->y + lower->height,
5891 upper->y + upper->height)
5892 - result->y);
5893 intersection_p = 1;
5897 return intersection_p;
5904 static void
5905 frame_highlight (f)
5906 struct frame *f;
5908 /* We used to only do this if Vx_no_window_manager was non-nil, but
5909 the ICCCM (section 4.1.6) says that the window's border pixmap
5910 and border pixel are window attributes which are "private to the
5911 client", so we can always change it to whatever we want. */
5912 BLOCK_INPUT;
5913 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5914 f->output_data.x->border_pixel);
5915 UNBLOCK_INPUT;
5916 x_update_cursor (f, 1);
5919 static void
5920 frame_unhighlight (f)
5921 struct frame *f;
5923 /* We used to only do this if Vx_no_window_manager was non-nil, but
5924 the ICCCM (section 4.1.6) says that the window's border pixmap
5925 and border pixel are window attributes which are "private to the
5926 client", so we can always change it to whatever we want. */
5927 BLOCK_INPUT;
5928 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5929 f->output_data.x->border_tile);
5930 UNBLOCK_INPUT;
5931 x_update_cursor (f, 1);
5934 /* The focus has changed. Update the frames as necessary to reflect
5935 the new situation. Note that we can't change the selected frame
5936 here, because the Lisp code we are interrupting might become confused.
5937 Each event gets marked with the frame in which it occurred, so the
5938 Lisp code can tell when the switch took place by examining the events. */
5940 static void
5941 x_new_focus_frame (dpyinfo, frame)
5942 struct x_display_info *dpyinfo;
5943 struct frame *frame;
5945 struct frame *old_focus = dpyinfo->x_focus_frame;
5947 if (frame != dpyinfo->x_focus_frame)
5949 /* Set this before calling other routines, so that they see
5950 the correct value of x_focus_frame. */
5951 dpyinfo->x_focus_frame = frame;
5953 if (old_focus && old_focus->auto_lower)
5954 x_lower_frame (old_focus);
5956 #if 0
5957 selected_frame = frame;
5958 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5959 selected_frame);
5960 Fselect_window (selected_frame->selected_window);
5961 choose_minibuf_frame ();
5962 #endif /* ! 0 */
5964 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5965 pending_autoraise_frame = dpyinfo->x_focus_frame;
5966 else
5967 pending_autoraise_frame = 0;
5970 x_frame_rehighlight (dpyinfo);
5973 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5975 void
5976 x_mouse_leave (dpyinfo)
5977 struct x_display_info *dpyinfo;
5979 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5982 /* The focus has changed, or we have redirected a frame's focus to
5983 another frame (this happens when a frame uses a surrogate
5984 mini-buffer frame). Shift the highlight as appropriate.
5986 The FRAME argument doesn't necessarily have anything to do with which
5987 frame is being highlighted or un-highlighted; we only use it to find
5988 the appropriate X display info. */
5990 static void
5991 XTframe_rehighlight (frame)
5992 struct frame *frame;
5994 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5997 static void
5998 x_frame_rehighlight (dpyinfo)
5999 struct x_display_info *dpyinfo;
6001 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6003 if (dpyinfo->x_focus_frame)
6005 dpyinfo->x_highlight_frame
6006 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6007 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6008 : dpyinfo->x_focus_frame);
6009 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6011 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6012 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6015 else
6016 dpyinfo->x_highlight_frame = 0;
6018 if (dpyinfo->x_highlight_frame != old_highlight)
6020 if (old_highlight)
6021 frame_unhighlight (old_highlight);
6022 if (dpyinfo->x_highlight_frame)
6023 frame_highlight (dpyinfo->x_highlight_frame);
6029 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6031 /* Initialize mode_switch_bit and modifier_meaning. */
6032 static void
6033 x_find_modifier_meanings (dpyinfo)
6034 struct x_display_info *dpyinfo;
6036 int min_code, max_code;
6037 KeySym *syms;
6038 int syms_per_code;
6039 XModifierKeymap *mods;
6041 dpyinfo->meta_mod_mask = 0;
6042 dpyinfo->shift_lock_mask = 0;
6043 dpyinfo->alt_mod_mask = 0;
6044 dpyinfo->super_mod_mask = 0;
6045 dpyinfo->hyper_mod_mask = 0;
6047 #ifdef HAVE_X11R4
6048 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6049 #else
6050 min_code = dpyinfo->display->min_keycode;
6051 max_code = dpyinfo->display->max_keycode;
6052 #endif
6054 syms = XGetKeyboardMapping (dpyinfo->display,
6055 min_code, max_code - min_code + 1,
6056 &syms_per_code);
6057 mods = XGetModifierMapping (dpyinfo->display);
6059 /* Scan the modifier table to see which modifier bits the Meta and
6060 Alt keysyms are on. */
6062 int row, col; /* The row and column in the modifier table. */
6064 for (row = 3; row < 8; row++)
6065 for (col = 0; col < mods->max_keypermod; col++)
6067 KeyCode code
6068 = mods->modifiermap[(row * mods->max_keypermod) + col];
6070 /* Zeroes are used for filler. Skip them. */
6071 if (code == 0)
6072 continue;
6074 /* Are any of this keycode's keysyms a meta key? */
6076 int code_col;
6078 for (code_col = 0; code_col < syms_per_code; code_col++)
6080 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6082 switch (sym)
6084 case XK_Meta_L:
6085 case XK_Meta_R:
6086 dpyinfo->meta_mod_mask |= (1 << row);
6087 break;
6089 case XK_Alt_L:
6090 case XK_Alt_R:
6091 dpyinfo->alt_mod_mask |= (1 << row);
6092 break;
6094 case XK_Hyper_L:
6095 case XK_Hyper_R:
6096 dpyinfo->hyper_mod_mask |= (1 << row);
6097 break;
6099 case XK_Super_L:
6100 case XK_Super_R:
6101 dpyinfo->super_mod_mask |= (1 << row);
6102 break;
6104 case XK_Shift_Lock:
6105 /* Ignore this if it's not on the lock modifier. */
6106 if ((1 << row) == LockMask)
6107 dpyinfo->shift_lock_mask = LockMask;
6108 break;
6115 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6116 if (! dpyinfo->meta_mod_mask)
6118 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6119 dpyinfo->alt_mod_mask = 0;
6122 /* If some keys are both alt and meta,
6123 make them just meta, not alt. */
6124 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6126 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6129 XFree ((char *) syms);
6130 XFreeModifiermap (mods);
6133 /* Convert between the modifier bits X uses and the modifier bits
6134 Emacs uses. */
6136 static unsigned int
6137 x_x_to_emacs_modifiers (dpyinfo, state)
6138 struct x_display_info *dpyinfo;
6139 unsigned int state;
6141 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6142 | ((state & ControlMask) ? ctrl_modifier : 0)
6143 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6144 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6145 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6146 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6149 static unsigned int
6150 x_emacs_to_x_modifiers (dpyinfo, state)
6151 struct x_display_info *dpyinfo;
6152 unsigned int state;
6154 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6155 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6156 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6157 | ((state & shift_modifier) ? ShiftMask : 0)
6158 | ((state & ctrl_modifier) ? ControlMask : 0)
6159 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6162 /* Convert a keysym to its name. */
6164 char *
6165 x_get_keysym_name (keysym)
6166 KeySym keysym;
6168 char *value;
6170 BLOCK_INPUT;
6171 value = XKeysymToString (keysym);
6172 UNBLOCK_INPUT;
6174 return value;
6179 /* Mouse clicks and mouse movement. Rah. */
6181 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6182 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6183 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6184 not force the value into range. */
6186 void
6187 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6188 FRAME_PTR f;
6189 register int pix_x, pix_y;
6190 register int *x, *y;
6191 XRectangle *bounds;
6192 int noclip;
6194 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6195 even for negative values. */
6196 if (pix_x < 0)
6197 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6198 if (pix_y < 0)
6199 pix_y -= (f)->output_data.x->line_height - 1;
6201 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6202 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6204 if (bounds)
6206 bounds->width = FONT_WIDTH (f->output_data.x->font);
6207 bounds->height = f->output_data.x->line_height;
6208 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6209 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6212 if (!noclip)
6214 if (pix_x < 0)
6215 pix_x = 0;
6216 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6217 pix_x = FRAME_WINDOW_WIDTH (f);
6219 if (pix_y < 0)
6220 pix_y = 0;
6221 else if (pix_y > f->height)
6222 pix_y = f->height;
6225 *x = pix_x;
6226 *y = pix_y;
6230 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6231 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6232 can't tell the positions because W's display is not up to date,
6233 return 0. */
6236 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6237 struct window *w;
6238 int hpos, vpos;
6239 int *frame_x, *frame_y;
6241 int success_p;
6243 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6244 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6246 if (display_completed)
6248 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6249 struct glyph *glyph = row->glyphs[TEXT_AREA];
6250 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6252 *frame_y = row->y;
6253 *frame_x = row->x;
6254 while (glyph < end)
6256 *frame_x += glyph->pixel_width;
6257 ++glyph;
6260 success_p = 1;
6262 else
6264 *frame_y = *frame_x = 0;
6265 success_p = 0;
6268 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6269 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6270 return success_p;
6274 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6276 If the event is a button press, then note that we have grabbed
6277 the mouse. */
6279 static Lisp_Object
6280 construct_mouse_click (result, event, f)
6281 struct input_event *result;
6282 XButtonEvent *event;
6283 struct frame *f;
6285 /* Make the event type no_event; we'll change that when we decide
6286 otherwise. */
6287 result->kind = mouse_click;
6288 result->code = event->button - Button1;
6289 result->timestamp = event->time;
6290 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6291 event->state)
6292 | (event->type == ButtonRelease
6293 ? up_modifier
6294 : down_modifier));
6296 XSETINT (result->x, event->x);
6297 XSETINT (result->y, event->y);
6298 XSETFRAME (result->frame_or_window, f);
6299 result->arg = Qnil;
6300 return Qnil;
6304 /* Function to report a mouse movement to the mainstream Emacs code.
6305 The input handler calls this.
6307 We have received a mouse movement event, which is given in *event.
6308 If the mouse is over a different glyph than it was last time, tell
6309 the mainstream emacs code by setting mouse_moved. If not, ask for
6310 another motion event, so we can check again the next time it moves. */
6312 static XMotionEvent last_mouse_motion_event;
6313 static Lisp_Object last_mouse_motion_frame;
6315 static void
6316 note_mouse_movement (frame, event)
6317 FRAME_PTR frame;
6318 XMotionEvent *event;
6320 last_mouse_movement_time = event->time;
6321 last_mouse_motion_event = *event;
6322 XSETFRAME (last_mouse_motion_frame, frame);
6324 if (event->window != FRAME_X_WINDOW (frame))
6326 frame->mouse_moved = 1;
6327 last_mouse_scroll_bar = Qnil;
6328 note_mouse_highlight (frame, -1, -1);
6331 /* Has the mouse moved off the glyph it was on at the last sighting? */
6332 else if (event->x < last_mouse_glyph.x
6333 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6334 || event->y < last_mouse_glyph.y
6335 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6337 frame->mouse_moved = 1;
6338 last_mouse_scroll_bar = Qnil;
6339 note_mouse_highlight (frame, event->x, event->y);
6343 /* This is used for debugging, to turn off note_mouse_highlight. */
6345 int disable_mouse_highlight;
6349 /************************************************************************
6350 Mouse Face
6351 ************************************************************************/
6353 /* Find the glyph under window-relative coordinates X/Y in window W.
6354 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6355 strings. Return in *HPOS and *VPOS the row and column number of
6356 the glyph found. Return in *AREA the glyph area containing X.
6357 Value is a pointer to the glyph found or null if X/Y is not on
6358 text, or we can't tell because W's current matrix is not up to
6359 date. */
6361 static struct glyph *
6362 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6363 struct window *w;
6364 int x, y;
6365 int *hpos, *vpos, *area;
6367 struct glyph *glyph, *end;
6368 struct glyph_row *row = NULL;
6369 int x0, i, left_area_width;
6371 /* Find row containing Y. Give up if some row is not enabled. */
6372 for (i = 0; i < w->current_matrix->nrows; ++i)
6374 row = MATRIX_ROW (w->current_matrix, i);
6375 if (!row->enabled_p)
6376 return NULL;
6377 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6378 break;
6381 *vpos = i;
6382 *hpos = 0;
6384 /* Give up if Y is not in the window. */
6385 if (i == w->current_matrix->nrows)
6386 return NULL;
6388 /* Get the glyph area containing X. */
6389 if (w->pseudo_window_p)
6391 *area = TEXT_AREA;
6392 x0 = 0;
6394 else
6396 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6397 if (x < left_area_width)
6399 *area = LEFT_MARGIN_AREA;
6400 x0 = 0;
6402 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6404 *area = TEXT_AREA;
6405 x0 = row->x + left_area_width;
6407 else
6409 *area = RIGHT_MARGIN_AREA;
6410 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6414 /* Find glyph containing X. */
6415 glyph = row->glyphs[*area];
6416 end = glyph + row->used[*area];
6417 while (glyph < end)
6419 if (x < x0 + glyph->pixel_width)
6421 if (w->pseudo_window_p)
6422 break;
6423 else if (BUFFERP (glyph->object))
6424 break;
6427 x0 += glyph->pixel_width;
6428 ++glyph;
6431 if (glyph == end)
6432 return NULL;
6434 *hpos = glyph - row->glyphs[*area];
6435 return glyph;
6439 /* Convert frame-relative x/y to coordinates relative to window W.
6440 Takes pseudo-windows into account. */
6442 static void
6443 frame_to_window_pixel_xy (w, x, y)
6444 struct window *w;
6445 int *x, *y;
6447 if (w->pseudo_window_p)
6449 /* A pseudo-window is always full-width, and starts at the
6450 left edge of the frame, plus a frame border. */
6451 struct frame *f = XFRAME (w->frame);
6452 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6453 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6455 else
6457 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6458 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6463 /* Take proper action when mouse has moved to the mode or top line of
6464 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6465 mode line. X is relative to the start of the text display area of
6466 W, so the width of bitmap areas and scroll bars must be subtracted
6467 to get a position relative to the start of the mode line. */
6469 static void
6470 note_mode_line_highlight (w, x, mode_line_p)
6471 struct window *w;
6472 int x, mode_line_p;
6474 struct frame *f = XFRAME (w->frame);
6475 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6476 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6477 struct glyph_row *row;
6479 if (mode_line_p)
6480 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6481 else
6482 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6484 if (row->enabled_p)
6486 struct glyph *glyph, *end;
6487 Lisp_Object help, map;
6488 int x0;
6490 /* Find the glyph under X. */
6491 glyph = row->glyphs[TEXT_AREA];
6492 end = glyph + row->used[TEXT_AREA];
6493 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6494 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6495 while (glyph < end
6496 && x >= x0 + glyph->pixel_width)
6498 x0 += glyph->pixel_width;
6499 ++glyph;
6502 if (glyph < end
6503 && STRINGP (glyph->object)
6504 && XSTRING (glyph->object)->intervals
6505 && glyph->charpos >= 0
6506 && glyph->charpos < XSTRING (glyph->object)->size)
6508 /* If we're on a string with `help-echo' text property,
6509 arrange for the help to be displayed. This is done by
6510 setting the global variable help_echo to the help string. */
6511 help = Fget_text_property (make_number (glyph->charpos),
6512 Qhelp_echo, glyph->object);
6513 if (!NILP (help))
6515 help_echo = help;
6516 XSETWINDOW (help_echo_window, w);
6517 help_echo_object = glyph->object;
6518 help_echo_pos = glyph->charpos;
6521 /* Change the mouse pointer according to what is under X/Y. */
6522 map = Fget_text_property (make_number (glyph->charpos),
6523 Qlocal_map, glyph->object);
6524 if (KEYMAPP (map))
6525 cursor = f->output_data.x->nontext_cursor;
6526 else
6528 map = Fget_text_property (make_number (glyph->charpos),
6529 Qkeymap, glyph->object);
6530 if (KEYMAPP (map))
6531 cursor = f->output_data.x->nontext_cursor;
6536 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6540 /* Take proper action when the mouse has moved to position X, Y on
6541 frame F as regards highlighting characters that have mouse-face
6542 properties. Also de-highlighting chars where the mouse was before.
6543 X and Y can be negative or out of range. */
6545 static void
6546 note_mouse_highlight (f, x, y)
6547 struct frame *f;
6548 int x, y;
6550 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6551 int portion;
6552 Lisp_Object window;
6553 struct window *w;
6555 /* When a menu is active, don't highlight because this looks odd. */
6556 #ifdef USE_X_TOOLKIT
6557 if (popup_activated ())
6558 return;
6559 #endif
6561 if (disable_mouse_highlight
6562 || !f->glyphs_initialized_p)
6563 return;
6565 dpyinfo->mouse_face_mouse_x = x;
6566 dpyinfo->mouse_face_mouse_y = y;
6567 dpyinfo->mouse_face_mouse_frame = f;
6569 if (dpyinfo->mouse_face_defer)
6570 return;
6572 if (gc_in_progress)
6574 dpyinfo->mouse_face_deferred_gc = 1;
6575 return;
6578 /* Which window is that in? */
6579 window = window_from_coordinates (f, x, y, &portion, 1);
6581 /* If we were displaying active text in another window, clear that. */
6582 if (! EQ (window, dpyinfo->mouse_face_window))
6583 clear_mouse_face (dpyinfo);
6585 /* Not on a window -> return. */
6586 if (!WINDOWP (window))
6587 return;
6589 /* Convert to window-relative pixel coordinates. */
6590 w = XWINDOW (window);
6591 frame_to_window_pixel_xy (w, &x, &y);
6593 /* Handle tool-bar window differently since it doesn't display a
6594 buffer. */
6595 if (EQ (window, f->tool_bar_window))
6597 note_tool_bar_highlight (f, x, y);
6598 return;
6601 if (portion == 1 || portion == 3)
6603 /* Mouse is on the mode or top line. */
6604 note_mode_line_highlight (w, x, portion == 1);
6605 return;
6607 else
6608 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6609 f->output_data.x->text_cursor);
6611 /* Are we in a window whose display is up to date?
6612 And verify the buffer's text has not changed. */
6613 if (/* Within text portion of the window. */
6614 portion == 0
6615 && EQ (w->window_end_valid, w->buffer)
6616 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6617 && (XFASTINT (w->last_overlay_modified)
6618 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6620 int hpos, vpos, pos, i, area;
6621 struct glyph *glyph;
6623 /* Find the glyph under X/Y. */
6624 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6626 /* Clear mouse face if X/Y not over text. */
6627 if (glyph == NULL
6628 || area != TEXT_AREA
6629 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6631 clear_mouse_face (dpyinfo);
6632 return;
6635 pos = glyph->charpos;
6636 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6638 /* Check for mouse-face and help-echo. */
6640 Lisp_Object mouse_face, overlay, position;
6641 Lisp_Object *overlay_vec;
6642 int len, noverlays;
6643 struct buffer *obuf;
6644 int obegv, ozv;
6646 /* If we get an out-of-range value, return now; avoid an error. */
6647 if (pos > BUF_Z (XBUFFER (w->buffer)))
6648 return;
6650 /* Make the window's buffer temporarily current for
6651 overlays_at and compute_char_face. */
6652 obuf = current_buffer;
6653 current_buffer = XBUFFER (w->buffer);
6654 obegv = BEGV;
6655 ozv = ZV;
6656 BEGV = BEG;
6657 ZV = Z;
6659 /* Is this char mouse-active or does it have help-echo? */
6660 XSETINT (position, pos);
6662 /* Put all the overlays we want in a vector in overlay_vec.
6663 Store the length in len. If there are more than 10, make
6664 enough space for all, and try again. */
6665 len = 10;
6666 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6667 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6668 if (noverlays > len)
6670 len = noverlays;
6671 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6672 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6675 /* Sort overlays into increasing priority order. */
6676 noverlays = sort_overlays (overlay_vec, noverlays, w);
6678 /* Check mouse-face highlighting. */
6679 if (! (EQ (window, dpyinfo->mouse_face_window)
6680 && vpos >= dpyinfo->mouse_face_beg_row
6681 && vpos <= dpyinfo->mouse_face_end_row
6682 && (vpos > dpyinfo->mouse_face_beg_row
6683 || hpos >= dpyinfo->mouse_face_beg_col)
6684 && (vpos < dpyinfo->mouse_face_end_row
6685 || hpos < dpyinfo->mouse_face_end_col
6686 || dpyinfo->mouse_face_past_end)))
6688 /* Clear the display of the old active region, if any. */
6689 clear_mouse_face (dpyinfo);
6691 /* Find the highest priority overlay that has a mouse-face prop. */
6692 overlay = Qnil;
6693 for (i = noverlays - 1; i >= 0; --i)
6695 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6696 if (!NILP (mouse_face))
6698 overlay = overlay_vec[i];
6699 break;
6703 /* If no overlay applies, get a text property. */
6704 if (NILP (overlay))
6705 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6707 /* Handle the overlay case. */
6708 if (! NILP (overlay))
6710 /* Find the range of text around this char that
6711 should be active. */
6712 Lisp_Object before, after;
6713 int ignore;
6715 before = Foverlay_start (overlay);
6716 after = Foverlay_end (overlay);
6717 /* Record this as the current active region. */
6718 fast_find_position (w, XFASTINT (before),
6719 &dpyinfo->mouse_face_beg_col,
6720 &dpyinfo->mouse_face_beg_row,
6721 &dpyinfo->mouse_face_beg_x,
6722 &dpyinfo->mouse_face_beg_y);
6723 dpyinfo->mouse_face_past_end
6724 = !fast_find_position (w, XFASTINT (after),
6725 &dpyinfo->mouse_face_end_col,
6726 &dpyinfo->mouse_face_end_row,
6727 &dpyinfo->mouse_face_end_x,
6728 &dpyinfo->mouse_face_end_y);
6729 dpyinfo->mouse_face_window = window;
6730 dpyinfo->mouse_face_face_id
6731 = face_at_buffer_position (w, pos, 0, 0,
6732 &ignore, pos + 1, 1);
6734 /* Display it as active. */
6735 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6737 /* Handle the text property case. */
6738 else if (! NILP (mouse_face))
6740 /* Find the range of text around this char that
6741 should be active. */
6742 Lisp_Object before, after, beginning, end;
6743 int ignore;
6745 beginning = Fmarker_position (w->start);
6746 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6747 - XFASTINT (w->window_end_pos)));
6748 before
6749 = Fprevious_single_property_change (make_number (pos + 1),
6750 Qmouse_face,
6751 w->buffer, beginning);
6752 after
6753 = Fnext_single_property_change (position, Qmouse_face,
6754 w->buffer, end);
6755 /* Record this as the current active region. */
6756 fast_find_position (w, XFASTINT (before),
6757 &dpyinfo->mouse_face_beg_col,
6758 &dpyinfo->mouse_face_beg_row,
6759 &dpyinfo->mouse_face_beg_x,
6760 &dpyinfo->mouse_face_beg_y);
6761 dpyinfo->mouse_face_past_end
6762 = !fast_find_position (w, XFASTINT (after),
6763 &dpyinfo->mouse_face_end_col,
6764 &dpyinfo->mouse_face_end_row,
6765 &dpyinfo->mouse_face_end_x,
6766 &dpyinfo->mouse_face_end_y);
6767 dpyinfo->mouse_face_window = window;
6768 dpyinfo->mouse_face_face_id
6769 = face_at_buffer_position (w, pos, 0, 0,
6770 &ignore, pos + 1, 1);
6772 /* Display it as active. */
6773 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6777 /* Look for a `help-echo' property. */
6779 Lisp_Object help, overlay;
6781 /* Check overlays first. */
6782 help = overlay = Qnil;
6783 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6785 overlay = overlay_vec[i];
6786 help = Foverlay_get (overlay, Qhelp_echo);
6789 if (!NILP (help))
6791 help_echo = help;
6792 help_echo_window = window;
6793 help_echo_object = overlay;
6794 help_echo_pos = pos;
6796 else
6798 /* Try text properties. */
6799 if ((STRINGP (glyph->object)
6800 && glyph->charpos >= 0
6801 && glyph->charpos < XSTRING (glyph->object)->size)
6802 || (BUFFERP (glyph->object)
6803 && glyph->charpos >= BEGV
6804 && glyph->charpos < ZV))
6805 help = Fget_text_property (make_number (glyph->charpos),
6806 Qhelp_echo, glyph->object);
6808 if (!NILP (help))
6810 help_echo = help;
6811 help_echo_window = window;
6812 help_echo_object = glyph->object;
6813 help_echo_pos = glyph->charpos;
6818 BEGV = obegv;
6819 ZV = ozv;
6820 current_buffer = obuf;
6825 static void
6826 redo_mouse_highlight ()
6828 if (!NILP (last_mouse_motion_frame)
6829 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6830 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6831 last_mouse_motion_event.x,
6832 last_mouse_motion_event.y);
6837 /***********************************************************************
6838 Tool-bars
6839 ***********************************************************************/
6841 static int x_tool_bar_item P_ ((struct frame *, int, int,
6842 struct glyph **, int *, int *, int *));
6844 /* Tool-bar item index of the item on which a mouse button was pressed
6845 or -1. */
6847 static int last_tool_bar_item;
6850 /* Get information about the tool-bar item at position X/Y on frame F.
6851 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6852 the current matrix of the tool-bar window of F, or NULL if not
6853 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6854 item in F->current_tool_bar_items. Value is
6856 -1 if X/Y is not on a tool-bar item
6857 0 if X/Y is on the same item that was highlighted before.
6858 1 otherwise. */
6860 static int
6861 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6862 struct frame *f;
6863 int x, y;
6864 struct glyph **glyph;
6865 int *hpos, *vpos, *prop_idx;
6867 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6868 struct window *w = XWINDOW (f->tool_bar_window);
6869 int area;
6871 /* Find the glyph under X/Y. */
6872 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6873 if (*glyph == NULL)
6874 return -1;
6876 /* Get the start of this tool-bar item's properties in
6877 f->current_tool_bar_items. */
6878 if (!tool_bar_item_info (f, *glyph, prop_idx))
6879 return -1;
6881 /* Is mouse on the highlighted item? */
6882 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6883 && *vpos >= dpyinfo->mouse_face_beg_row
6884 && *vpos <= dpyinfo->mouse_face_end_row
6885 && (*vpos > dpyinfo->mouse_face_beg_row
6886 || *hpos >= dpyinfo->mouse_face_beg_col)
6887 && (*vpos < dpyinfo->mouse_face_end_row
6888 || *hpos < dpyinfo->mouse_face_end_col
6889 || dpyinfo->mouse_face_past_end))
6890 return 0;
6892 return 1;
6896 /* Handle mouse button event on the tool-bar of frame F, at
6897 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6898 or ButtonRelase. */
6900 static void
6901 x_handle_tool_bar_click (f, button_event)
6902 struct frame *f;
6903 XButtonEvent *button_event;
6905 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6906 struct window *w = XWINDOW (f->tool_bar_window);
6907 int hpos, vpos, prop_idx;
6908 struct glyph *glyph;
6909 Lisp_Object enabled_p;
6910 int x = button_event->x;
6911 int y = button_event->y;
6913 /* If not on the highlighted tool-bar item, return. */
6914 frame_to_window_pixel_xy (w, &x, &y);
6915 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6916 return;
6918 /* If item is disabled, do nothing. */
6919 enabled_p = (XVECTOR (f->current_tool_bar_items)
6920 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6921 if (NILP (enabled_p))
6922 return;
6924 if (button_event->type == ButtonPress)
6926 /* Show item in pressed state. */
6927 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6928 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6929 last_tool_bar_item = prop_idx;
6931 else
6933 Lisp_Object key, frame;
6934 struct input_event event;
6936 /* Show item in released state. */
6937 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6938 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6940 key = (XVECTOR (f->current_tool_bar_items)
6941 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6943 XSETFRAME (frame, f);
6944 event.kind = TOOL_BAR_EVENT;
6945 event.frame_or_window = frame;
6946 event.arg = frame;
6947 kbd_buffer_store_event (&event);
6949 event.kind = TOOL_BAR_EVENT;
6950 event.frame_or_window = frame;
6951 event.arg = key;
6952 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6953 button_event->state);
6954 kbd_buffer_store_event (&event);
6955 last_tool_bar_item = -1;
6960 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6961 tool-bar window-relative coordinates X/Y. Called from
6962 note_mouse_highlight. */
6964 static void
6965 note_tool_bar_highlight (f, x, y)
6966 struct frame *f;
6967 int x, y;
6969 Lisp_Object window = f->tool_bar_window;
6970 struct window *w = XWINDOW (window);
6971 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6972 int hpos, vpos;
6973 struct glyph *glyph;
6974 struct glyph_row *row;
6975 int i;
6976 Lisp_Object enabled_p;
6977 int prop_idx;
6978 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6979 int mouse_down_p, rc;
6981 /* Function note_mouse_highlight is called with negative x(y
6982 values when mouse moves outside of the frame. */
6983 if (x <= 0 || y <= 0)
6985 clear_mouse_face (dpyinfo);
6986 return;
6989 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6990 if (rc < 0)
6992 /* Not on tool-bar item. */
6993 clear_mouse_face (dpyinfo);
6994 return;
6996 else if (rc == 0)
6997 /* On same tool-bar item as before. */
6998 goto set_help_echo;
7000 clear_mouse_face (dpyinfo);
7002 /* Mouse is down, but on different tool-bar item? */
7003 mouse_down_p = (dpyinfo->grabbed
7004 && f == last_mouse_frame
7005 && FRAME_LIVE_P (f));
7006 if (mouse_down_p
7007 && last_tool_bar_item != prop_idx)
7008 return;
7010 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7011 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7013 /* If tool-bar item is not enabled, don't highlight it. */
7014 enabled_p = (XVECTOR (f->current_tool_bar_items)
7015 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
7016 if (!NILP (enabled_p))
7018 /* Compute the x-position of the glyph. In front and past the
7019 image is a space. We include this is the highlighted area. */
7020 row = MATRIX_ROW (w->current_matrix, vpos);
7021 for (i = x = 0; i < hpos; ++i)
7022 x += row->glyphs[TEXT_AREA][i].pixel_width;
7024 /* Record this as the current active region. */
7025 dpyinfo->mouse_face_beg_col = hpos;
7026 dpyinfo->mouse_face_beg_row = vpos;
7027 dpyinfo->mouse_face_beg_x = x;
7028 dpyinfo->mouse_face_beg_y = row->y;
7029 dpyinfo->mouse_face_past_end = 0;
7031 dpyinfo->mouse_face_end_col = hpos + 1;
7032 dpyinfo->mouse_face_end_row = vpos;
7033 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7034 dpyinfo->mouse_face_end_y = row->y;
7035 dpyinfo->mouse_face_window = window;
7036 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7038 /* Display it as active. */
7039 show_mouse_face (dpyinfo, draw);
7040 dpyinfo->mouse_face_image_state = draw;
7043 set_help_echo:
7045 /* Set help_echo to a help string.to display for this tool-bar item.
7046 XTread_socket does the rest. */
7047 help_echo_object = help_echo_window = Qnil;
7048 help_echo_pos = -1;
7049 help_echo = (XVECTOR (f->current_tool_bar_items)
7050 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
7051 if (NILP (help_echo))
7052 help_echo = (XVECTOR (f->current_tool_bar_items)
7053 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
7058 /* Find the glyph matrix position of buffer position POS in window W.
7059 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7060 current glyphs must be up to date. If POS is above window start
7061 return (0, 0, 0, 0). If POS is after end of W, return end of
7062 last line in W. */
7064 static int
7065 fast_find_position (w, pos, hpos, vpos, x, y)
7066 struct window *w;
7067 int pos;
7068 int *hpos, *vpos, *x, *y;
7070 int i;
7071 int lastcol;
7072 int maybe_next_line_p = 0;
7073 int line_start_position;
7074 int yb = window_text_bottom_y (w);
7075 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7076 struct glyph_row *best_row = row;
7077 int row_vpos = 0, best_row_vpos = 0;
7078 int current_x;
7080 while (row->y < yb)
7082 if (row->used[TEXT_AREA])
7083 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7084 else
7085 line_start_position = 0;
7087 if (line_start_position > pos)
7088 break;
7089 /* If the position sought is the end of the buffer,
7090 don't include the blank lines at the bottom of the window. */
7091 else if (line_start_position == pos
7092 && pos == BUF_ZV (XBUFFER (w->buffer)))
7094 maybe_next_line_p = 1;
7095 break;
7097 else if (line_start_position > 0)
7099 best_row = row;
7100 best_row_vpos = row_vpos;
7103 if (row->y + row->height >= yb)
7104 break;
7106 ++row;
7107 ++row_vpos;
7110 /* Find the right column within BEST_ROW. */
7111 lastcol = 0;
7112 current_x = best_row->x;
7113 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7115 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7116 int charpos;
7118 charpos = glyph->charpos;
7119 if (charpos == pos)
7121 *hpos = i;
7122 *vpos = best_row_vpos;
7123 *x = current_x;
7124 *y = best_row->y;
7125 return 1;
7127 else if (charpos > pos)
7128 break;
7129 else if (charpos > 0)
7130 lastcol = i;
7132 current_x += glyph->pixel_width;
7135 /* If we're looking for the end of the buffer,
7136 and we didn't find it in the line we scanned,
7137 use the start of the following line. */
7138 if (maybe_next_line_p)
7140 ++best_row;
7141 ++best_row_vpos;
7142 lastcol = 0;
7143 current_x = best_row->x;
7146 *vpos = best_row_vpos;
7147 *hpos = lastcol + 1;
7148 *x = current_x;
7149 *y = best_row->y;
7150 return 0;
7154 /* Display the active region described by mouse_face_*
7155 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7157 static void
7158 show_mouse_face (dpyinfo, draw)
7159 struct x_display_info *dpyinfo;
7160 enum draw_glyphs_face draw;
7162 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7163 struct frame *f = XFRAME (WINDOW_FRAME (w));
7164 int i;
7165 int cursor_off_p = 0;
7166 struct cursor_pos saved_cursor;
7168 saved_cursor = output_cursor;
7170 /* If window is in the process of being destroyed, don't bother
7171 to do anything. */
7172 if (w->current_matrix == NULL)
7173 goto set_x_cursor;
7175 /* Recognize when we are called to operate on rows that don't exist
7176 anymore. This can happen when a window is split. */
7177 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7178 goto set_x_cursor;
7180 set_output_cursor (&w->phys_cursor);
7182 /* Note that mouse_face_beg_row etc. are window relative. */
7183 for (i = dpyinfo->mouse_face_beg_row;
7184 i <= dpyinfo->mouse_face_end_row;
7185 i++)
7187 int start_hpos, end_hpos, start_x;
7188 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7190 /* Don't do anything if row doesn't have valid contents. */
7191 if (!row->enabled_p)
7192 continue;
7194 /* For all but the first row, the highlight starts at column 0. */
7195 if (i == dpyinfo->mouse_face_beg_row)
7197 start_hpos = dpyinfo->mouse_face_beg_col;
7198 start_x = dpyinfo->mouse_face_beg_x;
7200 else
7202 start_hpos = 0;
7203 start_x = 0;
7206 if (i == dpyinfo->mouse_face_end_row)
7207 end_hpos = dpyinfo->mouse_face_end_col;
7208 else
7209 end_hpos = row->used[TEXT_AREA];
7211 /* If the cursor's in the text we are about to rewrite, turn the
7212 cursor off. */
7213 if (!w->pseudo_window_p
7214 && i == output_cursor.vpos
7215 && output_cursor.hpos >= start_hpos - 1
7216 && output_cursor.hpos <= end_hpos)
7218 x_update_window_cursor (w, 0);
7219 cursor_off_p = 1;
7222 if (end_hpos > start_hpos)
7224 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7225 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7226 start_hpos, end_hpos, draw, NULL, NULL, 0);
7230 /* If we turned the cursor off, turn it back on. */
7231 if (cursor_off_p)
7232 x_display_cursor (w, 1,
7233 output_cursor.hpos, output_cursor.vpos,
7234 output_cursor.x, output_cursor.y);
7236 output_cursor = saved_cursor;
7238 set_x_cursor:
7240 /* Change the mouse cursor. */
7241 if (draw == DRAW_NORMAL_TEXT)
7242 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7243 f->output_data.x->text_cursor);
7244 else if (draw == DRAW_MOUSE_FACE)
7245 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7246 f->output_data.x->cross_cursor);
7247 else
7248 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7249 f->output_data.x->nontext_cursor);
7252 /* Clear out the mouse-highlighted active region.
7253 Redraw it un-highlighted first. */
7255 void
7256 clear_mouse_face (dpyinfo)
7257 struct x_display_info *dpyinfo;
7259 if (tip_frame)
7260 return;
7262 if (! NILP (dpyinfo->mouse_face_window))
7263 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7265 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7266 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7267 dpyinfo->mouse_face_window = Qnil;
7271 /* Clear any mouse-face on window W. This function is part of the
7272 redisplay interface, and is called from try_window_id and similar
7273 functions to ensure the mouse-highlight is off. */
7275 static void
7276 x_clear_mouse_face (w)
7277 struct window *w;
7279 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7280 Lisp_Object window;
7282 BLOCK_INPUT;
7283 XSETWINDOW (window, w);
7284 if (EQ (window, dpyinfo->mouse_face_window))
7285 clear_mouse_face (dpyinfo);
7286 UNBLOCK_INPUT;
7290 /* Just discard the mouse face information for frame F, if any.
7291 This is used when the size of F is changed. */
7293 void
7294 cancel_mouse_face (f)
7295 FRAME_PTR f;
7297 Lisp_Object window;
7298 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7300 window = dpyinfo->mouse_face_window;
7301 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7303 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7304 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7305 dpyinfo->mouse_face_window = Qnil;
7309 static struct scroll_bar *x_window_to_scroll_bar ();
7310 static void x_scroll_bar_report_motion ();
7312 /* Return the current position of the mouse.
7313 *fp should be a frame which indicates which display to ask about.
7315 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7316 and *part to the frame, window, and scroll bar part that the mouse
7317 is over. Set *x and *y to the portion and whole of the mouse's
7318 position on the scroll bar.
7320 If the mouse movement started elsewhere, set *fp to the frame the
7321 mouse is on, *bar_window to nil, and *x and *y to the character cell
7322 the mouse is over.
7324 Set *time to the server time-stamp for the time at which the mouse
7325 was at this position.
7327 Don't store anything if we don't have a valid set of values to report.
7329 This clears the mouse_moved flag, so we can wait for the next mouse
7330 movement. */
7332 static void
7333 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7334 FRAME_PTR *fp;
7335 int insist;
7336 Lisp_Object *bar_window;
7337 enum scroll_bar_part *part;
7338 Lisp_Object *x, *y;
7339 unsigned long *time;
7341 FRAME_PTR f1;
7343 BLOCK_INPUT;
7345 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7346 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7347 else
7349 Window root;
7350 int root_x, root_y;
7352 Window dummy_window;
7353 int dummy;
7355 Lisp_Object frame, tail;
7357 /* Clear the mouse-moved flag for every frame on this display. */
7358 FOR_EACH_FRAME (tail, frame)
7359 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7360 XFRAME (frame)->mouse_moved = 0;
7362 last_mouse_scroll_bar = Qnil;
7364 /* Figure out which root window we're on. */
7365 XQueryPointer (FRAME_X_DISPLAY (*fp),
7366 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7368 /* The root window which contains the pointer. */
7369 &root,
7371 /* Trash which we can't trust if the pointer is on
7372 a different screen. */
7373 &dummy_window,
7375 /* The position on that root window. */
7376 &root_x, &root_y,
7378 /* More trash we can't trust. */
7379 &dummy, &dummy,
7381 /* Modifier keys and pointer buttons, about which
7382 we don't care. */
7383 (unsigned int *) &dummy);
7385 /* Now we have a position on the root; find the innermost window
7386 containing the pointer. */
7388 Window win, child;
7389 int win_x, win_y;
7390 int parent_x = 0, parent_y = 0;
7391 int count;
7393 win = root;
7395 /* XTranslateCoordinates can get errors if the window
7396 structure is changing at the same time this function
7397 is running. So at least we must not crash from them. */
7399 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7401 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7402 && FRAME_LIVE_P (last_mouse_frame))
7404 /* If mouse was grabbed on a frame, give coords for that frame
7405 even if the mouse is now outside it. */
7406 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7408 /* From-window, to-window. */
7409 root, FRAME_X_WINDOW (last_mouse_frame),
7411 /* From-position, to-position. */
7412 root_x, root_y, &win_x, &win_y,
7414 /* Child of win. */
7415 &child);
7416 f1 = last_mouse_frame;
7418 else
7420 while (1)
7422 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7424 /* From-window, to-window. */
7425 root, win,
7427 /* From-position, to-position. */
7428 root_x, root_y, &win_x, &win_y,
7430 /* Child of win. */
7431 &child);
7433 if (child == None || child == win)
7434 break;
7436 win = child;
7437 parent_x = win_x;
7438 parent_y = win_y;
7441 /* Now we know that:
7442 win is the innermost window containing the pointer
7443 (XTC says it has no child containing the pointer),
7444 win_x and win_y are the pointer's position in it
7445 (XTC did this the last time through), and
7446 parent_x and parent_y are the pointer's position in win's parent.
7447 (They are what win_x and win_y were when win was child.
7448 If win is the root window, it has no parent, and
7449 parent_{x,y} are invalid, but that's okay, because we'll
7450 never use them in that case.) */
7452 /* Is win one of our frames? */
7453 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7456 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7457 f1 = 0;
7459 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7461 /* If not, is it one of our scroll bars? */
7462 if (! f1)
7464 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7466 if (bar)
7468 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7469 win_x = parent_x;
7470 win_y = parent_y;
7474 if (f1 == 0 && insist > 0)
7475 f1 = SELECTED_FRAME ();
7477 if (f1)
7479 /* Ok, we found a frame. Store all the values.
7480 last_mouse_glyph is a rectangle used to reduce the
7481 generation of mouse events. To not miss any motion
7482 events, we must divide the frame into rectangles of the
7483 size of the smallest character that could be displayed
7484 on it, i.e. into the same rectangles that matrices on
7485 the frame are divided into. */
7487 #if OLD_REDISPLAY_CODE
7488 int ignore1, ignore2;
7489 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7490 &last_mouse_glyph,
7491 FRAME_X_DISPLAY_INFO (f1)->grabbed
7492 || insist);
7493 #else
7495 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7496 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7497 int x = win_x;
7498 int y = win_y;
7500 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7501 round down even for negative values. */
7502 if (x < 0)
7503 x -= width - 1;
7504 if (y < 0)
7505 y -= height - 1;
7507 last_mouse_glyph.width = width;
7508 last_mouse_glyph.height = height;
7509 last_mouse_glyph.x = (x + width - 1) / width * width;
7510 last_mouse_glyph.y = (y + height - 1) / height * height;
7512 #endif
7514 *bar_window = Qnil;
7515 *part = 0;
7516 *fp = f1;
7517 XSETINT (*x, win_x);
7518 XSETINT (*y, win_y);
7519 *time = last_mouse_movement_time;
7524 UNBLOCK_INPUT;
7528 #ifdef USE_X_TOOLKIT
7530 /* Atimer callback function for TIMER. Called every 0.1s to process
7531 Xt timeouts, if needed. We must avoid calling XtAppPending as
7532 much as possible because that function does an implicit XFlush
7533 that slows us down. */
7535 static void
7536 x_process_timeouts (timer)
7537 struct atimer *timer;
7539 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7541 BLOCK_INPUT;
7542 while (XtAppPending (Xt_app_con) & XtIMTimer)
7543 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7544 UNBLOCK_INPUT;
7548 #endif /* USE_X_TOOLKIT */
7551 /* Scroll bar support. */
7553 /* Given an X window ID, find the struct scroll_bar which manages it.
7554 This can be called in GC, so we have to make sure to strip off mark
7555 bits. */
7557 static struct scroll_bar *
7558 x_window_to_scroll_bar (window_id)
7559 Window window_id;
7561 Lisp_Object tail;
7563 for (tail = Vframe_list;
7564 XGCTYPE (tail) == Lisp_Cons;
7565 tail = XCDR (tail))
7567 Lisp_Object frame, bar, condemned;
7569 frame = XCAR (tail);
7570 /* All elements of Vframe_list should be frames. */
7571 if (! GC_FRAMEP (frame))
7572 abort ();
7574 /* Scan this frame's scroll bar list for a scroll bar with the
7575 right window ID. */
7576 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7577 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7578 /* This trick allows us to search both the ordinary and
7579 condemned scroll bar lists with one loop. */
7580 ! GC_NILP (bar) || (bar = condemned,
7581 condemned = Qnil,
7582 ! GC_NILP (bar));
7583 bar = XSCROLL_BAR (bar)->next)
7584 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7585 return XSCROLL_BAR (bar);
7588 return 0;
7593 /************************************************************************
7594 Toolkit scroll bars
7595 ************************************************************************/
7597 #if USE_TOOLKIT_SCROLL_BARS
7599 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7600 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7601 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7602 struct scroll_bar *));
7603 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7604 int, int, int));
7607 /* Id of action hook installed for scroll bars. */
7609 static XtActionHookId action_hook_id;
7611 /* Lisp window being scrolled. Set when starting to interact with
7612 a toolkit scroll bar, reset to nil when ending the interaction. */
7614 static Lisp_Object window_being_scrolled;
7616 /* Last scroll bar part sent in xm_scroll_callback. */
7618 static int last_scroll_bar_part;
7620 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7621 that movements of 1/20 of the screen size are mapped to up/down. */
7623 static Boolean xaw3d_arrow_scroll;
7625 /* Whether the drag scrolling maintains the mouse at the top of the
7626 thumb. If not, resizing the thumb needs to be done more carefully
7627 to avoid jerkyness. */
7629 static Boolean xaw3d_pick_top;
7632 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7633 bars are used.. The hook is responsible for detecting when
7634 the user ends an interaction with the scroll bar, and generates
7635 a `end-scroll' scroll_bar_click' event if so. */
7637 static void
7638 xt_action_hook (widget, client_data, action_name, event, params,
7639 num_params)
7640 Widget widget;
7641 XtPointer client_data;
7642 String action_name;
7643 XEvent *event;
7644 String *params;
7645 Cardinal *num_params;
7647 int scroll_bar_p;
7648 char *end_action;
7650 #ifdef USE_MOTIF
7651 scroll_bar_p = XmIsScrollBar (widget);
7652 end_action = "Release";
7653 #else /* !USE_MOTIF i.e. use Xaw */
7654 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7655 end_action = "EndScroll";
7656 #endif /* USE_MOTIF */
7658 if (scroll_bar_p
7659 && strcmp (action_name, end_action) == 0
7660 && WINDOWP (window_being_scrolled))
7662 struct window *w;
7664 x_send_scroll_bar_event (window_being_scrolled,
7665 scroll_bar_end_scroll, 0, 0);
7666 w = XWINDOW (window_being_scrolled);
7667 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7668 window_being_scrolled = Qnil;
7669 last_scroll_bar_part = -1;
7671 /* Xt timeouts no longer needed. */
7672 toolkit_scroll_bar_interaction = 0;
7677 /* Send a client message with message type Xatom_Scrollbar for a
7678 scroll action to the frame of WINDOW. PART is a value identifying
7679 the part of the scroll bar that was clicked on. PORTION is the
7680 amount to scroll of a whole of WHOLE. */
7682 static void
7683 x_send_scroll_bar_event (window, part, portion, whole)
7684 Lisp_Object window;
7685 int part, portion, whole;
7687 XEvent event;
7688 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7689 struct frame *f = XFRAME (XWINDOW (window)->frame);
7691 /* Construct a ClientMessage event to send to the frame. */
7692 ev->type = ClientMessage;
7693 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7694 ev->display = FRAME_X_DISPLAY (f);
7695 ev->window = FRAME_X_WINDOW (f);
7696 ev->format = 32;
7697 ev->data.l[0] = (long) XFASTINT (window);
7698 ev->data.l[1] = (long) part;
7699 ev->data.l[2] = (long) 0;
7700 ev->data.l[3] = (long) portion;
7701 ev->data.l[4] = (long) whole;
7703 /* Make Xt timeouts work while the scroll bar is active. */
7704 toolkit_scroll_bar_interaction = 1;
7706 /* Setting the event mask to zero means that the message will
7707 be sent to the client that created the window, and if that
7708 window no longer exists, no event will be sent. */
7709 BLOCK_INPUT;
7710 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7711 UNBLOCK_INPUT;
7715 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7716 in *IEVENT. */
7718 static void
7719 x_scroll_bar_to_input_event (event, ievent)
7720 XEvent *event;
7721 struct input_event *ievent;
7723 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7724 Lisp_Object window;
7725 struct frame *f;
7727 XSETFASTINT (window, ev->data.l[0]);
7728 f = XFRAME (XWINDOW (window)->frame);
7730 ievent->kind = scroll_bar_click;
7731 ievent->frame_or_window = window;
7732 ievent->arg = Qnil;
7733 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7734 ievent->part = ev->data.l[1];
7735 ievent->code = ev->data.l[2];
7736 ievent->x = make_number ((int) ev->data.l[3]);
7737 ievent->y = make_number ((int) ev->data.l[4]);
7738 ievent->modifiers = 0;
7742 #ifdef USE_MOTIF
7744 /* Minimum and maximum values used for Motif scroll bars. */
7746 #define XM_SB_MIN 1
7747 #define XM_SB_MAX 10000000
7748 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7751 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7752 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7753 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7755 static void
7756 xm_scroll_callback (widget, client_data, call_data)
7757 Widget widget;
7758 XtPointer client_data, call_data;
7760 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7761 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7762 double percent;
7763 int part = -1, whole = 0, portion = 0;
7765 switch (cs->reason)
7767 case XmCR_DECREMENT:
7768 bar->dragging = Qnil;
7769 part = scroll_bar_up_arrow;
7770 break;
7772 case XmCR_INCREMENT:
7773 bar->dragging = Qnil;
7774 part = scroll_bar_down_arrow;
7775 break;
7777 case XmCR_PAGE_DECREMENT:
7778 bar->dragging = Qnil;
7779 part = scroll_bar_above_handle;
7780 break;
7782 case XmCR_PAGE_INCREMENT:
7783 bar->dragging = Qnil;
7784 part = scroll_bar_below_handle;
7785 break;
7787 case XmCR_TO_TOP:
7788 bar->dragging = Qnil;
7789 part = scroll_bar_to_top;
7790 break;
7792 case XmCR_TO_BOTTOM:
7793 bar->dragging = Qnil;
7794 part = scroll_bar_to_bottom;
7795 break;
7797 case XmCR_DRAG:
7799 int slider_size;
7800 int dragging_down_p = (INTEGERP (bar->dragging)
7801 && XINT (bar->dragging) <= cs->value);
7803 /* Get the slider size. */
7804 BLOCK_INPUT;
7805 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7806 UNBLOCK_INPUT;
7808 /* At the max position of the scroll bar, do a line-wise
7809 movement. Without doing anything, the LessTif scroll bar
7810 calls us with the same cs->value again and again. If we
7811 want to make sure that we can reach the end of the buffer,
7812 we have to do something.
7814 Implementation note: setting bar->dragging always to
7815 cs->value gives a smoother movement at the max position.
7816 Setting it to nil when doing line-wise movement gives
7817 a better slider behavior. */
7819 if (cs->value + slider_size == XM_SB_MAX
7820 || (dragging_down_p
7821 && last_scroll_bar_part == scroll_bar_down_arrow))
7823 part = scroll_bar_down_arrow;
7824 bar->dragging = Qnil;
7826 else
7828 whole = XM_SB_RANGE;
7829 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7830 part = scroll_bar_handle;
7831 bar->dragging = make_number (cs->value);
7834 break;
7836 case XmCR_VALUE_CHANGED:
7837 break;
7840 if (part >= 0)
7842 window_being_scrolled = bar->window;
7843 last_scroll_bar_part = part;
7844 x_send_scroll_bar_event (bar->window, part, portion, whole);
7849 #else /* !USE_MOTIF, i.e. Xaw. */
7852 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7853 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7854 scroll bar struct. CALL_DATA is a pointer to a float saying where
7855 the thumb is. */
7857 static void
7858 xaw_jump_callback (widget, client_data, call_data)
7859 Widget widget;
7860 XtPointer client_data, call_data;
7862 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7863 float top = *(float *) call_data;
7864 float shown;
7865 int whole, portion, height;
7866 int part;
7868 /* Get the size of the thumb, a value between 0 and 1. */
7869 BLOCK_INPUT;
7870 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7871 UNBLOCK_INPUT;
7873 whole = 10000000;
7874 portion = shown < 1 ? top * whole : 0;
7876 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7877 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7878 the bottom, so we force the scrolling whenever we see that we're
7879 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7880 we try to ensure that we always stay two pixels away from the
7881 bottom). */
7882 part = scroll_bar_down_arrow;
7883 else
7884 part = scroll_bar_handle;
7886 window_being_scrolled = bar->window;
7887 bar->dragging = make_number (portion);
7888 last_scroll_bar_part = part;
7889 x_send_scroll_bar_event (bar->window, part, portion, whole);
7893 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7894 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7895 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7896 the scroll bar. CALL_DATA is an integer specifying the action that
7897 has taken place. It's magnitude is in the range 0..height of the
7898 scroll bar. Negative values mean scroll towards buffer start.
7899 Values < height of scroll bar mean line-wise movement. */
7901 static void
7902 xaw_scroll_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 int position = (int) call_data;
7908 Dimension height;
7909 int part;
7911 /* Get the height of the scroll bar. */
7912 BLOCK_INPUT;
7913 XtVaGetValues (widget, XtNheight, &height, NULL);
7914 UNBLOCK_INPUT;
7916 if (abs (position) >= height)
7917 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7919 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7920 it maps line-movement to call_data = max(5, height/20). */
7921 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7922 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7923 else
7924 part = scroll_bar_move_ratio;
7926 window_being_scrolled = bar->window;
7927 bar->dragging = Qnil;
7928 last_scroll_bar_part = part;
7929 x_send_scroll_bar_event (bar->window, part, position, height);
7933 #endif /* not USE_MOTIF */
7936 /* Create the widget for scroll bar BAR on frame F. Record the widget
7937 and X window of the scroll bar in BAR. */
7939 static void
7940 x_create_toolkit_scroll_bar (f, bar)
7941 struct frame *f;
7942 struct scroll_bar *bar;
7944 Window xwindow;
7945 Widget widget;
7946 Arg av[20];
7947 int ac = 0;
7948 char *scroll_bar_name = "verticalScrollBar";
7949 unsigned long pixel;
7951 BLOCK_INPUT;
7953 #ifdef USE_MOTIF
7954 /* LessTif 0.85, problems:
7956 1. When the mouse if over the scroll bar, the scroll bar will
7957 get keyboard events. I didn't find a way to turn this off.
7959 2. Do we have to explicitly set the cursor to get an arrow
7960 cursor (see below)? */
7962 /* Set resources. Create the widget. */
7963 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7964 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7965 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7966 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7967 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7968 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7969 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7971 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7972 if (pixel != -1)
7974 XtSetArg (av[ac], XmNforeground, pixel);
7975 ++ac;
7978 pixel = f->output_data.x->scroll_bar_background_pixel;
7979 if (pixel != -1)
7981 XtSetArg (av[ac], XmNbackground, pixel);
7982 ++ac;
7985 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7986 scroll_bar_name, av, ac);
7988 /* Add one callback for everything that can happen. */
7989 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7990 (XtPointer) bar);
7991 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7992 (XtPointer) bar);
7993 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7994 (XtPointer) bar);
7995 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7996 (XtPointer) bar);
7997 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7998 (XtPointer) bar);
7999 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8000 (XtPointer) bar);
8001 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8002 (XtPointer) bar);
8004 /* Realize the widget. Only after that is the X window created. */
8005 XtRealizeWidget (widget);
8007 /* Set the cursor to an arrow. I didn't find a resource to do that.
8008 And I'm wondering why it hasn't an arrow cursor by default. */
8009 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8010 f->output_data.x->nontext_cursor);
8012 #else /* !USE_MOTIF i.e. use Xaw */
8014 /* Set resources. Create the widget. The background of the
8015 Xaw3d scroll bar widget is a little bit light for my taste.
8016 We don't alter it here to let users change it according
8017 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8018 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8019 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8020 /* For smoother scrolling with Xaw3d -sm */
8021 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8022 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8024 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8025 if (pixel != -1)
8027 XtSetArg (av[ac], XtNforeground, pixel);
8028 ++ac;
8031 pixel = f->output_data.x->scroll_bar_background_pixel;
8032 if (pixel != -1)
8034 XtSetArg (av[ac], XtNbackground, pixel);
8035 ++ac;
8038 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8039 f->output_data.x->edit_widget, av, ac);
8042 char *initial = "";
8043 char *val = initial;
8044 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8045 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8046 if (val == initial)
8047 { /* ARROW_SCROLL */
8048 xaw3d_arrow_scroll = True;
8049 /* Isn't that just a personal preference ? -sm */
8050 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8054 /* Define callbacks. */
8055 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8056 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8057 (XtPointer) bar);
8059 /* Realize the widget. Only after that is the X window created. */
8060 XtRealizeWidget (widget);
8062 #endif /* !USE_MOTIF */
8064 /* Install an action hook that let's us detect when the user
8065 finishes interacting with a scroll bar. */
8066 if (action_hook_id == 0)
8067 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8069 /* Remember X window and widget in the scroll bar vector. */
8070 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8071 xwindow = XtWindow (widget);
8072 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8074 UNBLOCK_INPUT;
8078 /* Set the thumb size and position of scroll bar BAR. We are currently
8079 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8081 static void
8082 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8083 struct scroll_bar *bar;
8084 int portion, position, whole;
8086 float top, shown;
8087 Widget widget = SCROLL_BAR_X_WIDGET (bar);
8089 if (whole == 0)
8090 top = 0, shown = 1;
8091 else
8093 top = (float) position / whole;
8094 shown = (float) portion / whole;
8097 BLOCK_INPUT;
8099 #ifdef USE_MOTIF
8101 int size, value;
8102 Boolean arrow1_selected, arrow2_selected;
8103 unsigned char flags;
8104 XmScrollBarWidget sb;
8106 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8107 is the scroll bar's maximum and MIN is the scroll bar's minimum
8108 value. */
8109 size = shown * XM_SB_RANGE;
8110 size = min (size, XM_SB_RANGE);
8111 size = max (size, 1);
8113 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8114 value = top * XM_SB_RANGE;
8115 value = min (value, XM_SB_MAX - size);
8116 value = max (value, XM_SB_MIN);
8118 /* LessTif: Calling XmScrollBarSetValues after an increment or
8119 decrement turns off auto-repeat LessTif-internally. This can
8120 be seen in ScrollBar.c which resets Arrow1Selected and
8121 Arrow2Selected. It also sets internal flags so that LessTif
8122 believes the mouse is in the slider. We either have to change
8123 our code, or work around that by accessing private data. */
8125 sb = (XmScrollBarWidget) widget;
8126 arrow1_selected = sb->scrollBar.arrow1_selected;
8127 arrow2_selected = sb->scrollBar.arrow2_selected;
8128 flags = sb->scrollBar.flags;
8130 if (NILP (bar->dragging))
8131 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8132 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8133 /* This has the negative side effect that the slider value is
8134 not what it would be if we scrolled here using line-wise or
8135 page-wise movement. */
8136 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8137 else
8139 /* If currently dragging, only update the slider size.
8140 This reduces flicker effects. */
8141 int old_value, old_size, increment, page_increment;
8143 XmScrollBarGetValues (widget, &old_value, &old_size,
8144 &increment, &page_increment);
8145 XmScrollBarSetValues (widget, old_value,
8146 min (size, XM_SB_RANGE - old_value),
8147 0, 0, False);
8150 sb->scrollBar.arrow1_selected = arrow1_selected;
8151 sb->scrollBar.arrow2_selected = arrow2_selected;
8152 sb->scrollBar.flags = flags;
8154 #else /* !USE_MOTIF i.e. use Xaw */
8156 float old_top, old_shown;
8157 Dimension height;
8158 XtVaGetValues (widget,
8159 XtNtopOfThumb, &old_top,
8160 XtNshown, &old_shown,
8161 XtNheight, &height,
8162 NULL);
8164 /* Massage the top+shown values. */
8165 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8166 top = max (0, min (1, top));
8167 else
8168 top = old_top;
8169 /* Keep two pixels available for moving the thumb down. */
8170 shown = max (0, min (1 - top - (2.0 / height), shown));
8172 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8173 check that your system's configuration file contains a define
8174 for `NARROWPROTO'. See s/freebsd.h for an example. */
8175 if (top != old_top || shown != old_shown)
8177 if (NILP (bar->dragging))
8178 XawScrollbarSetThumb (widget, top, shown);
8179 else
8181 #ifdef HAVE_XAW3D
8182 ScrollbarWidget sb = (ScrollbarWidget) widget;
8183 int scroll_mode = 0;
8185 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8186 if (xaw3d_arrow_scroll)
8188 /* Xaw3d stupidly ignores resize requests while dragging
8189 so we have to make it believe it's not in dragging mode. */
8190 scroll_mode = sb->scrollbar.scroll_mode;
8191 if (scroll_mode == 2)
8192 sb->scrollbar.scroll_mode = 0;
8194 #endif
8195 /* Try to make the scrolling a tad smoother. */
8196 if (!xaw3d_pick_top)
8197 shown = min (shown, old_shown);
8199 XawScrollbarSetThumb (widget, top, shown);
8201 #ifdef HAVE_XAW3D
8202 if (xaw3d_arrow_scroll && scroll_mode == 2)
8203 sb->scrollbar.scroll_mode = scroll_mode;
8204 #endif
8208 #endif /* !USE_MOTIF */
8210 UNBLOCK_INPUT;
8213 #endif /* USE_TOOLKIT_SCROLL_BARS */
8217 /************************************************************************
8218 Scroll bars, general
8219 ************************************************************************/
8221 /* Create a scroll bar and return the scroll bar vector for it. W is
8222 the Emacs window on which to create the scroll bar. TOP, LEFT,
8223 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8224 scroll bar. */
8226 static struct scroll_bar *
8227 x_scroll_bar_create (w, top, left, width, height)
8228 struct window *w;
8229 int top, left, width, height;
8231 struct frame *f = XFRAME (w->frame);
8232 struct scroll_bar *bar
8233 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8235 BLOCK_INPUT;
8237 #if USE_TOOLKIT_SCROLL_BARS
8238 x_create_toolkit_scroll_bar (f, bar);
8239 #else /* not USE_TOOLKIT_SCROLL_BARS */
8241 XSetWindowAttributes a;
8242 unsigned long mask;
8243 Window window;
8245 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8246 if (a.background_pixel == -1)
8247 a.background_pixel = f->output_data.x->background_pixel;
8249 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8250 | ButtonMotionMask | PointerMotionHintMask
8251 | ExposureMask);
8252 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8254 mask = (CWBackPixel | CWEventMask | CWCursor);
8256 /* Clear the area of W that will serve as a scroll bar. This is
8257 for the case that a window has been split horizontally. In
8258 this case, no clear_frame is generated to reduce flickering. */
8259 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8260 left, top, width,
8261 window_box_height (w), False);
8263 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8264 /* Position and size of scroll bar. */
8265 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8266 top,
8267 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8268 height,
8269 /* Border width, depth, class, and visual. */
8271 CopyFromParent,
8272 CopyFromParent,
8273 CopyFromParent,
8274 /* Attributes. */
8275 mask, &a);
8276 SET_SCROLL_BAR_X_WINDOW (bar, window);
8278 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8280 XSETWINDOW (bar->window, w);
8281 XSETINT (bar->top, top);
8282 XSETINT (bar->left, left);
8283 XSETINT (bar->width, width);
8284 XSETINT (bar->height, height);
8285 XSETINT (bar->start, 0);
8286 XSETINT (bar->end, 0);
8287 bar->dragging = Qnil;
8289 /* Add bar to its frame's list of scroll bars. */
8290 bar->next = FRAME_SCROLL_BARS (f);
8291 bar->prev = Qnil;
8292 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8293 if (!NILP (bar->next))
8294 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8296 /* Map the window/widget. */
8297 #if USE_TOOLKIT_SCROLL_BARS
8298 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8299 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8300 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8301 top,
8302 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8303 height, 0);
8304 #else /* not USE_TOOLKIT_SCROLL_BARS */
8305 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8306 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8308 UNBLOCK_INPUT;
8309 return bar;
8313 /* Draw BAR's handle in the proper position.
8315 If the handle is already drawn from START to END, don't bother
8316 redrawing it, unless REBUILD is non-zero; in that case, always
8317 redraw it. (REBUILD is handy for drawing the handle after expose
8318 events.)
8320 Normally, we want to constrain the start and end of the handle to
8321 fit inside its rectangle, but if the user is dragging the scroll
8322 bar handle, we want to let them drag it down all the way, so that
8323 the bar's top is as far down as it goes; otherwise, there's no way
8324 to move to the very end of the buffer. */
8326 #ifndef USE_TOOLKIT_SCROLL_BARS
8328 static void
8329 x_scroll_bar_set_handle (bar, start, end, rebuild)
8330 struct scroll_bar *bar;
8331 int start, end;
8332 int rebuild;
8334 int dragging = ! NILP (bar->dragging);
8335 Window w = SCROLL_BAR_X_WINDOW (bar);
8336 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8337 GC gc = f->output_data.x->normal_gc;
8339 /* If the display is already accurate, do nothing. */
8340 if (! rebuild
8341 && start == XINT (bar->start)
8342 && end == XINT (bar->end))
8343 return;
8345 BLOCK_INPUT;
8348 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8349 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8350 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8352 /* Make sure the values are reasonable, and try to preserve
8353 the distance between start and end. */
8355 int length = end - start;
8357 if (start < 0)
8358 start = 0;
8359 else if (start > top_range)
8360 start = top_range;
8361 end = start + length;
8363 if (end < start)
8364 end = start;
8365 else if (end > top_range && ! dragging)
8366 end = top_range;
8369 /* Store the adjusted setting in the scroll bar. */
8370 XSETINT (bar->start, start);
8371 XSETINT (bar->end, end);
8373 /* Clip the end position, just for display. */
8374 if (end > top_range)
8375 end = top_range;
8377 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8378 below top positions, to make sure the handle is always at least
8379 that many pixels tall. */
8380 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8382 /* Draw the empty space above the handle. Note that we can't clear
8383 zero-height areas; that means "clear to end of window." */
8384 if (0 < start)
8385 XClearArea (FRAME_X_DISPLAY (f), w,
8387 /* x, y, width, height, and exposures. */
8388 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8389 VERTICAL_SCROLL_BAR_TOP_BORDER,
8390 inside_width, start,
8391 False);
8393 /* Change to proper foreground color if one is specified. */
8394 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8395 XSetForeground (FRAME_X_DISPLAY (f), gc,
8396 f->output_data.x->scroll_bar_foreground_pixel);
8398 /* Draw the handle itself. */
8399 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8401 /* x, y, width, height */
8402 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8403 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8404 inside_width, end - start);
8406 /* Restore the foreground color of the GC if we changed it above. */
8407 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8408 XSetForeground (FRAME_X_DISPLAY (f), gc,
8409 f->output_data.x->foreground_pixel);
8411 /* Draw the empty space below the handle. Note that we can't
8412 clear zero-height areas; that means "clear to end of window." */
8413 if (end < inside_height)
8414 XClearArea (FRAME_X_DISPLAY (f), w,
8416 /* x, y, width, height, and exposures. */
8417 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8418 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8419 inside_width, inside_height - end,
8420 False);
8424 UNBLOCK_INPUT;
8427 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8429 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8430 nil. */
8432 static void
8433 x_scroll_bar_remove (bar)
8434 struct scroll_bar *bar;
8436 BLOCK_INPUT;
8438 #if USE_TOOLKIT_SCROLL_BARS
8439 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8440 #else /* not USE_TOOLKIT_SCROLL_BARS */
8442 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8443 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8445 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8447 /* Disassociate this scroll bar from its window. */
8448 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8450 UNBLOCK_INPUT;
8454 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8455 that we are displaying PORTION characters out of a total of WHOLE
8456 characters, starting at POSITION. If WINDOW has no scroll bar,
8457 create one. */
8459 static void
8460 XTset_vertical_scroll_bar (w, portion, whole, position)
8461 struct window *w;
8462 int portion, whole, position;
8464 struct frame *f = XFRAME (w->frame);
8465 struct scroll_bar *bar;
8466 int top, height, left, sb_left, width, sb_width;
8467 int window_x, window_y, window_width, window_height;
8469 /* Get window dimensions. */
8470 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8471 top = window_y;
8472 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8473 height = window_height;
8475 /* Compute the left edge of the scroll bar area. */
8476 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8477 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8478 else
8479 left = XFASTINT (w->left);
8480 left *= CANON_X_UNIT (f);
8481 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8483 /* Compute the width of the scroll bar which might be less than
8484 the width of the area reserved for the scroll bar. */
8485 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8486 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8487 else
8488 sb_width = width;
8490 /* Compute the left edge of the scroll bar. */
8491 #ifdef USE_TOOLKIT_SCROLL_BARS
8492 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8493 sb_left = left + width - sb_width - (width - sb_width) / 2;
8494 else
8495 sb_left = left + (width - sb_width) / 2;
8496 #else
8497 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8498 sb_left = left + width - sb_width;
8499 else
8500 sb_left = left;
8501 #endif
8503 /* Does the scroll bar exist yet? */
8504 if (NILP (w->vertical_scroll_bar))
8506 BLOCK_INPUT;
8507 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8508 left, top, width, height, False);
8509 UNBLOCK_INPUT;
8510 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8512 else
8514 /* It may just need to be moved and resized. */
8515 unsigned int mask = 0;
8517 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8519 BLOCK_INPUT;
8521 if (sb_left != XINT (bar->left))
8522 mask |= CWX;
8523 if (top != XINT (bar->top))
8524 mask |= CWY;
8525 if (sb_width != XINT (bar->width))
8526 mask |= CWWidth;
8527 if (height != XINT (bar->height))
8528 mask |= CWHeight;
8530 #ifdef USE_TOOLKIT_SCROLL_BARS
8532 /* Since toolkit scroll bars are smaller than the space reserved
8533 for them on the frame, we have to clear "under" them. */
8534 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8535 left, top, width, height, False);
8537 /* Move/size the scroll bar widget. */
8538 if (mask)
8539 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8540 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8541 top,
8542 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8543 height, 0);
8545 #else /* not USE_TOOLKIT_SCROLL_BARS */
8547 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8549 /* Clear areas not covered by the scroll bar. This makes sure a
8550 previous mode line display is cleared after C-x 2 C-x 1, for
8551 example. Non-toolkit scroll bars are as wide as the area
8552 reserved for scroll bars - trim at both sides. */
8553 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8554 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8555 height, False);
8556 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8557 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8558 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8559 height, False);
8562 /* Move/size the scroll bar window. */
8563 if (mask)
8565 XWindowChanges wc;
8567 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8568 wc.y = top;
8569 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8570 wc.height = height;
8571 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8572 mask, &wc);
8575 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8577 /* Remember new settings. */
8578 XSETINT (bar->left, sb_left);
8579 XSETINT (bar->top, top);
8580 XSETINT (bar->width, sb_width);
8581 XSETINT (bar->height, height);
8583 UNBLOCK_INPUT;
8586 #if USE_TOOLKIT_SCROLL_BARS
8587 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8588 #else /* not USE_TOOLKIT_SCROLL_BARS */
8589 /* Set the scroll bar's current state, unless we're currently being
8590 dragged. */
8591 if (NILP (bar->dragging))
8593 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8595 if (whole == 0)
8596 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8597 else
8599 int start = ((double) position * top_range) / whole;
8600 int end = ((double) (position + portion) * top_range) / whole;
8601 x_scroll_bar_set_handle (bar, start, end, 0);
8604 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8606 XSETVECTOR (w->vertical_scroll_bar, bar);
8610 /* The following three hooks are used when we're doing a thorough
8611 redisplay of the frame. We don't explicitly know which scroll bars
8612 are going to be deleted, because keeping track of when windows go
8613 away is a real pain - "Can you say set-window-configuration, boys
8614 and girls?" Instead, we just assert at the beginning of redisplay
8615 that *all* scroll bars are to be removed, and then save a scroll bar
8616 from the fiery pit when we actually redisplay its window. */
8618 /* Arrange for all scroll bars on FRAME to be removed at the next call
8619 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8620 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8622 static void
8623 XTcondemn_scroll_bars (frame)
8624 FRAME_PTR frame;
8626 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8627 while (! NILP (FRAME_SCROLL_BARS (frame)))
8629 Lisp_Object bar;
8630 bar = FRAME_SCROLL_BARS (frame);
8631 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8632 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8633 XSCROLL_BAR (bar)->prev = Qnil;
8634 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8635 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8636 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8640 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8641 Note that WINDOW isn't necessarily condemned at all. */
8642 static void
8643 XTredeem_scroll_bar (window)
8644 struct window *window;
8646 struct scroll_bar *bar;
8648 /* We can't redeem this window's scroll bar if it doesn't have one. */
8649 if (NILP (window->vertical_scroll_bar))
8650 abort ();
8652 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8654 /* Unlink it from the condemned list. */
8656 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8658 if (NILP (bar->prev))
8660 /* If the prev pointer is nil, it must be the first in one of
8661 the lists. */
8662 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8663 /* It's not condemned. Everything's fine. */
8664 return;
8665 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8666 window->vertical_scroll_bar))
8667 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8668 else
8669 /* If its prev pointer is nil, it must be at the front of
8670 one or the other! */
8671 abort ();
8673 else
8674 XSCROLL_BAR (bar->prev)->next = bar->next;
8676 if (! NILP (bar->next))
8677 XSCROLL_BAR (bar->next)->prev = bar->prev;
8679 bar->next = FRAME_SCROLL_BARS (f);
8680 bar->prev = Qnil;
8681 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8682 if (! NILP (bar->next))
8683 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8687 /* Remove all scroll bars on FRAME that haven't been saved since the
8688 last call to `*condemn_scroll_bars_hook'. */
8690 static void
8691 XTjudge_scroll_bars (f)
8692 FRAME_PTR f;
8694 Lisp_Object bar, next;
8696 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8698 /* Clear out the condemned list now so we won't try to process any
8699 more events on the hapless scroll bars. */
8700 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8702 for (; ! NILP (bar); bar = next)
8704 struct scroll_bar *b = XSCROLL_BAR (bar);
8706 x_scroll_bar_remove (b);
8708 next = b->next;
8709 b->next = b->prev = Qnil;
8712 /* Now there should be no references to the condemned scroll bars,
8713 and they should get garbage-collected. */
8717 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8718 is a no-op when using toolkit scroll bars.
8720 This may be called from a signal handler, so we have to ignore GC
8721 mark bits. */
8723 static void
8724 x_scroll_bar_expose (bar, event)
8725 struct scroll_bar *bar;
8726 XEvent *event;
8728 #ifndef USE_TOOLKIT_SCROLL_BARS
8730 Window w = SCROLL_BAR_X_WINDOW (bar);
8731 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8732 GC gc = f->output_data.x->normal_gc;
8733 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8735 BLOCK_INPUT;
8737 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8739 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8740 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8742 /* x, y, width, height */
8743 0, 0,
8744 XINT (bar->width) - 1 - width_trim - width_trim,
8745 XINT (bar->height) - 1);
8747 UNBLOCK_INPUT;
8749 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8752 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8753 is set to something other than no_event, it is enqueued.
8755 This may be called from a signal handler, so we have to ignore GC
8756 mark bits. */
8758 #ifndef USE_TOOLKIT_SCROLL_BARS
8760 static void
8761 x_scroll_bar_handle_click (bar, event, emacs_event)
8762 struct scroll_bar *bar;
8763 XEvent *event;
8764 struct input_event *emacs_event;
8766 if (! GC_WINDOWP (bar->window))
8767 abort ();
8769 emacs_event->kind = scroll_bar_click;
8770 emacs_event->code = event->xbutton.button - Button1;
8771 emacs_event->modifiers
8772 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8773 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8774 event->xbutton.state)
8775 | (event->type == ButtonRelease
8776 ? up_modifier
8777 : down_modifier));
8778 emacs_event->frame_or_window = bar->window;
8779 emacs_event->arg = Qnil;
8780 emacs_event->timestamp = event->xbutton.time;
8782 #if 0
8783 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8784 int internal_height
8785 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8786 #endif
8787 int top_range
8788 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8789 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8791 if (y < 0) y = 0;
8792 if (y > top_range) y = top_range;
8794 if (y < XINT (bar->start))
8795 emacs_event->part = scroll_bar_above_handle;
8796 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8797 emacs_event->part = scroll_bar_handle;
8798 else
8799 emacs_event->part = scroll_bar_below_handle;
8801 /* Just because the user has clicked on the handle doesn't mean
8802 they want to drag it. Lisp code needs to be able to decide
8803 whether or not we're dragging. */
8804 #if 0
8805 /* If the user has just clicked on the handle, record where they're
8806 holding it. */
8807 if (event->type == ButtonPress
8808 && emacs_event->part == scroll_bar_handle)
8809 XSETINT (bar->dragging, y - XINT (bar->start));
8810 #endif
8812 /* If the user has released the handle, set it to its final position. */
8813 if (event->type == ButtonRelease
8814 && ! NILP (bar->dragging))
8816 int new_start = y - XINT (bar->dragging);
8817 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8819 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8820 bar->dragging = Qnil;
8823 /* Same deal here as the other #if 0. */
8824 #if 0
8825 /* Clicks on the handle are always reported as occurring at the top of
8826 the handle. */
8827 if (emacs_event->part == scroll_bar_handle)
8828 emacs_event->x = bar->start;
8829 else
8830 XSETINT (emacs_event->x, y);
8831 #else
8832 XSETINT (emacs_event->x, y);
8833 #endif
8835 XSETINT (emacs_event->y, top_range);
8839 /* Handle some mouse motion while someone is dragging the scroll bar.
8841 This may be called from a signal handler, so we have to ignore GC
8842 mark bits. */
8844 static void
8845 x_scroll_bar_note_movement (bar, event)
8846 struct scroll_bar *bar;
8847 XEvent *event;
8849 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8851 last_mouse_movement_time = event->xmotion.time;
8853 f->mouse_moved = 1;
8854 XSETVECTOR (last_mouse_scroll_bar, bar);
8856 /* If we're dragging the bar, display it. */
8857 if (! GC_NILP (bar->dragging))
8859 /* Where should the handle be now? */
8860 int new_start = event->xmotion.y - XINT (bar->dragging);
8862 if (new_start != XINT (bar->start))
8864 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8866 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8871 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8873 /* Return information to the user about the current position of the mouse
8874 on the scroll bar. */
8876 static void
8877 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8878 FRAME_PTR *fp;
8879 Lisp_Object *bar_window;
8880 enum scroll_bar_part *part;
8881 Lisp_Object *x, *y;
8882 unsigned long *time;
8884 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8885 Window w = SCROLL_BAR_X_WINDOW (bar);
8886 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8887 int win_x, win_y;
8888 Window dummy_window;
8889 int dummy_coord;
8890 unsigned int dummy_mask;
8892 BLOCK_INPUT;
8894 /* Get the mouse's position relative to the scroll bar window, and
8895 report that. */
8896 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8898 /* Root, child, root x and root y. */
8899 &dummy_window, &dummy_window,
8900 &dummy_coord, &dummy_coord,
8902 /* Position relative to scroll bar. */
8903 &win_x, &win_y,
8905 /* Mouse buttons and modifier keys. */
8906 &dummy_mask))
8908 else
8910 #if 0
8911 int inside_height
8912 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8913 #endif
8914 int top_range
8915 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8917 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8919 if (! NILP (bar->dragging))
8920 win_y -= XINT (bar->dragging);
8922 if (win_y < 0)
8923 win_y = 0;
8924 if (win_y > top_range)
8925 win_y = top_range;
8927 *fp = f;
8928 *bar_window = bar->window;
8930 if (! NILP (bar->dragging))
8931 *part = scroll_bar_handle;
8932 else if (win_y < XINT (bar->start))
8933 *part = scroll_bar_above_handle;
8934 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8935 *part = scroll_bar_handle;
8936 else
8937 *part = scroll_bar_below_handle;
8939 XSETINT (*x, win_y);
8940 XSETINT (*y, top_range);
8942 f->mouse_moved = 0;
8943 last_mouse_scroll_bar = Qnil;
8946 *time = last_mouse_movement_time;
8948 UNBLOCK_INPUT;
8952 /* The screen has been cleared so we may have changed foreground or
8953 background colors, and the scroll bars may need to be redrawn.
8954 Clear out the scroll bars, and ask for expose events, so we can
8955 redraw them. */
8957 void
8958 x_scroll_bar_clear (f)
8959 FRAME_PTR f;
8961 #ifndef USE_TOOLKIT_SCROLL_BARS
8962 Lisp_Object bar;
8964 /* We can have scroll bars even if this is 0,
8965 if we just turned off scroll bar mode.
8966 But in that case we should not clear them. */
8967 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8968 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8969 bar = XSCROLL_BAR (bar)->next)
8970 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8971 0, 0, 0, 0, True);
8972 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8975 /* This processes Expose events from the menu-bar specific X event
8976 loop in xmenu.c. This allows to redisplay the frame if necessary
8977 when handling menu-bar or pop-up items. */
8980 process_expose_from_menu (event)
8981 XEvent event;
8983 FRAME_PTR f;
8984 struct x_display_info *dpyinfo;
8985 int frame_exposed_p = 0;
8987 BLOCK_INPUT;
8989 dpyinfo = x_display_info_for_display (event.xexpose.display);
8990 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8991 if (f)
8993 if (f->async_visible == 0)
8995 f->async_visible = 1;
8996 f->async_iconified = 0;
8997 f->output_data.x->has_been_visible = 1;
8998 SET_FRAME_GARBAGED (f);
9000 else
9002 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9003 event.xexpose.x, event.xexpose.y,
9004 event.xexpose.width, event.xexpose.height);
9005 frame_exposed_p = 1;
9008 else
9010 struct scroll_bar *bar
9011 = x_window_to_scroll_bar (event.xexpose.window);
9013 if (bar)
9014 x_scroll_bar_expose (bar, &event);
9017 UNBLOCK_INPUT;
9018 return frame_exposed_p;
9021 /* Define a queue to save up SelectionRequest events for later handling. */
9023 struct selection_event_queue
9025 XEvent event;
9026 struct selection_event_queue *next;
9029 static struct selection_event_queue *queue;
9031 /* Nonzero means queue up certain events--don't process them yet. */
9033 static int x_queue_selection_requests;
9035 /* Queue up an X event *EVENT, to be processed later. */
9037 static void
9038 x_queue_event (f, event)
9039 FRAME_PTR f;
9040 XEvent *event;
9042 struct selection_event_queue *queue_tmp
9043 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9045 if (queue_tmp != NULL)
9047 queue_tmp->event = *event;
9048 queue_tmp->next = queue;
9049 queue = queue_tmp;
9053 /* Take all the queued events and put them back
9054 so that they get processed afresh. */
9056 static void
9057 x_unqueue_events (display)
9058 Display *display;
9060 while (queue != NULL)
9062 struct selection_event_queue *queue_tmp = queue;
9063 XPutBackEvent (display, &queue_tmp->event);
9064 queue = queue_tmp->next;
9065 xfree ((char *)queue_tmp);
9069 /* Start queuing SelectionRequest events. */
9071 void
9072 x_start_queuing_selection_requests (display)
9073 Display *display;
9075 x_queue_selection_requests++;
9078 /* Stop queuing SelectionRequest events. */
9080 void
9081 x_stop_queuing_selection_requests (display)
9082 Display *display;
9084 x_queue_selection_requests--;
9085 x_unqueue_events (display);
9088 /* The main X event-reading loop - XTread_socket. */
9090 /* Time stamp of enter window event. This is only used by XTread_socket,
9091 but we have to put it out here, since static variables within functions
9092 sometimes don't work. */
9094 static Time enter_timestamp;
9096 /* This holds the state XLookupString needs to implement dead keys
9097 and other tricks known as "compose processing". _X Window System_
9098 says that a portable program can't use this, but Stephen Gildea assures
9099 me that letting the compiler initialize it to zeros will work okay.
9101 This must be defined outside of XTread_socket, for the same reasons
9102 given for enter_time stamp, above. */
9104 static XComposeStatus compose_status;
9106 /* Record the last 100 characters stored
9107 to help debug the loss-of-chars-during-GC problem. */
9109 static int temp_index;
9110 static short temp_buffer[100];
9112 /* Set this to nonzero to fake an "X I/O error"
9113 on a particular display. */
9115 struct x_display_info *XTread_socket_fake_io_error;
9117 /* When we find no input here, we occasionally do a no-op command
9118 to verify that the X server is still running and we can still talk with it.
9119 We try all the open displays, one by one.
9120 This variable is used for cycling thru the displays. */
9122 static struct x_display_info *next_noop_dpyinfo;
9124 #define SET_SAVED_MENU_EVENT(size) \
9125 do \
9127 if (f->output_data.x->saved_menu_event == 0) \
9128 f->output_data.x->saved_menu_event \
9129 = (XEvent *) xmalloc (sizeof (XEvent)); \
9130 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9131 if (numchars >= 1) \
9133 bufp->kind = menu_bar_activate_event; \
9134 XSETFRAME (bufp->frame_or_window, f); \
9135 bufp->arg = Qnil; \
9136 bufp++; \
9137 count++; \
9138 numchars--; \
9141 while (0)
9143 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9144 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9146 /* Read events coming from the X server.
9147 This routine is called by the SIGIO handler.
9148 We return as soon as there are no more events to be read.
9150 Events representing keys are stored in buffer BUFP,
9151 which can hold up to NUMCHARS characters.
9152 We return the number of characters stored into the buffer,
9153 thus pretending to be `read'.
9155 EXPECTED is nonzero if the caller knows input is available. */
9158 XTread_socket (sd, bufp, numchars, expected)
9159 register int sd;
9160 /* register */ struct input_event *bufp;
9161 /* register */ int numchars;
9162 int expected;
9164 int count = 0;
9165 int nbytes = 0;
9166 XEvent event;
9167 struct frame *f;
9168 int event_found = 0;
9169 struct x_display_info *dpyinfo;
9170 struct coding_system coding;
9172 if (interrupt_input_blocked)
9174 interrupt_input_pending = 1;
9175 return -1;
9178 interrupt_input_pending = 0;
9179 BLOCK_INPUT;
9181 /* So people can tell when we have read the available input. */
9182 input_signal_count++;
9184 if (numchars <= 0)
9185 abort (); /* Don't think this happens. */
9187 ++handling_signal;
9189 /* The input should be decoded if it is from XIM. Currently the
9190 locale of XIM is the same as that of the system. So, we can use
9191 Vlocale_coding_system which is initialized properly at Emacs
9192 startup time. */
9193 setup_coding_system (Vlocale_coding_system, &coding);
9194 coding.src_multibyte = 0;
9195 coding.dst_multibyte = 1;
9196 /* The input is converted to events, thus we can't handle
9197 composition. Anyway, there's no XIM that gives us composition
9198 information. */
9199 coding.composing = COMPOSITION_DISABLED;
9201 /* Find the display we are supposed to read input for.
9202 It's the one communicating on descriptor SD. */
9203 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9205 #if 0 /* This ought to be unnecessary; let's verify it. */
9206 #ifdef FIOSNBIO
9207 /* If available, Xlib uses FIOSNBIO to make the socket
9208 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9209 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9210 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9211 fcntl (dpyinfo->connection, F_SETFL, 0);
9212 #endif /* ! defined (FIOSNBIO) */
9213 #endif
9215 #if 0 /* This code can't be made to work, with multiple displays,
9216 and appears not to be used on any system any more.
9217 Also keyboard.c doesn't turn O_NDELAY on and off
9218 for X connections. */
9219 #ifndef SIGIO
9220 #ifndef HAVE_SELECT
9221 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9223 extern int read_alarm_should_throw;
9224 read_alarm_should_throw = 1;
9225 XPeekEvent (dpyinfo->display, &event);
9226 read_alarm_should_throw = 0;
9228 #endif /* HAVE_SELECT */
9229 #endif /* SIGIO */
9230 #endif
9232 /* For debugging, this gives a way to fake an I/O error. */
9233 if (dpyinfo == XTread_socket_fake_io_error)
9235 XTread_socket_fake_io_error = 0;
9236 x_io_error_quitter (dpyinfo->display);
9239 while (XPending (dpyinfo->display))
9241 XNextEvent (dpyinfo->display, &event);
9243 #ifdef HAVE_X_I18N
9245 /* Filter events for the current X input method.
9246 XFilterEvent returns non-zero if the input method has
9247 consumed the event. We pass the frame's X window to
9248 XFilterEvent because that's the one for which the IC
9249 was created. */
9250 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9251 event.xclient.window);
9252 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9253 break;
9255 #endif
9256 event_found = 1;
9258 switch (event.type)
9260 case ClientMessage:
9262 if (event.xclient.message_type
9263 == dpyinfo->Xatom_wm_protocols
9264 && event.xclient.format == 32)
9266 if (event.xclient.data.l[0]
9267 == dpyinfo->Xatom_wm_take_focus)
9269 /* Use x_any_window_to_frame because this
9270 could be the shell widget window
9271 if the frame has no title bar. */
9272 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9273 #ifdef HAVE_X_I18N
9274 /* Not quite sure this is needed -pd */
9275 if (f && FRAME_XIC (f))
9276 XSetICFocus (FRAME_XIC (f));
9277 #endif
9278 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9279 instructs the WM to set the input focus automatically for
9280 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9281 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9282 it has set the focus. So, XSetInputFocus below is not
9283 needed.
9285 The call to XSetInputFocus below has also caused trouble. In
9286 cases where the XSetInputFocus done by the WM and the one
9287 below are temporally close (on a fast machine), the call
9288 below can generate additional FocusIn events which confuse
9289 Emacs. */
9291 /* Since we set WM_TAKE_FOCUS, we must call
9292 XSetInputFocus explicitly. But not if f is null,
9293 since that might be an event for a deleted frame. */
9294 if (f)
9296 Display *d = event.xclient.display;
9297 /* Catch and ignore errors, in case window has been
9298 iconified by a window manager such as GWM. */
9299 int count = x_catch_errors (d);
9300 XSetInputFocus (d, event.xclient.window,
9301 /* The ICCCM says this is
9302 the only valid choice. */
9303 RevertToParent,
9304 event.xclient.data.l[1]);
9305 /* This is needed to detect the error
9306 if there is an error. */
9307 XSync (d, False);
9308 x_uncatch_errors (d, count);
9310 /* Not certain about handling scroll bars here */
9311 #endif /* 0 */
9313 else if (event.xclient.data.l[0]
9314 == dpyinfo->Xatom_wm_save_yourself)
9316 /* Save state modify the WM_COMMAND property to
9317 something which can reinstate us. This notifies
9318 the session manager, who's looking for such a
9319 PropertyNotify. Can restart processing when
9320 a keyboard or mouse event arrives. */
9321 if (numchars > 0)
9323 f = x_top_window_to_frame (dpyinfo,
9324 event.xclient.window);
9326 /* This is just so we only give real data once
9327 for a single Emacs process. */
9328 if (f == SELECTED_FRAME ())
9329 XSetCommand (FRAME_X_DISPLAY (f),
9330 event.xclient.window,
9331 initial_argv, initial_argc);
9332 else if (f)
9333 XSetCommand (FRAME_X_DISPLAY (f),
9334 event.xclient.window,
9335 0, 0);
9338 else if (event.xclient.data.l[0]
9339 == dpyinfo->Xatom_wm_delete_window)
9341 struct frame *f
9342 = x_any_window_to_frame (dpyinfo,
9343 event.xclient.window);
9345 if (f)
9347 if (numchars == 0)
9348 abort ();
9350 bufp->kind = delete_window_event;
9351 XSETFRAME (bufp->frame_or_window, f);
9352 bufp->arg = Qnil;
9353 bufp++;
9355 count += 1;
9356 numchars -= 1;
9360 else if (event.xclient.message_type
9361 == dpyinfo->Xatom_wm_configure_denied)
9364 else if (event.xclient.message_type
9365 == dpyinfo->Xatom_wm_window_moved)
9367 int new_x, new_y;
9368 struct frame *f
9369 = x_window_to_frame (dpyinfo, event.xclient.window);
9371 new_x = event.xclient.data.s[0];
9372 new_y = event.xclient.data.s[1];
9374 if (f)
9376 f->output_data.x->left_pos = new_x;
9377 f->output_data.x->top_pos = new_y;
9380 #ifdef HACK_EDITRES
9381 else if (event.xclient.message_type
9382 == dpyinfo->Xatom_editres)
9384 struct frame *f
9385 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9386 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9387 &event, NULL);
9389 #endif /* HACK_EDITRES */
9390 else if ((event.xclient.message_type
9391 == dpyinfo->Xatom_DONE)
9392 || (event.xclient.message_type
9393 == dpyinfo->Xatom_PAGE))
9395 /* Ghostview job completed. Kill it. We could
9396 reply with "Next" if we received "Page", but we
9397 currently never do because we are interested in
9398 images, only, which should have 1 page. */
9399 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9400 struct frame *f
9401 = x_window_to_frame (dpyinfo, event.xclient.window);
9402 x_kill_gs_process (pixmap, f);
9403 expose_frame (f, 0, 0, 0, 0);
9405 #ifdef USE_TOOLKIT_SCROLL_BARS
9406 /* Scroll bar callbacks send a ClientMessage from which
9407 we construct an input_event. */
9408 else if (event.xclient.message_type
9409 == dpyinfo->Xatom_Scrollbar)
9411 x_scroll_bar_to_input_event (&event, bufp);
9412 ++bufp, ++count, --numchars;
9413 goto out;
9415 #endif /* USE_TOOLKIT_SCROLL_BARS */
9416 else
9417 goto OTHER;
9419 break;
9421 case SelectionNotify:
9422 #ifdef USE_X_TOOLKIT
9423 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9424 goto OTHER;
9425 #endif /* not USE_X_TOOLKIT */
9426 x_handle_selection_notify (&event.xselection);
9427 break;
9429 case SelectionClear: /* Someone has grabbed ownership. */
9430 #ifdef USE_X_TOOLKIT
9431 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9432 goto OTHER;
9433 #endif /* USE_X_TOOLKIT */
9435 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9437 if (numchars == 0)
9438 abort ();
9440 bufp->kind = selection_clear_event;
9441 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9442 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9443 SELECTION_EVENT_TIME (bufp) = eventp->time;
9444 bufp->frame_or_window = Qnil;
9445 bufp->arg = Qnil;
9446 bufp++;
9448 count += 1;
9449 numchars -= 1;
9451 break;
9453 case SelectionRequest: /* Someone wants our selection. */
9454 #ifdef USE_X_TOOLKIT
9455 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9456 goto OTHER;
9457 #endif /* USE_X_TOOLKIT */
9458 if (x_queue_selection_requests)
9459 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9460 &event);
9461 else
9463 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9465 if (numchars == 0)
9466 abort ();
9468 bufp->kind = selection_request_event;
9469 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9470 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9471 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9472 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9473 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9474 SELECTION_EVENT_TIME (bufp) = eventp->time;
9475 bufp->frame_or_window = Qnil;
9476 bufp->arg = Qnil;
9477 bufp++;
9479 count += 1;
9480 numchars -= 1;
9482 break;
9484 case PropertyNotify:
9485 #ifdef USE_X_TOOLKIT
9486 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9487 goto OTHER;
9488 #endif /* not USE_X_TOOLKIT */
9489 x_handle_property_notify (&event.xproperty);
9490 break;
9492 case ReparentNotify:
9493 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9494 if (f)
9496 int x, y;
9497 f->output_data.x->parent_desc = event.xreparent.parent;
9498 x_real_positions (f, &x, &y);
9499 f->output_data.x->left_pos = x;
9500 f->output_data.x->top_pos = y;
9502 break;
9504 case Expose:
9505 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9506 if (f)
9508 if (f->async_visible == 0)
9510 f->async_visible = 1;
9511 f->async_iconified = 0;
9512 f->output_data.x->has_been_visible = 1;
9513 SET_FRAME_GARBAGED (f);
9515 else
9516 expose_frame (x_window_to_frame (dpyinfo,
9517 event.xexpose.window),
9518 event.xexpose.x, event.xexpose.y,
9519 event.xexpose.width, event.xexpose.height);
9521 else
9523 #ifdef USE_TOOLKIT_SCROLL_BARS
9524 /* Dispatch event to the widget. */
9525 goto OTHER;
9526 #else /* not USE_TOOLKIT_SCROLL_BARS */
9527 struct scroll_bar *bar
9528 = x_window_to_scroll_bar (event.xexpose.window);
9530 if (bar)
9531 x_scroll_bar_expose (bar, &event);
9532 #ifdef USE_X_TOOLKIT
9533 else
9534 goto OTHER;
9535 #endif /* USE_X_TOOLKIT */
9536 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9538 break;
9540 case GraphicsExpose: /* This occurs when an XCopyArea's
9541 source area was obscured or not
9542 available.*/
9543 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9544 if (f)
9546 expose_frame (f,
9547 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9548 event.xgraphicsexpose.width,
9549 event.xgraphicsexpose.height);
9551 #ifdef USE_X_TOOLKIT
9552 else
9553 goto OTHER;
9554 #endif /* USE_X_TOOLKIT */
9555 break;
9557 case NoExpose: /* This occurs when an XCopyArea's
9558 source area was completely
9559 available */
9560 break;
9562 case UnmapNotify:
9563 /* Redo the mouse-highlight after the tooltip has gone. */
9564 if (event.xmap.window == tip_window)
9566 tip_window = 0;
9567 redo_mouse_highlight ();
9570 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9571 if (f) /* F may no longer exist if
9572 the frame was deleted. */
9574 /* While a frame is unmapped, display generation is
9575 disabled; you don't want to spend time updating a
9576 display that won't ever be seen. */
9577 f->async_visible = 0;
9578 /* We can't distinguish, from the event, whether the window
9579 has become iconified or invisible. So assume, if it
9580 was previously visible, than now it is iconified.
9581 But x_make_frame_invisible clears both
9582 the visible flag and the iconified flag;
9583 and that way, we know the window is not iconified now. */
9584 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9586 f->async_iconified = 1;
9588 bufp->kind = iconify_event;
9589 XSETFRAME (bufp->frame_or_window, f);
9590 bufp->arg = Qnil;
9591 bufp++;
9592 count++;
9593 numchars--;
9596 goto OTHER;
9598 case MapNotify:
9599 if (event.xmap.window == tip_window)
9600 /* The tooltip has been drawn already. Avoid
9601 the SET_FRAME_GARBAGED below. */
9602 goto OTHER;
9604 /* We use x_top_window_to_frame because map events can
9605 come for sub-windows and they don't mean that the
9606 frame is visible. */
9607 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9608 if (f)
9610 f->async_visible = 1;
9611 f->async_iconified = 0;
9612 f->output_data.x->has_been_visible = 1;
9614 /* wait_reading_process_input will notice this and update
9615 the frame's display structures. */
9616 SET_FRAME_GARBAGED (f);
9618 if (f->iconified)
9620 bufp->kind = deiconify_event;
9621 XSETFRAME (bufp->frame_or_window, f);
9622 bufp->arg = Qnil;
9623 bufp++;
9624 count++;
9625 numchars--;
9627 else if (! NILP (Vframe_list)
9628 && ! NILP (XCDR (Vframe_list)))
9629 /* Force a redisplay sooner or later
9630 to update the frame titles
9631 in case this is the second frame. */
9632 record_asynch_buffer_change ();
9634 goto OTHER;
9636 case KeyPress:
9637 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9639 #ifdef USE_MOTIF
9640 /* I couldn't find a way to prevent LessTif scroll bars
9641 from consuming key events. */
9642 if (f == 0)
9644 Widget widget = XtWindowToWidget (dpyinfo->display,
9645 event.xkey.window);
9646 if (widget && XmIsScrollBar (widget))
9648 widget = XtParent (widget);
9649 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9652 #endif /* USE_MOTIF */
9654 if (f != 0)
9656 KeySym keysym, orig_keysym;
9657 /* al%imercury@uunet.uu.net says that making this 81
9658 instead of 80 fixed a bug whereby meta chars made
9659 his Emacs hang.
9661 It seems that some version of XmbLookupString has
9662 a bug of not returning XBufferOverflow in
9663 status_return even if the input is too long to
9664 fit in 81 bytes. So, we must prepare sufficient
9665 bytes for copy_buffer. 513 bytes (256 chars for
9666 two-byte character set) seems to be a faily good
9667 approximation. -- 2000.8.10 handa@etl.go.jp */
9668 unsigned char copy_buffer[513];
9669 unsigned char *copy_bufptr = copy_buffer;
9670 int copy_bufsiz = sizeof (copy_buffer);
9671 int modifiers;
9673 event.xkey.state
9674 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9675 extra_keyboard_modifiers);
9676 modifiers = event.xkey.state;
9678 /* This will have to go some day... */
9680 /* make_lispy_event turns chars into control chars.
9681 Don't do it here because XLookupString is too eager. */
9682 event.xkey.state &= ~ControlMask;
9683 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9684 | dpyinfo->super_mod_mask
9685 | dpyinfo->hyper_mod_mask
9686 | dpyinfo->alt_mod_mask);
9688 /* In case Meta is ComposeCharacter,
9689 clear its status. According to Markus Ehrnsperger
9690 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9691 this enables ComposeCharacter to work whether or
9692 not it is combined with Meta. */
9693 if (modifiers & dpyinfo->meta_mod_mask)
9694 bzero (&compose_status, sizeof (compose_status));
9696 #ifdef HAVE_X_I18N
9697 if (FRAME_XIC (f))
9699 Status status_return;
9701 nbytes = XmbLookupString (FRAME_XIC (f),
9702 &event.xkey, copy_bufptr,
9703 copy_bufsiz, &keysym,
9704 &status_return);
9705 if (status_return == XBufferOverflow)
9707 copy_bufsiz = nbytes + 1;
9708 copy_bufptr = (char *) alloca (copy_bufsiz);
9709 nbytes = XmbLookupString (FRAME_XIC (f),
9710 &event.xkey, copy_bufptr,
9711 copy_bufsiz, &keysym,
9712 &status_return);
9715 if (status_return == XLookupNone)
9716 break;
9717 else if (status_return == XLookupChars)
9719 keysym = NoSymbol;
9720 modifiers = 0;
9722 else if (status_return != XLookupKeySym
9723 && status_return != XLookupBoth)
9724 abort ();
9726 else
9727 nbytes = XLookupString (&event.xkey, copy_bufptr,
9728 copy_bufsiz, &keysym,
9729 &compose_status);
9730 #else
9731 nbytes = XLookupString (&event.xkey, copy_bufptr,
9732 copy_bufsiz, &keysym,
9733 &compose_status);
9734 #endif
9736 orig_keysym = keysym;
9738 if (numchars > 1)
9740 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9741 || keysym == XK_Delete
9742 #ifdef XK_ISO_Left_Tab
9743 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9744 #endif
9745 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9746 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9747 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9748 #ifdef HPUX
9749 /* This recognizes the "extended function keys".
9750 It seems there's no cleaner way.
9751 Test IsModifierKey to avoid handling mode_switch
9752 incorrectly. */
9753 || ((unsigned) (keysym) >= XK_Select
9754 && (unsigned)(keysym) < XK_KP_Space)
9755 #endif
9756 #ifdef XK_dead_circumflex
9757 || orig_keysym == XK_dead_circumflex
9758 #endif
9759 #ifdef XK_dead_grave
9760 || orig_keysym == XK_dead_grave
9761 #endif
9762 #ifdef XK_dead_tilde
9763 || orig_keysym == XK_dead_tilde
9764 #endif
9765 #ifdef XK_dead_diaeresis
9766 || orig_keysym == XK_dead_diaeresis
9767 #endif
9768 #ifdef XK_dead_macron
9769 || orig_keysym == XK_dead_macron
9770 #endif
9771 #ifdef XK_dead_degree
9772 || orig_keysym == XK_dead_degree
9773 #endif
9774 #ifdef XK_dead_acute
9775 || orig_keysym == XK_dead_acute
9776 #endif
9777 #ifdef XK_dead_cedilla
9778 || orig_keysym == XK_dead_cedilla
9779 #endif
9780 #ifdef XK_dead_breve
9781 || orig_keysym == XK_dead_breve
9782 #endif
9783 #ifdef XK_dead_ogonek
9784 || orig_keysym == XK_dead_ogonek
9785 #endif
9786 #ifdef XK_dead_caron
9787 || orig_keysym == XK_dead_caron
9788 #endif
9789 #ifdef XK_dead_doubleacute
9790 || orig_keysym == XK_dead_doubleacute
9791 #endif
9792 #ifdef XK_dead_abovedot
9793 || orig_keysym == XK_dead_abovedot
9794 #endif
9795 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9796 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9797 /* Any "vendor-specific" key is ok. */
9798 || (orig_keysym & (1 << 28)))
9799 && ! (IsModifierKey (orig_keysym)
9800 #ifndef HAVE_X11R5
9801 #ifdef XK_Mode_switch
9802 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9803 #endif
9804 #ifdef XK_Num_Lock
9805 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9806 #endif
9807 #endif /* not HAVE_X11R5 */
9810 if (temp_index == sizeof temp_buffer / sizeof (short))
9811 temp_index = 0;
9812 temp_buffer[temp_index++] = keysym;
9813 bufp->kind = non_ascii_keystroke;
9814 bufp->code = keysym;
9815 XSETFRAME (bufp->frame_or_window, f);
9816 bufp->arg = Qnil;
9817 bufp->modifiers
9818 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9819 modifiers);
9820 bufp->timestamp = event.xkey.time;
9821 bufp++;
9822 count++;
9823 numchars--;
9825 else if (numchars > nbytes)
9827 register int i;
9828 register int c;
9829 unsigned char *p, *pend;
9830 int nchars, len;
9832 for (i = 0; i < nbytes; i++)
9834 if (temp_index == (sizeof temp_buffer
9835 / sizeof (short)))
9836 temp_index = 0;
9837 temp_buffer[temp_index++] = copy_bufptr[i];
9840 if (/* If the event is not from XIM, */
9841 event.xkey.keycode != 0
9842 /* or the current locale doesn't request
9843 decoding of the intup data, ... */
9844 || coding.type == coding_type_raw_text
9845 || coding.type == coding_type_no_conversion)
9847 /* ... we can use the input data as is. */
9848 nchars = nbytes;
9850 else
9852 /* We have to decode the input data. */
9853 int require;
9854 unsigned char *p;
9856 require = decoding_buffer_size (&coding, nbytes);
9857 p = (unsigned char *) alloca (require);
9858 coding.mode |= CODING_MODE_LAST_BLOCK;
9859 decode_coding (&coding, copy_bufptr, p,
9860 nbytes, require);
9861 nbytes = coding.produced;
9862 nchars = coding.produced_char;
9863 copy_bufptr = p;
9866 /* Convert the input data to a sequence of
9867 character events. */
9868 for (i = 0; i < nbytes; i += len)
9870 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9871 nbytes - i, len);
9872 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9873 ? ascii_keystroke
9874 : multibyte_char_keystroke);
9875 bufp->code = c;
9876 XSETFRAME (bufp->frame_or_window, f);
9877 bufp->arg = Qnil;
9878 bufp->modifiers
9879 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9880 modifiers);
9881 bufp->timestamp = event.xkey.time;
9882 bufp++;
9885 count += nchars;
9886 numchars -= nchars;
9888 if (keysym == NoSymbol)
9889 break;
9891 else
9892 abort ();
9894 else
9895 abort ();
9897 #ifdef HAVE_X_I18N
9898 /* Don't dispatch this event since XtDispatchEvent calls
9899 XFilterEvent, and two calls in a row may freeze the
9900 client. */
9901 break;
9902 #else
9903 goto OTHER;
9904 #endif
9906 case KeyRelease:
9907 #ifdef HAVE_X_I18N
9908 /* Don't dispatch this event since XtDispatchEvent calls
9909 XFilterEvent, and two calls in a row may freeze the
9910 client. */
9911 break;
9912 #else
9913 goto OTHER;
9914 #endif
9916 /* Here's a possible interpretation of the whole
9917 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9918 you get a FocusIn event, you have to get a FocusOut
9919 event before you relinquish the focus. If you
9920 haven't received a FocusIn event, then a mere
9921 LeaveNotify is enough to free you. */
9923 case EnterNotify:
9925 int from_menu_bar_p = 0;
9927 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9929 #ifdef LESSTIF_VERSION
9930 /* When clicking outside of a menu bar popup to close
9931 it, we get a FocusIn/ EnterNotify sequence of
9932 events. The flag event.xcrossing.focus is not set
9933 in the EnterNotify event of that sequence because
9934 the focus is in the menu bar,
9935 event.xcrossing.window is the frame's X window.
9936 Unconditionally setting the focus frame to null in
9937 this case is not the right thing, because no event
9938 follows that could set the focus frame to the right
9939 value.
9941 This could be a LessTif bug, but I wasn't able to
9942 reproduce the behavior in a simple test program.
9944 (gerd, LessTif 0.88.1). */
9946 if (!event.xcrossing.focus
9947 && f
9948 && f->output_data.x->menubar_widget)
9950 Window focus;
9951 int revert;
9953 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9954 if (focus == XtWindow (f->output_data.x->menubar_widget))
9955 from_menu_bar_p = 1;
9957 #endif /* LESSTIF_VERSION */
9959 if (event.xcrossing.focus || from_menu_bar_p)
9961 /* Avoid nasty pop/raise loops. */
9962 if (f && (!(f->auto_raise)
9963 || !(f->auto_lower)
9964 || (event.xcrossing.time - enter_timestamp) > 500))
9966 x_new_focus_frame (dpyinfo, f);
9967 enter_timestamp = event.xcrossing.time;
9970 else if (f == dpyinfo->x_focus_frame)
9971 x_new_focus_frame (dpyinfo, 0);
9973 /* EnterNotify counts as mouse movement,
9974 so update things that depend on mouse position. */
9975 if (f && !f->output_data.x->busy_p)
9976 note_mouse_movement (f, &event.xmotion);
9977 goto OTHER;
9980 case FocusIn:
9981 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9982 if (event.xfocus.detail != NotifyPointer)
9983 dpyinfo->x_focus_event_frame = f;
9984 if (f)
9986 x_new_focus_frame (dpyinfo, f);
9988 /* Don't stop displaying the initial startup message
9989 for a switch-frame event we don't need. */
9990 if (GC_NILP (Vterminal_frame)
9991 && GC_CONSP (Vframe_list)
9992 && !GC_NILP (XCDR (Vframe_list)))
9994 bufp->kind = FOCUS_IN_EVENT;
9995 XSETFRAME (bufp->frame_or_window, f);
9996 bufp->arg = Qnil;
9997 ++bufp, ++count, --numchars;
10001 #ifdef HAVE_X_I18N
10002 if (f && FRAME_XIC (f))
10003 XSetICFocus (FRAME_XIC (f));
10004 #endif
10006 goto OTHER;
10008 case LeaveNotify:
10009 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10010 if (f)
10012 Lisp_Object frame;
10013 int from_menu_bar_p = 0;
10015 if (f == dpyinfo->mouse_face_mouse_frame)
10017 /* If we move outside the frame, then we're
10018 certainly no longer on any text in the frame. */
10019 clear_mouse_face (dpyinfo);
10020 dpyinfo->mouse_face_mouse_frame = 0;
10023 /* Generate a nil HELP_EVENT to cancel a help-echo.
10024 Do it only if there's something to cancel.
10025 Otherwise, the startup message is cleared when
10026 the mouse leaves the frame. */
10027 if (any_help_event_p)
10029 Lisp_Object frame;
10030 int n;
10032 XSETFRAME (frame, f);
10033 n = gen_help_event (bufp, numchars,
10034 Qnil, frame, Qnil, Qnil, 0);
10035 bufp += n, count += n, numchars -= n;
10038 #ifdef LESSTIF_VERSION
10039 /* Please see the comment at the start of the
10040 EnterNotify case. */
10041 if (!event.xcrossing.focus
10042 && f->output_data.x->menubar_widget)
10044 Window focus;
10045 int revert;
10046 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10047 if (focus == XtWindow (f->output_data.x->menubar_widget))
10048 from_menu_bar_p = 1;
10050 #endif /* LESSTIF_VERSION */
10052 if (event.xcrossing.focus || from_menu_bar_p)
10053 x_mouse_leave (dpyinfo);
10054 else
10056 if (f == dpyinfo->x_focus_event_frame)
10057 dpyinfo->x_focus_event_frame = 0;
10058 if (f == dpyinfo->x_focus_frame)
10059 x_new_focus_frame (dpyinfo, 0);
10062 goto OTHER;
10064 case FocusOut:
10065 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10066 if (event.xfocus.detail != NotifyPointer
10067 && f == dpyinfo->x_focus_event_frame)
10068 dpyinfo->x_focus_event_frame = 0;
10069 if (f && f == dpyinfo->x_focus_frame)
10070 x_new_focus_frame (dpyinfo, 0);
10072 #ifdef HAVE_X_I18N
10073 if (f && FRAME_XIC (f))
10074 XUnsetICFocus (FRAME_XIC (f));
10075 #endif
10077 goto OTHER;
10079 case MotionNotify:
10081 previous_help_echo = help_echo;
10082 help_echo = help_echo_object = help_echo_window = Qnil;
10083 help_echo_pos = -1;
10085 if (dpyinfo->grabbed && last_mouse_frame
10086 && FRAME_LIVE_P (last_mouse_frame))
10087 f = last_mouse_frame;
10088 else
10089 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10091 if (f)
10092 note_mouse_movement (f, &event.xmotion);
10093 else
10095 #ifndef USE_TOOLKIT_SCROLL_BARS
10096 struct scroll_bar *bar
10097 = x_window_to_scroll_bar (event.xmotion.window);
10099 if (bar)
10100 x_scroll_bar_note_movement (bar, &event);
10101 #endif /* USE_TOOLKIT_SCROLL_BARS */
10103 /* If we move outside the frame, then we're
10104 certainly no longer on any text in the frame. */
10105 clear_mouse_face (dpyinfo);
10108 /* If the contents of the global variable help_echo
10109 has changed, generate a HELP_EVENT. */
10110 if (!NILP (help_echo)
10111 || !NILP (previous_help_echo))
10113 Lisp_Object frame;
10114 int n;
10116 if (f)
10117 XSETFRAME (frame, f);
10118 else
10119 frame = Qnil;
10121 any_help_event_p = 1;
10122 n = gen_help_event (bufp, numchars, help_echo, frame,
10123 help_echo_window, help_echo_object,
10124 help_echo_pos);
10125 bufp += n, count += n, numchars -= n;
10128 goto OTHER;
10131 case ConfigureNotify:
10132 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10133 if (f)
10135 #ifndef USE_X_TOOLKIT
10136 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10137 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10139 /* In the toolkit version, change_frame_size
10140 is called by the code that handles resizing
10141 of the EmacsFrame widget. */
10143 /* Even if the number of character rows and columns has
10144 not changed, the font size may have changed, so we need
10145 to check the pixel dimensions as well. */
10146 if (columns != f->width
10147 || rows != f->height
10148 || event.xconfigure.width != f->output_data.x->pixel_width
10149 || event.xconfigure.height != f->output_data.x->pixel_height)
10151 change_frame_size (f, rows, columns, 0, 1, 0);
10152 SET_FRAME_GARBAGED (f);
10153 cancel_mouse_face (f);
10155 #endif
10157 f->output_data.x->pixel_width = event.xconfigure.width;
10158 f->output_data.x->pixel_height = event.xconfigure.height;
10160 /* What we have now is the position of Emacs's own window.
10161 Convert that to the position of the window manager window. */
10162 x_real_positions (f, &f->output_data.x->left_pos,
10163 &f->output_data.x->top_pos);
10165 #ifdef HAVE_X_I18N
10166 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10167 xic_set_statusarea (f);
10168 #endif
10170 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10172 /* Since the WM decorations come below top_pos now,
10173 we must put them below top_pos in the future. */
10174 f->output_data.x->win_gravity = NorthWestGravity;
10175 x_wm_set_size_hint (f, (long) 0, 0);
10177 #ifdef USE_MOTIF
10178 /* Some window managers pass (0,0) as the location of
10179 the window, and the Motif event handler stores it
10180 in the emacs widget, which messes up Motif menus. */
10181 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10183 event.xconfigure.x = f->output_data.x->widget->core.x;
10184 event.xconfigure.y = f->output_data.x->widget->core.y;
10186 #endif /* USE_MOTIF */
10188 goto OTHER;
10190 case ButtonPress:
10191 case ButtonRelease:
10193 /* If we decide we want to generate an event to be seen
10194 by the rest of Emacs, we put it here. */
10195 struct input_event emacs_event;
10196 int tool_bar_p = 0;
10198 emacs_event.kind = no_event;
10199 bzero (&compose_status, sizeof (compose_status));
10201 if (dpyinfo->grabbed
10202 && last_mouse_frame
10203 && FRAME_LIVE_P (last_mouse_frame))
10204 f = last_mouse_frame;
10205 else
10206 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10208 if (f)
10210 /* Is this in the tool-bar? */
10211 if (WINDOWP (f->tool_bar_window)
10212 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10214 Lisp_Object window;
10215 int p, x, y;
10217 x = event.xbutton.x;
10218 y = event.xbutton.y;
10220 /* Set x and y. */
10221 window = window_from_coordinates (f, x, y, &p, 1);
10222 if (EQ (window, f->tool_bar_window))
10224 x_handle_tool_bar_click (f, &event.xbutton);
10225 tool_bar_p = 1;
10229 if (!tool_bar_p)
10230 if (!dpyinfo->x_focus_frame
10231 || f == dpyinfo->x_focus_frame)
10232 construct_mouse_click (&emacs_event, &event, f);
10234 else
10236 #ifndef USE_TOOLKIT_SCROLL_BARS
10237 struct scroll_bar *bar
10238 = x_window_to_scroll_bar (event.xbutton.window);
10240 if (bar)
10241 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10242 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10245 if (event.type == ButtonPress)
10247 dpyinfo->grabbed |= (1 << event.xbutton.button);
10248 last_mouse_frame = f;
10249 /* Ignore any mouse motion that happened
10250 before this event; any subsequent mouse-movement
10251 Emacs events should reflect only motion after
10252 the ButtonPress. */
10253 if (f != 0)
10254 f->mouse_moved = 0;
10256 if (!tool_bar_p)
10257 last_tool_bar_item = -1;
10259 else
10261 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10264 if (numchars >= 1 && emacs_event.kind != no_event)
10266 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10267 bufp++;
10268 count++;
10269 numchars--;
10272 #ifdef USE_X_TOOLKIT
10273 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10274 /* For a down-event in the menu bar,
10275 don't pass it to Xt right now.
10276 Instead, save it away
10277 and we will pass it to Xt from kbd_buffer_get_event.
10278 That way, we can run some Lisp code first. */
10279 if (f && event.type == ButtonPress
10280 /* Verify the event is really within the menu bar
10281 and not just sent to it due to grabbing. */
10282 && event.xbutton.x >= 0
10283 && event.xbutton.x < f->output_data.x->pixel_width
10284 && event.xbutton.y >= 0
10285 && event.xbutton.y < f->output_data.x->menubar_height
10286 && event.xbutton.same_screen)
10288 SET_SAVED_BUTTON_EVENT;
10289 XSETFRAME (last_mouse_press_frame, f);
10291 else if (event.type == ButtonPress)
10293 last_mouse_press_frame = Qnil;
10294 goto OTHER;
10297 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10298 but I am trying to be cautious. */
10299 else if (event.type == ButtonRelease)
10301 if (!NILP (last_mouse_press_frame))
10303 f = XFRAME (last_mouse_press_frame);
10304 if (f->output_data.x)
10305 SET_SAVED_BUTTON_EVENT;
10307 else
10308 goto OTHER;
10310 #endif /* USE_MOTIF */
10311 else
10312 goto OTHER;
10313 #endif /* USE_X_TOOLKIT */
10315 break;
10317 case CirculateNotify:
10318 goto OTHER;
10320 case CirculateRequest:
10321 goto OTHER;
10323 case VisibilityNotify:
10324 goto OTHER;
10326 case MappingNotify:
10327 /* Someone has changed the keyboard mapping - update the
10328 local cache. */
10329 switch (event.xmapping.request)
10331 case MappingModifier:
10332 x_find_modifier_meanings (dpyinfo);
10333 /* This is meant to fall through. */
10334 case MappingKeyboard:
10335 XRefreshKeyboardMapping (&event.xmapping);
10337 goto OTHER;
10339 default:
10340 OTHER:
10341 #ifdef USE_X_TOOLKIT
10342 BLOCK_INPUT;
10343 XtDispatchEvent (&event);
10344 UNBLOCK_INPUT;
10345 #endif /* USE_X_TOOLKIT */
10346 break;
10351 out:;
10353 /* On some systems, an X bug causes Emacs to get no more events
10354 when the window is destroyed. Detect that. (1994.) */
10355 if (! event_found)
10357 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10358 One XNOOP in 100 loops will make Emacs terminate.
10359 B. Bretthauer, 1994 */
10360 x_noop_count++;
10361 if (x_noop_count >= 100)
10363 x_noop_count=0;
10365 if (next_noop_dpyinfo == 0)
10366 next_noop_dpyinfo = x_display_list;
10368 XNoOp (next_noop_dpyinfo->display);
10370 /* Each time we get here, cycle through the displays now open. */
10371 next_noop_dpyinfo = next_noop_dpyinfo->next;
10375 /* If the focus was just given to an auto-raising frame,
10376 raise it now. */
10377 /* ??? This ought to be able to handle more than one such frame. */
10378 if (pending_autoraise_frame)
10380 x_raise_frame (pending_autoraise_frame);
10381 pending_autoraise_frame = 0;
10384 UNBLOCK_INPUT;
10385 --handling_signal;
10386 return count;
10392 /***********************************************************************
10393 Text Cursor
10394 ***********************************************************************/
10396 /* Note if the text cursor of window W has been overwritten by a
10397 drawing operation that outputs N glyphs starting at HPOS in the
10398 line given by output_cursor.vpos. N < 0 means all the rest of the
10399 line after HPOS has been written. */
10401 static void
10402 note_overwritten_text_cursor (w, hpos, n)
10403 struct window *w;
10404 int hpos, n;
10406 if (updated_area == TEXT_AREA
10407 && output_cursor.vpos == w->phys_cursor.vpos
10408 && hpos <= w->phys_cursor.hpos
10409 && (n < 0
10410 || hpos + n > w->phys_cursor.hpos))
10411 w->phys_cursor_on_p = 0;
10415 /* Set clipping for output in glyph row ROW. W is the window in which
10416 we operate. GC is the graphics context to set clipping in.
10417 WHOLE_LINE_P non-zero means include the areas used for truncation
10418 mark display and alike in the clipping rectangle.
10420 ROW may be a text row or, e.g., a mode line. Text rows must be
10421 clipped to the interior of the window dedicated to text display,
10422 mode lines must be clipped to the whole window. */
10424 static void
10425 x_clip_to_row (w, row, gc, whole_line_p)
10426 struct window *w;
10427 struct glyph_row *row;
10428 GC gc;
10429 int whole_line_p;
10431 struct frame *f = XFRAME (WINDOW_FRAME (w));
10432 XRectangle clip_rect;
10433 int window_x, window_y, window_width, window_height;
10435 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10437 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10438 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10439 clip_rect.y = max (clip_rect.y, window_y);
10440 clip_rect.width = window_width;
10441 clip_rect.height = row->visible_height;
10443 /* If clipping to the whole line, including trunc marks, extend
10444 the rectangle to the left and increase its width. */
10445 if (whole_line_p)
10447 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10448 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10451 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10455 /* Draw a hollow box cursor on window W in glyph row ROW. */
10457 static void
10458 x_draw_hollow_cursor (w, row)
10459 struct window *w;
10460 struct glyph_row *row;
10462 struct frame *f = XFRAME (WINDOW_FRAME (w));
10463 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10464 Display *dpy = FRAME_X_DISPLAY (f);
10465 int x, y, wd, h;
10466 XGCValues xgcv;
10467 struct glyph *cursor_glyph;
10468 GC gc;
10470 /* Compute frame-relative coordinates from window-relative
10471 coordinates. */
10472 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10473 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10474 + row->ascent - w->phys_cursor_ascent);
10475 h = row->height - 1;
10477 /* Get the glyph the cursor is on. If we can't tell because
10478 the current matrix is invalid or such, give up. */
10479 cursor_glyph = get_phys_cursor_glyph (w);
10480 if (cursor_glyph == NULL)
10481 return;
10483 /* Compute the width of the rectangle to draw. If on a stretch
10484 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10485 rectangle as wide as the glyph, but use a canonical character
10486 width instead. */
10487 wd = cursor_glyph->pixel_width - 1;
10488 if (cursor_glyph->type == STRETCH_GLYPH
10489 && !x_stretch_cursor_p)
10490 wd = min (CANON_X_UNIT (f), wd);
10492 /* The foreground of cursor_gc is typically the same as the normal
10493 background color, which can cause the cursor box to be invisible. */
10494 xgcv.foreground = f->output_data.x->cursor_pixel;
10495 if (dpyinfo->scratch_cursor_gc)
10496 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10497 else
10498 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10499 GCForeground, &xgcv);
10500 gc = dpyinfo->scratch_cursor_gc;
10502 /* Set clipping, draw the rectangle, and reset clipping again. */
10503 x_clip_to_row (w, row, gc, 0);
10504 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10505 XSetClipMask (dpy, gc, None);
10509 /* Draw a bar cursor on window W in glyph row ROW.
10511 Implementation note: One would like to draw a bar cursor with an
10512 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10513 Unfortunately, I didn't find a font yet that has this property set.
10514 --gerd. */
10516 static void
10517 x_draw_bar_cursor (w, row, width)
10518 struct window *w;
10519 struct glyph_row *row;
10520 int width;
10522 struct frame *f = XFRAME (w->frame);
10523 struct glyph *cursor_glyph;
10524 GC gc;
10525 int x;
10526 unsigned long mask;
10527 XGCValues xgcv;
10528 Display *dpy;
10529 Window window;
10531 /* If cursor is out of bounds, don't draw garbage. This can happen
10532 in mini-buffer windows when switching between echo area glyphs
10533 and mini-buffer. */
10534 cursor_glyph = get_phys_cursor_glyph (w);
10535 if (cursor_glyph == NULL)
10536 return;
10538 /* If on an image, draw like a normal cursor. That's usually better
10539 visible than drawing a bar, esp. if the image is large so that
10540 the bar might not be in the window. */
10541 if (cursor_glyph->type == IMAGE_GLYPH)
10543 struct glyph_row *row;
10544 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10545 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10547 else
10549 xgcv.background = f->output_data.x->cursor_pixel;
10550 xgcv.foreground = f->output_data.x->cursor_pixel;
10551 xgcv.graphics_exposures = 0;
10552 mask = GCForeground | GCBackground | GCGraphicsExposures;
10553 dpy = FRAME_X_DISPLAY (f);
10554 window = FRAME_X_WINDOW (f);
10555 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10557 if (gc)
10558 XChangeGC (dpy, gc, mask, &xgcv);
10559 else
10561 gc = XCreateGC (dpy, window, mask, &xgcv);
10562 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10565 if (width < 0)
10566 width = f->output_data.x->cursor_width;
10568 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10569 x_clip_to_row (w, row, gc, 0);
10570 XFillRectangle (dpy, window, gc,
10572 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10573 min (cursor_glyph->pixel_width, width),
10574 row->height);
10575 XSetClipMask (dpy, gc, None);
10580 /* Clear the cursor of window W to background color, and mark the
10581 cursor as not shown. This is used when the text where the cursor
10582 is is about to be rewritten. */
10584 static void
10585 x_clear_cursor (w)
10586 struct window *w;
10588 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10589 x_update_window_cursor (w, 0);
10593 /* Draw the cursor glyph of window W in glyph row ROW. See the
10594 comment of x_draw_glyphs for the meaning of HL. */
10596 static void
10597 x_draw_phys_cursor_glyph (w, row, hl)
10598 struct window *w;
10599 struct glyph_row *row;
10600 enum draw_glyphs_face hl;
10602 /* If cursor hpos is out of bounds, don't draw garbage. This can
10603 happen in mini-buffer windows when switching between echo area
10604 glyphs and mini-buffer. */
10605 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10607 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10608 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10609 hl, 0, 0, 0);
10611 /* When we erase the cursor, and ROW is overlapped by other
10612 rows, make sure that these overlapping parts of other rows
10613 are redrawn. */
10614 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10616 if (row > w->current_matrix->rows
10617 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10618 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10620 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10621 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10622 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10628 /* Erase the image of a cursor of window W from the screen. */
10630 static void
10631 x_erase_phys_cursor (w)
10632 struct window *w;
10634 struct frame *f = XFRAME (w->frame);
10635 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10636 int hpos = w->phys_cursor.hpos;
10637 int vpos = w->phys_cursor.vpos;
10638 int mouse_face_here_p = 0;
10639 struct glyph_matrix *active_glyphs = w->current_matrix;
10640 struct glyph_row *cursor_row;
10641 struct glyph *cursor_glyph;
10642 enum draw_glyphs_face hl;
10644 /* No cursor displayed or row invalidated => nothing to do on the
10645 screen. */
10646 if (w->phys_cursor_type == NO_CURSOR)
10647 goto mark_cursor_off;
10649 /* VPOS >= active_glyphs->nrows means that window has been resized.
10650 Don't bother to erase the cursor. */
10651 if (vpos >= active_glyphs->nrows)
10652 goto mark_cursor_off;
10654 /* If row containing cursor is marked invalid, there is nothing we
10655 can do. */
10656 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10657 if (!cursor_row->enabled_p)
10658 goto mark_cursor_off;
10660 /* This can happen when the new row is shorter than the old one.
10661 In this case, either x_draw_glyphs or clear_end_of_line
10662 should have cleared the cursor. Note that we wouldn't be
10663 able to erase the cursor in this case because we don't have a
10664 cursor glyph at hand. */
10665 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10666 goto mark_cursor_off;
10668 /* If the cursor is in the mouse face area, redisplay that when
10669 we clear the cursor. */
10670 if (! NILP (dpyinfo->mouse_face_window)
10671 && w == XWINDOW (dpyinfo->mouse_face_window)
10672 && (vpos > dpyinfo->mouse_face_beg_row
10673 || (vpos == dpyinfo->mouse_face_beg_row
10674 && hpos >= dpyinfo->mouse_face_beg_col))
10675 && (vpos < dpyinfo->mouse_face_end_row
10676 || (vpos == dpyinfo->mouse_face_end_row
10677 && hpos < dpyinfo->mouse_face_end_col))
10678 /* Don't redraw the cursor's spot in mouse face if it is at the
10679 end of a line (on a newline). The cursor appears there, but
10680 mouse highlighting does not. */
10681 && cursor_row->used[TEXT_AREA] > hpos)
10682 mouse_face_here_p = 1;
10684 /* Maybe clear the display under the cursor. */
10685 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10687 int x;
10688 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10690 cursor_glyph = get_phys_cursor_glyph (w);
10691 if (cursor_glyph == NULL)
10692 goto mark_cursor_off;
10694 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10696 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10698 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10699 cursor_row->y)),
10700 cursor_glyph->pixel_width,
10701 cursor_row->visible_height,
10702 False);
10705 /* Erase the cursor by redrawing the character underneath it. */
10706 if (mouse_face_here_p)
10707 hl = DRAW_MOUSE_FACE;
10708 else if (cursor_row->inverse_p)
10709 hl = DRAW_INVERSE_VIDEO;
10710 else
10711 hl = DRAW_NORMAL_TEXT;
10712 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10714 mark_cursor_off:
10715 w->phys_cursor_on_p = 0;
10716 w->phys_cursor_type = NO_CURSOR;
10720 /* Display or clear cursor of window W. If ON is zero, clear the
10721 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10722 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10724 void
10725 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10726 struct window *w;
10727 int on, hpos, vpos, x, y;
10729 struct frame *f = XFRAME (w->frame);
10730 int new_cursor_type;
10731 int new_cursor_width;
10732 struct glyph_matrix *current_glyphs;
10733 struct glyph_row *glyph_row;
10734 struct glyph *glyph;
10736 /* This is pointless on invisible frames, and dangerous on garbaged
10737 windows and frames; in the latter case, the frame or window may
10738 be in the midst of changing its size, and x and y may be off the
10739 window. */
10740 if (! FRAME_VISIBLE_P (f)
10741 || FRAME_GARBAGED_P (f)
10742 || vpos >= w->current_matrix->nrows
10743 || hpos >= w->current_matrix->matrix_w)
10744 return;
10746 /* If cursor is off and we want it off, return quickly. */
10747 if (!on && !w->phys_cursor_on_p)
10748 return;
10750 current_glyphs = w->current_matrix;
10751 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10752 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10754 /* If cursor row is not enabled, we don't really know where to
10755 display the cursor. */
10756 if (!glyph_row->enabled_p)
10758 w->phys_cursor_on_p = 0;
10759 return;
10762 xassert (interrupt_input_blocked);
10764 /* Set new_cursor_type to the cursor we want to be displayed. In a
10765 mini-buffer window, we want the cursor only to appear if we are
10766 reading input from this window. For the selected window, we want
10767 the cursor type given by the frame parameter. If explicitly
10768 marked off, draw no cursor. In all other cases, we want a hollow
10769 box cursor. */
10770 new_cursor_width = -1;
10771 if (cursor_in_echo_area
10772 && FRAME_HAS_MINIBUF_P (f)
10773 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10775 if (w == XWINDOW (echo_area_window))
10776 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10777 else
10778 new_cursor_type = HOLLOW_BOX_CURSOR;
10780 else
10782 if (w != XWINDOW (selected_window)
10783 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10785 extern int cursor_in_non_selected_windows;
10787 if (MINI_WINDOW_P (w)
10788 || !cursor_in_non_selected_windows
10789 || NILP (XBUFFER (w->buffer)->cursor_type))
10790 new_cursor_type = NO_CURSOR;
10791 else
10792 new_cursor_type = HOLLOW_BOX_CURSOR;
10794 else if (w->cursor_off_p)
10795 new_cursor_type = NO_CURSOR;
10796 else
10798 struct buffer *b = XBUFFER (w->buffer);
10800 if (EQ (b->cursor_type, Qt))
10801 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10802 else
10803 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10804 &new_cursor_width);
10808 /* If cursor is currently being shown and we don't want it to be or
10809 it is in the wrong place, or the cursor type is not what we want,
10810 erase it. */
10811 if (w->phys_cursor_on_p
10812 && (!on
10813 || w->phys_cursor.x != x
10814 || w->phys_cursor.y != y
10815 || new_cursor_type != w->phys_cursor_type))
10816 x_erase_phys_cursor (w);
10818 /* If the cursor is now invisible and we want it to be visible,
10819 display it. */
10820 if (on && !w->phys_cursor_on_p)
10822 w->phys_cursor_ascent = glyph_row->ascent;
10823 w->phys_cursor_height = glyph_row->height;
10825 /* Set phys_cursor_.* before x_draw_.* is called because some
10826 of them may need the information. */
10827 w->phys_cursor.x = x;
10828 w->phys_cursor.y = glyph_row->y;
10829 w->phys_cursor.hpos = hpos;
10830 w->phys_cursor.vpos = vpos;
10831 w->phys_cursor_type = new_cursor_type;
10832 w->phys_cursor_on_p = 1;
10834 switch (new_cursor_type)
10836 case HOLLOW_BOX_CURSOR:
10837 x_draw_hollow_cursor (w, glyph_row);
10838 break;
10840 case FILLED_BOX_CURSOR:
10841 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10842 break;
10844 case BAR_CURSOR:
10845 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10846 break;
10848 case NO_CURSOR:
10849 break;
10851 default:
10852 abort ();
10855 #ifdef HAVE_X_I18N
10856 if (w == XWINDOW (f->selected_window))
10857 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10858 xic_set_preeditarea (w, x, y);
10859 #endif
10862 #ifndef XFlush
10863 if (updating_frame != f)
10864 XFlush (FRAME_X_DISPLAY (f));
10865 #endif
10869 /* Display the cursor on window W, or clear it. X and Y are window
10870 relative pixel coordinates. HPOS and VPOS are glyph matrix
10871 positions. If W is not the selected window, display a hollow
10872 cursor. ON non-zero means display the cursor at X, Y which
10873 correspond to HPOS, VPOS, otherwise it is cleared. */
10875 void
10876 x_display_cursor (w, on, hpos, vpos, x, y)
10877 struct window *w;
10878 int on, hpos, vpos, x, y;
10880 BLOCK_INPUT;
10881 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10882 UNBLOCK_INPUT;
10886 /* Display the cursor on window W, or clear it, according to ON_P.
10887 Don't change the cursor's position. */
10889 void
10890 x_update_cursor (f, on_p)
10891 struct frame *f;
10893 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10897 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10898 in the window tree rooted at W. */
10900 static void
10901 x_update_cursor_in_window_tree (w, on_p)
10902 struct window *w;
10903 int on_p;
10905 while (w)
10907 if (!NILP (w->hchild))
10908 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10909 else if (!NILP (w->vchild))
10910 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10911 else
10912 x_update_window_cursor (w, on_p);
10914 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10919 /* Switch the display of W's cursor on or off, according to the value
10920 of ON. */
10922 static void
10923 x_update_window_cursor (w, on)
10924 struct window *w;
10925 int on;
10927 /* Don't update cursor in windows whose frame is in the process
10928 of being deleted. */
10929 if (w->current_matrix)
10931 BLOCK_INPUT;
10932 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10933 w->phys_cursor.x, w->phys_cursor.y);
10934 UNBLOCK_INPUT;
10941 /* Icons. */
10943 /* Refresh bitmap kitchen sink icon for frame F
10944 when we get an expose event for it. */
10946 void
10947 refreshicon (f)
10948 struct frame *f;
10950 /* Normally, the window manager handles this function. */
10953 /* Make the x-window of frame F use the gnu icon bitmap. */
10956 x_bitmap_icon (f, file)
10957 struct frame *f;
10958 Lisp_Object file;
10960 int bitmap_id;
10962 if (FRAME_X_WINDOW (f) == 0)
10963 return 1;
10965 /* Free up our existing icon bitmap if any. */
10966 if (f->output_data.x->icon_bitmap > 0)
10967 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10968 f->output_data.x->icon_bitmap = 0;
10970 if (STRINGP (file))
10971 bitmap_id = x_create_bitmap_from_file (f, file);
10972 else
10974 /* Create the GNU bitmap if necessary. */
10975 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10976 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10977 = x_create_bitmap_from_data (f, gnu_bits,
10978 gnu_width, gnu_height);
10980 /* The first time we create the GNU bitmap,
10981 this increments the ref-count one extra time.
10982 As a result, the GNU bitmap is never freed.
10983 That way, we don't have to worry about allocating it again. */
10984 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10986 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10989 x_wm_set_icon_pixmap (f, bitmap_id);
10990 f->output_data.x->icon_bitmap = bitmap_id;
10992 return 0;
10996 /* Make the x-window of frame F use a rectangle with text.
10997 Use ICON_NAME as the text. */
11000 x_text_icon (f, icon_name)
11001 struct frame *f;
11002 char *icon_name;
11004 if (FRAME_X_WINDOW (f) == 0)
11005 return 1;
11007 #ifdef HAVE_X11R4
11009 XTextProperty text;
11010 text.value = (unsigned char *) icon_name;
11011 text.encoding = XA_STRING;
11012 text.format = 8;
11013 text.nitems = strlen (icon_name);
11014 #ifdef USE_X_TOOLKIT
11015 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11016 &text);
11017 #else /* not USE_X_TOOLKIT */
11018 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11019 #endif /* not USE_X_TOOLKIT */
11021 #else /* not HAVE_X11R4 */
11022 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11023 #endif /* not HAVE_X11R4 */
11025 if (f->output_data.x->icon_bitmap > 0)
11026 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11027 f->output_data.x->icon_bitmap = 0;
11028 x_wm_set_icon_pixmap (f, 0);
11030 return 0;
11033 #define X_ERROR_MESSAGE_SIZE 200
11035 /* If non-nil, this should be a string.
11036 It means catch X errors and store the error message in this string. */
11038 static Lisp_Object x_error_message_string;
11040 /* An X error handler which stores the error message in
11041 x_error_message_string. This is called from x_error_handler if
11042 x_catch_errors is in effect. */
11044 static void
11045 x_error_catcher (display, error)
11046 Display *display;
11047 XErrorEvent *error;
11049 XGetErrorText (display, error->error_code,
11050 XSTRING (x_error_message_string)->data,
11051 X_ERROR_MESSAGE_SIZE);
11054 /* Begin trapping X errors for display DPY. Actually we trap X errors
11055 for all displays, but DPY should be the display you are actually
11056 operating on.
11058 After calling this function, X protocol errors no longer cause
11059 Emacs to exit; instead, they are recorded in the string
11060 stored in x_error_message_string.
11062 Calling x_check_errors signals an Emacs error if an X error has
11063 occurred since the last call to x_catch_errors or x_check_errors.
11065 Calling x_uncatch_errors resumes the normal error handling. */
11067 void x_check_errors ();
11068 static Lisp_Object x_catch_errors_unwind ();
11071 x_catch_errors (dpy)
11072 Display *dpy;
11074 int count = specpdl_ptr - specpdl;
11076 /* Make sure any errors from previous requests have been dealt with. */
11077 XSync (dpy, False);
11079 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11081 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11082 XSTRING (x_error_message_string)->data[0] = 0;
11084 return count;
11087 /* Unbind the binding that we made to check for X errors. */
11089 static Lisp_Object
11090 x_catch_errors_unwind (old_val)
11091 Lisp_Object old_val;
11093 x_error_message_string = old_val;
11094 return Qnil;
11097 /* If any X protocol errors have arrived since the last call to
11098 x_catch_errors or x_check_errors, signal an Emacs error using
11099 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11101 void
11102 x_check_errors (dpy, format)
11103 Display *dpy;
11104 char *format;
11106 /* Make sure to catch any errors incurred so far. */
11107 XSync (dpy, False);
11109 if (XSTRING (x_error_message_string)->data[0])
11110 error (format, XSTRING (x_error_message_string)->data);
11113 /* Nonzero if we had any X protocol errors
11114 since we did x_catch_errors on DPY. */
11117 x_had_errors_p (dpy)
11118 Display *dpy;
11120 /* Make sure to catch any errors incurred so far. */
11121 XSync (dpy, False);
11123 return XSTRING (x_error_message_string)->data[0] != 0;
11126 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11128 void
11129 x_clear_errors (dpy)
11130 Display *dpy;
11132 XSTRING (x_error_message_string)->data[0] = 0;
11135 /* Stop catching X protocol errors and let them make Emacs die.
11136 DPY should be the display that was passed to x_catch_errors.
11137 COUNT should be the value that was returned by
11138 the corresponding call to x_catch_errors. */
11140 void
11141 x_uncatch_errors (dpy, count)
11142 Display *dpy;
11143 int count;
11145 unbind_to (count, Qnil);
11148 #if 0
11149 static unsigned int x_wire_count;
11150 x_trace_wire ()
11152 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11154 #endif /* ! 0 */
11157 /* Handle SIGPIPE, which can happen when the connection to a server
11158 simply goes away. SIGPIPE is handled by x_connection_signal.
11159 Don't need to do anything, because the write which caused the
11160 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11161 which will do the appropriate cleanup for us. */
11163 static SIGTYPE
11164 x_connection_signal (signalnum) /* If we don't have an argument, */
11165 int signalnum; /* some compilers complain in signal calls. */
11167 #ifdef USG
11168 /* USG systems forget handlers when they are used;
11169 must reestablish each time */
11170 signal (signalnum, x_connection_signal);
11171 #endif /* USG */
11174 /* Handling X errors. */
11176 /* Handle the loss of connection to display DISPLAY. */
11178 static SIGTYPE
11179 x_connection_closed (display, error_message)
11180 Display *display;
11181 char *error_message;
11183 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11184 Lisp_Object frame, tail;
11186 /* Indicate that this display is dead. */
11188 #if 0 /* Closing the display caused a bus error on OpenWindows. */
11189 #ifdef USE_X_TOOLKIT
11190 XtCloseDisplay (display);
11191 #endif
11192 #endif
11194 if (dpyinfo)
11195 dpyinfo->display = 0;
11197 /* First delete frames whose mini-buffers are on frames
11198 that are on the dead display. */
11199 FOR_EACH_FRAME (tail, frame)
11201 Lisp_Object minibuf_frame;
11202 minibuf_frame
11203 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11204 if (FRAME_X_P (XFRAME (frame))
11205 && FRAME_X_P (XFRAME (minibuf_frame))
11206 && ! EQ (frame, minibuf_frame)
11207 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11208 Fdelete_frame (frame, Qt);
11211 /* Now delete all remaining frames on the dead display.
11212 We are now sure none of these is used as the mini-buffer
11213 for another frame that we need to delete. */
11214 FOR_EACH_FRAME (tail, frame)
11215 if (FRAME_X_P (XFRAME (frame))
11216 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11218 /* Set this to t so that Fdelete_frame won't get confused
11219 trying to find a replacement. */
11220 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11221 Fdelete_frame (frame, Qt);
11224 if (dpyinfo)
11225 x_delete_display (dpyinfo);
11227 if (x_display_list == 0)
11229 fprintf (stderr, "%s\n", error_message);
11230 shut_down_emacs (0, 0, Qnil);
11231 exit (70);
11234 /* Ordinary stack unwind doesn't deal with these. */
11235 #ifdef SIGIO
11236 sigunblock (sigmask (SIGIO));
11237 #endif
11238 sigunblock (sigmask (SIGALRM));
11239 TOTALLY_UNBLOCK_INPUT;
11241 clear_waiting_for_input ();
11242 handling_signal = 0;
11243 error ("%s", error_message);
11246 /* This is the usual handler for X protocol errors.
11247 It kills all frames on the display that we got the error for.
11248 If that was the only one, it prints an error message and kills Emacs. */
11250 static void
11251 x_error_quitter (display, error)
11252 Display *display;
11253 XErrorEvent *error;
11255 char buf[256], buf1[356];
11257 /* Note that there is no real way portable across R3/R4 to get the
11258 original error handler. */
11260 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11261 sprintf (buf1, "X protocol error: %s on protocol request %d",
11262 buf, error->request_code);
11263 x_connection_closed (display, buf1);
11266 /* This is the first-level handler for X protocol errors.
11267 It calls x_error_quitter or x_error_catcher. */
11269 static int
11270 x_error_handler (display, error)
11271 Display *display;
11272 XErrorEvent *error;
11274 if (! NILP (x_error_message_string))
11275 x_error_catcher (display, error);
11276 else
11277 x_error_quitter (display, error);
11278 return 0;
11281 /* This is the handler for X IO errors, always.
11282 It kills all frames on the display that we lost touch with.
11283 If that was the only one, it prints an error message and kills Emacs. */
11285 static int
11286 x_io_error_quitter (display)
11287 Display *display;
11289 char buf[256];
11291 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11292 x_connection_closed (display, buf);
11293 return 0;
11296 /* Changing the font of the frame. */
11298 /* Give frame F the font named FONTNAME as its default font, and
11299 return the full name of that font. FONTNAME may be a wildcard
11300 pattern; in that case, we choose some font that fits the pattern.
11301 The return value shows which font we chose. */
11303 Lisp_Object
11304 x_new_font (f, fontname)
11305 struct frame *f;
11306 register char *fontname;
11308 struct font_info *fontp
11309 = FS_LOAD_FONT (f, 0, fontname, -1);
11311 if (!fontp)
11312 return Qnil;
11314 f->output_data.x->font = (XFontStruct *) (fontp->font);
11315 f->output_data.x->baseline_offset = fontp->baseline_offset;
11316 f->output_data.x->fontset = -1;
11318 /* Compute the scroll bar width in character columns. */
11319 if (f->scroll_bar_pixel_width > 0)
11321 int wid = FONT_WIDTH (f->output_data.x->font);
11322 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11324 else
11326 int wid = FONT_WIDTH (f->output_data.x->font);
11327 f->scroll_bar_cols = (14 + wid - 1) / wid;
11330 /* Now make the frame display the given font. */
11331 if (FRAME_X_WINDOW (f) != 0)
11333 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11334 f->output_data.x->font->fid);
11335 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11336 f->output_data.x->font->fid);
11337 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11338 f->output_data.x->font->fid);
11340 frame_update_line_height (f);
11341 x_set_window_size (f, 0, f->width, f->height);
11343 else
11344 /* If we are setting a new frame's font for the first time,
11345 there are no faces yet, so this font's height is the line height. */
11346 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11348 return build_string (fontp->full_name);
11351 /* Give frame F the fontset named FONTSETNAME as its default font, and
11352 return the full name of that fontset. FONTSETNAME may be a wildcard
11353 pattern; in that case, we choose some fontset that fits the pattern.
11354 The return value shows which fontset we chose. */
11356 Lisp_Object
11357 x_new_fontset (f, fontsetname)
11358 struct frame *f;
11359 char *fontsetname;
11361 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11362 Lisp_Object result;
11364 if (fontset < 0)
11365 return Qnil;
11367 if (f->output_data.x->fontset == fontset)
11368 /* This fontset is already set in frame F. There's nothing more
11369 to do. */
11370 return fontset_name (fontset);
11372 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11374 if (!STRINGP (result))
11375 /* Can't load ASCII font. */
11376 return Qnil;
11378 /* Since x_new_font doesn't update any fontset information, do it now. */
11379 f->output_data.x->fontset = fontset;
11381 #ifdef HAVE_X_I18N
11382 if (FRAME_XIC (f)
11383 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11384 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11385 #endif
11387 return build_string (fontsetname);
11391 /***********************************************************************
11392 X Input Methods
11393 ***********************************************************************/
11395 #ifdef HAVE_X_I18N
11397 #ifdef HAVE_X11R6
11399 /* XIM destroy callback function, which is called whenever the
11400 connection to input method XIM dies. CLIENT_DATA contains a
11401 pointer to the x_display_info structure corresponding to XIM. */
11403 static void
11404 xim_destroy_callback (xim, client_data, call_data)
11405 XIM xim;
11406 XPointer client_data;
11407 XPointer call_data;
11409 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11410 Lisp_Object frame, tail;
11412 BLOCK_INPUT;
11414 /* No need to call XDestroyIC.. */
11415 FOR_EACH_FRAME (tail, frame)
11417 struct frame *f = XFRAME (frame);
11418 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11420 FRAME_XIC (f) = NULL;
11421 if (FRAME_XIC_FONTSET (f))
11423 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11424 FRAME_XIC_FONTSET (f) = NULL;
11429 /* No need to call XCloseIM. */
11430 dpyinfo->xim = NULL;
11431 XFree (dpyinfo->xim_styles);
11432 UNBLOCK_INPUT;
11435 #endif /* HAVE_X11R6 */
11437 /* Open the connection to the XIM server on display DPYINFO.
11438 RESOURCE_NAME is the resource name Emacs uses. */
11440 static void
11441 xim_open_dpy (dpyinfo, resource_name)
11442 struct x_display_info *dpyinfo;
11443 char *resource_name;
11445 #ifdef USE_XIM
11446 XIM xim;
11448 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11449 dpyinfo->xim = xim;
11451 if (xim)
11453 #ifdef HAVE_X11R6
11454 XIMCallback destroy;
11455 #endif
11457 /* Get supported styles and XIM values. */
11458 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11460 #ifdef HAVE_X11R6
11461 destroy.callback = xim_destroy_callback;
11462 destroy.client_data = (XPointer)dpyinfo;
11463 /* This isn't prptotyped in OSF 5.0. */
11464 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11465 #endif
11468 #else /* not USE_XIM */
11469 dpyinfo->xim = NULL;
11470 #endif /* not USE_XIM */
11474 #ifdef HAVE_X11R6_XIM
11476 struct xim_inst_t
11478 struct x_display_info *dpyinfo;
11479 char *resource_name;
11482 /* XIM instantiate callback function, which is called whenever an XIM
11483 server is available. DISPLAY is teh display of the XIM.
11484 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11485 when the callback was registered. */
11487 static void
11488 xim_instantiate_callback (display, client_data, call_data)
11489 Display *display;
11490 XPointer client_data;
11491 XPointer call_data;
11493 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11494 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11496 /* We don't support multiple XIM connections. */
11497 if (dpyinfo->xim)
11498 return;
11500 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11502 /* Create XIC for the existing frames on the same display, as long
11503 as they have no XIC. */
11504 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11506 Lisp_Object tail, frame;
11508 BLOCK_INPUT;
11509 FOR_EACH_FRAME (tail, frame)
11511 struct frame *f = XFRAME (frame);
11513 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11514 if (FRAME_XIC (f) == NULL)
11516 create_frame_xic (f);
11517 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11518 xic_set_statusarea (f);
11519 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11521 struct window *w = XWINDOW (f->selected_window);
11522 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11527 UNBLOCK_INPUT;
11531 #endif /* HAVE_X11R6_XIM */
11534 /* Open a connection to the XIM server on display DPYINFO.
11535 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11536 connection only at the first time. On X11R6, open the connection
11537 in the XIM instantiate callback function. */
11539 static void
11540 xim_initialize (dpyinfo, resource_name)
11541 struct x_display_info *dpyinfo;
11542 char *resource_name;
11544 #ifdef USE_XIM
11545 #ifdef HAVE_X11R6_XIM
11546 struct xim_inst_t *xim_inst;
11547 int len;
11549 dpyinfo->xim = NULL;
11550 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11551 xim_inst->dpyinfo = dpyinfo;
11552 len = strlen (resource_name);
11553 xim_inst->resource_name = (char *) xmalloc (len + 1);
11554 bcopy (resource_name, xim_inst->resource_name, len + 1);
11555 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11556 resource_name, EMACS_CLASS,
11557 xim_instantiate_callback,
11558 /* Fixme: This is XPointer in
11559 XFree86 but (XPointer *) on
11560 Tru64, at least. */
11561 (XPointer) xim_inst);
11562 #else /* not HAVE_X11R6_XIM */
11563 dpyinfo->xim = NULL;
11564 xim_open_dpy (dpyinfo, resource_name);
11565 #endif /* not HAVE_X11R6_XIM */
11567 #else /* not USE_XIM */
11568 dpyinfo->xim = NULL;
11569 #endif /* not USE_XIM */
11573 /* Close the connection to the XIM server on display DPYINFO. */
11575 static void
11576 xim_close_dpy (dpyinfo)
11577 struct x_display_info *dpyinfo;
11579 #ifdef USE_XIM
11580 #ifdef HAVE_X11R6_XIM
11581 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11582 NULL, EMACS_CLASS,
11583 xim_instantiate_callback, NULL);
11584 #endif /* not HAVE_X11R6_XIM */
11585 XCloseIM (dpyinfo->xim);
11586 dpyinfo->xim = NULL;
11587 XFree (dpyinfo->xim_styles);
11588 #endif /* USE_XIM */
11591 #endif /* not HAVE_X11R6_XIM */
11595 /* Calculate the absolute position in frame F
11596 from its current recorded position values and gravity. */
11598 void
11599 x_calc_absolute_position (f)
11600 struct frame *f;
11602 Window child;
11603 int win_x = 0, win_y = 0;
11604 int flags = f->output_data.x->size_hint_flags;
11605 int this_window;
11607 /* We have nothing to do if the current position
11608 is already for the top-left corner. */
11609 if (! ((flags & XNegative) || (flags & YNegative)))
11610 return;
11612 #ifdef USE_X_TOOLKIT
11613 this_window = XtWindow (f->output_data.x->widget);
11614 #else
11615 this_window = FRAME_X_WINDOW (f);
11616 #endif
11618 /* Find the position of the outside upper-left corner of
11619 the inner window, with respect to the outer window.
11620 But do this only if we will need the results. */
11621 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11623 int count;
11625 BLOCK_INPUT;
11626 count = x_catch_errors (FRAME_X_DISPLAY (f));
11627 while (1)
11629 x_clear_errors (FRAME_X_DISPLAY (f));
11630 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11632 /* From-window, to-window. */
11633 this_window,
11634 f->output_data.x->parent_desc,
11636 /* From-position, to-position. */
11637 0, 0, &win_x, &win_y,
11639 /* Child of win. */
11640 &child);
11641 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11643 Window newroot, newparent = 0xdeadbeef;
11644 Window *newchildren;
11645 unsigned int nchildren;
11647 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11648 &newparent, &newchildren, &nchildren))
11649 break;
11651 XFree ((char *) newchildren);
11653 f->output_data.x->parent_desc = newparent;
11655 else
11656 break;
11659 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11660 UNBLOCK_INPUT;
11663 /* Treat negative positions as relative to the leftmost bottommost
11664 position that fits on the screen. */
11665 if (flags & XNegative)
11666 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11667 - 2 * f->output_data.x->border_width - win_x
11668 - PIXEL_WIDTH (f)
11669 + f->output_data.x->left_pos);
11671 if (flags & YNegative)
11673 int menubar_height = 0;
11675 #ifdef USE_X_TOOLKIT
11676 if (f->output_data.x->menubar_widget)
11677 menubar_height
11678 = (f->output_data.x->menubar_widget->core.height
11679 + f->output_data.x->menubar_widget->core.border_width);
11680 #endif
11682 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11683 - 2 * f->output_data.x->border_width
11684 - win_y
11685 - PIXEL_HEIGHT (f)
11686 - menubar_height
11687 + f->output_data.x->top_pos);
11690 /* The left_pos and top_pos
11691 are now relative to the top and left screen edges,
11692 so the flags should correspond. */
11693 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11696 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11697 to really change the position, and 0 when calling from
11698 x_make_frame_visible (in that case, XOFF and YOFF are the current
11699 position values). It is -1 when calling from x_set_frame_parameters,
11700 which means, do adjust for borders but don't change the gravity. */
11702 void
11703 x_set_offset (f, xoff, yoff, change_gravity)
11704 struct frame *f;
11705 register int xoff, yoff;
11706 int change_gravity;
11708 int modified_top, modified_left;
11710 if (change_gravity > 0)
11712 f->output_data.x->top_pos = yoff;
11713 f->output_data.x->left_pos = xoff;
11714 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11715 if (xoff < 0)
11716 f->output_data.x->size_hint_flags |= XNegative;
11717 if (yoff < 0)
11718 f->output_data.x->size_hint_flags |= YNegative;
11719 f->output_data.x->win_gravity = NorthWestGravity;
11721 x_calc_absolute_position (f);
11723 BLOCK_INPUT;
11724 x_wm_set_size_hint (f, (long) 0, 0);
11726 modified_left = f->output_data.x->left_pos;
11727 modified_top = f->output_data.x->top_pos;
11728 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11729 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11730 /* It is a mystery why we need to add the border_width here
11731 when the frame is already visible, but experiment says we do. */
11732 if (change_gravity != 0)
11734 modified_left += f->output_data.x->border_width;
11735 modified_top += f->output_data.x->border_width;
11737 #endif
11739 #ifdef USE_X_TOOLKIT
11740 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11741 modified_left, modified_top);
11742 #else /* not USE_X_TOOLKIT */
11743 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11744 modified_left, modified_top);
11745 #endif /* not USE_X_TOOLKIT */
11746 UNBLOCK_INPUT;
11749 /* Call this to change the size of frame F's x-window.
11750 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11751 for this size change and subsequent size changes.
11752 Otherwise we leave the window gravity unchanged. */
11754 void
11755 x_set_window_size (f, change_gravity, cols, rows)
11756 struct frame *f;
11757 int change_gravity;
11758 int cols, rows;
11760 #ifndef USE_X_TOOLKIT
11761 int pixelwidth, pixelheight;
11762 #endif
11764 BLOCK_INPUT;
11766 #ifdef USE_X_TOOLKIT
11768 /* The x and y position of the widget is clobbered by the
11769 call to XtSetValues within EmacsFrameSetCharSize.
11770 This is a real kludge, but I don't understand Xt so I can't
11771 figure out a correct fix. Can anyone else tell me? -- rms. */
11772 int xpos = f->output_data.x->widget->core.x;
11773 int ypos = f->output_data.x->widget->core.y;
11774 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11775 f->output_data.x->widget->core.x = xpos;
11776 f->output_data.x->widget->core.y = ypos;
11779 #else /* not USE_X_TOOLKIT */
11781 check_frame_size (f, &rows, &cols);
11782 f->output_data.x->vertical_scroll_bar_extra
11783 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11785 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11786 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11787 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11788 f->output_data.x->flags_areas_extra
11789 = FRAME_FLAGS_AREA_WIDTH (f);
11790 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11791 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11793 f->output_data.x->win_gravity = NorthWestGravity;
11794 x_wm_set_size_hint (f, (long) 0, 0);
11796 XSync (FRAME_X_DISPLAY (f), False);
11797 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11798 pixelwidth, pixelheight);
11800 /* Now, strictly speaking, we can't be sure that this is accurate,
11801 but the window manager will get around to dealing with the size
11802 change request eventually, and we'll hear how it went when the
11803 ConfigureNotify event gets here.
11805 We could just not bother storing any of this information here,
11806 and let the ConfigureNotify event set everything up, but that
11807 might be kind of confusing to the Lisp code, since size changes
11808 wouldn't be reported in the frame parameters until some random
11809 point in the future when the ConfigureNotify event arrives.
11811 We pass 1 for DELAY since we can't run Lisp code inside of
11812 a BLOCK_INPUT. */
11813 change_frame_size (f, rows, cols, 0, 1, 0);
11814 PIXEL_WIDTH (f) = pixelwidth;
11815 PIXEL_HEIGHT (f) = pixelheight;
11817 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11818 receive in the ConfigureNotify event; if we get what we asked
11819 for, then the event won't cause the screen to become garbaged, so
11820 we have to make sure to do it here. */
11821 SET_FRAME_GARBAGED (f);
11823 XFlush (FRAME_X_DISPLAY (f));
11825 #endif /* not USE_X_TOOLKIT */
11827 /* If cursor was outside the new size, mark it as off. */
11828 mark_window_cursors_off (XWINDOW (f->root_window));
11830 /* Clear out any recollection of where the mouse highlighting was,
11831 since it might be in a place that's outside the new frame size.
11832 Actually checking whether it is outside is a pain in the neck,
11833 so don't try--just let the highlighting be done afresh with new size. */
11834 cancel_mouse_face (f);
11836 UNBLOCK_INPUT;
11839 /* Mouse warping. */
11841 void
11842 x_set_mouse_position (f, x, y)
11843 struct frame *f;
11844 int x, y;
11846 int pix_x, pix_y;
11848 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11849 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11851 if (pix_x < 0) pix_x = 0;
11852 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11854 if (pix_y < 0) pix_y = 0;
11855 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11857 BLOCK_INPUT;
11859 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11860 0, 0, 0, 0, pix_x, pix_y);
11861 UNBLOCK_INPUT;
11864 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11866 void
11867 x_set_mouse_pixel_position (f, pix_x, pix_y)
11868 struct frame *f;
11869 int pix_x, pix_y;
11871 BLOCK_INPUT;
11873 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11874 0, 0, 0, 0, pix_x, pix_y);
11875 UNBLOCK_INPUT;
11878 /* focus shifting, raising and lowering. */
11880 void
11881 x_focus_on_frame (f)
11882 struct frame *f;
11884 #if 0 /* This proves to be unpleasant. */
11885 x_raise_frame (f);
11886 #endif
11887 #if 0
11888 /* I don't think that the ICCCM allows programs to do things like this
11889 without the interaction of the window manager. Whatever you end up
11890 doing with this code, do it to x_unfocus_frame too. */
11891 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11892 RevertToPointerRoot, CurrentTime);
11893 #endif /* ! 0 */
11896 void
11897 x_unfocus_frame (f)
11898 struct frame *f;
11900 #if 0
11901 /* Look at the remarks in x_focus_on_frame. */
11902 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11903 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11904 RevertToPointerRoot, CurrentTime);
11905 #endif /* ! 0 */
11908 /* Raise frame F. */
11910 void
11911 x_raise_frame (f)
11912 struct frame *f;
11914 if (f->async_visible)
11916 BLOCK_INPUT;
11917 #ifdef USE_X_TOOLKIT
11918 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11919 #else /* not USE_X_TOOLKIT */
11920 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11921 #endif /* not USE_X_TOOLKIT */
11922 XFlush (FRAME_X_DISPLAY (f));
11923 UNBLOCK_INPUT;
11927 /* Lower frame F. */
11929 void
11930 x_lower_frame (f)
11931 struct frame *f;
11933 if (f->async_visible)
11935 BLOCK_INPUT;
11936 #ifdef USE_X_TOOLKIT
11937 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11938 #else /* not USE_X_TOOLKIT */
11939 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11940 #endif /* not USE_X_TOOLKIT */
11941 XFlush (FRAME_X_DISPLAY (f));
11942 UNBLOCK_INPUT;
11946 static void
11947 XTframe_raise_lower (f, raise_flag)
11948 FRAME_PTR f;
11949 int raise_flag;
11951 if (raise_flag)
11952 x_raise_frame (f);
11953 else
11954 x_lower_frame (f);
11957 /* Change of visibility. */
11959 /* This tries to wait until the frame is really visible.
11960 However, if the window manager asks the user where to position
11961 the frame, this will return before the user finishes doing that.
11962 The frame will not actually be visible at that time,
11963 but it will become visible later when the window manager
11964 finishes with it. */
11966 void
11967 x_make_frame_visible (f)
11968 struct frame *f;
11970 Lisp_Object type;
11971 int original_top, original_left;
11972 int retry_count = 2;
11974 retry:
11976 BLOCK_INPUT;
11978 type = x_icon_type (f);
11979 if (!NILP (type))
11980 x_bitmap_icon (f, type);
11982 if (! FRAME_VISIBLE_P (f))
11984 /* We test FRAME_GARBAGED_P here to make sure we don't
11985 call x_set_offset a second time
11986 if we get to x_make_frame_visible a second time
11987 before the window gets really visible. */
11988 if (! FRAME_ICONIFIED_P (f)
11989 && ! f->output_data.x->asked_for_visible)
11990 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11992 f->output_data.x->asked_for_visible = 1;
11994 if (! EQ (Vx_no_window_manager, Qt))
11995 x_wm_set_window_state (f, NormalState);
11996 #ifdef USE_X_TOOLKIT
11997 /* This was XtPopup, but that did nothing for an iconified frame. */
11998 XtMapWidget (f->output_data.x->widget);
11999 #else /* not USE_X_TOOLKIT */
12000 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12001 #endif /* not USE_X_TOOLKIT */
12002 #if 0 /* This seems to bring back scroll bars in the wrong places
12003 if the window configuration has changed. They seem
12004 to come back ok without this. */
12005 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12006 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12007 #endif
12010 XFlush (FRAME_X_DISPLAY (f));
12012 /* Synchronize to ensure Emacs knows the frame is visible
12013 before we do anything else. We do this loop with input not blocked
12014 so that incoming events are handled. */
12016 Lisp_Object frame;
12017 int count;
12018 /* This must be before UNBLOCK_INPUT
12019 since events that arrive in response to the actions above
12020 will set it when they are handled. */
12021 int previously_visible = f->output_data.x->has_been_visible;
12023 original_left = f->output_data.x->left_pos;
12024 original_top = f->output_data.x->top_pos;
12026 /* This must come after we set COUNT. */
12027 UNBLOCK_INPUT;
12029 /* We unblock here so that arriving X events are processed. */
12031 /* Now move the window back to where it was "supposed to be".
12032 But don't do it if the gravity is negative.
12033 When the gravity is negative, this uses a position
12034 that is 3 pixels too low. Perhaps that's really the border width.
12036 Don't do this if the window has never been visible before,
12037 because the window manager may choose the position
12038 and we don't want to override it. */
12040 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12041 && f->output_data.x->win_gravity == NorthWestGravity
12042 && previously_visible)
12044 Drawable rootw;
12045 int x, y;
12046 unsigned int width, height, border, depth;
12048 BLOCK_INPUT;
12050 /* On some window managers (such as FVWM) moving an existing
12051 window, even to the same place, causes the window manager
12052 to introduce an offset. This can cause the window to move
12053 to an unexpected location. Check the geometry (a little
12054 slow here) and then verify that the window is in the right
12055 place. If the window is not in the right place, move it
12056 there, and take the potential window manager hit. */
12057 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12058 &rootw, &x, &y, &width, &height, &border, &depth);
12060 if (original_left != x || original_top != y)
12061 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12062 original_left, original_top);
12064 UNBLOCK_INPUT;
12067 XSETFRAME (frame, f);
12069 /* Wait until the frame is visible. Process X events until a
12070 MapNotify event has been seen, or until we think we won't get a
12071 MapNotify at all.. */
12072 for (count = input_signal_count + 10;
12073 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12075 /* Force processing of queued events. */
12076 x_sync (f);
12078 /* Machines that do polling rather than SIGIO have been
12079 observed to go into a busy-wait here. So we'll fake an
12080 alarm signal to let the handler know that there's something
12081 to be read. We used to raise a real alarm, but it seems
12082 that the handler isn't always enabled here. This is
12083 probably a bug. */
12084 if (input_polling_used ())
12086 /* It could be confusing if a real alarm arrives while
12087 processing the fake one. Turn it off and let the
12088 handler reset it. */
12089 extern void poll_for_input_1 P_ ((void));
12090 int old_poll_suppress_count = poll_suppress_count;
12091 poll_suppress_count = 1;
12092 poll_for_input_1 ();
12093 poll_suppress_count = old_poll_suppress_count;
12096 /* See if a MapNotify event has been processed. */
12097 FRAME_SAMPLE_VISIBILITY (f);
12100 /* 2000-09-28: In
12102 (let ((f (selected-frame)))
12103 (iconify-frame f)
12104 (raise-frame f))
12106 the frame is not raised with various window managers on
12107 FreeBSD, Linux and Solaris. It turns out that, for some
12108 unknown reason, the call to XtMapWidget is completely ignored.
12109 Mapping the widget a second time works. */
12111 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12112 goto retry;
12116 /* Change from mapped state to withdrawn state. */
12118 /* Make the frame visible (mapped and not iconified). */
12120 void
12121 x_make_frame_invisible (f)
12122 struct frame *f;
12124 Window window;
12126 #ifdef USE_X_TOOLKIT
12127 /* Use the frame's outermost window, not the one we normally draw on. */
12128 window = XtWindow (f->output_data.x->widget);
12129 #else /* not USE_X_TOOLKIT */
12130 window = FRAME_X_WINDOW (f);
12131 #endif /* not USE_X_TOOLKIT */
12133 /* Don't keep the highlight on an invisible frame. */
12134 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12135 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12137 #if 0/* This might add unreliability; I don't trust it -- rms. */
12138 if (! f->async_visible && ! f->async_iconified)
12139 return;
12140 #endif
12142 BLOCK_INPUT;
12144 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12145 that the current position of the window is user-specified, rather than
12146 program-specified, so that when the window is mapped again, it will be
12147 placed at the same location, without forcing the user to position it
12148 by hand again (they have already done that once for this window.) */
12149 x_wm_set_size_hint (f, (long) 0, 1);
12151 #ifdef HAVE_X11R4
12153 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12154 DefaultScreen (FRAME_X_DISPLAY (f))))
12156 UNBLOCK_INPUT_RESIGNAL;
12157 error ("Can't notify window manager of window withdrawal");
12159 #else /* ! defined (HAVE_X11R4) */
12161 /* Tell the window manager what we're going to do. */
12162 if (! EQ (Vx_no_window_manager, Qt))
12164 XEvent unmap;
12166 unmap.xunmap.type = UnmapNotify;
12167 unmap.xunmap.window = window;
12168 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12169 unmap.xunmap.from_configure = False;
12170 if (! XSendEvent (FRAME_X_DISPLAY (f),
12171 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12172 False,
12173 SubstructureRedirectMaskSubstructureNotifyMask,
12174 &unmap))
12176 UNBLOCK_INPUT_RESIGNAL;
12177 error ("Can't notify window manager of withdrawal");
12181 /* Unmap the window ourselves. Cheeky! */
12182 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12183 #endif /* ! defined (HAVE_X11R4) */
12185 /* We can't distinguish this from iconification
12186 just by the event that we get from the server.
12187 So we can't win using the usual strategy of letting
12188 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12189 and synchronize with the server to make sure we agree. */
12190 f->visible = 0;
12191 FRAME_ICONIFIED_P (f) = 0;
12192 f->async_visible = 0;
12193 f->async_iconified = 0;
12195 x_sync (f);
12197 UNBLOCK_INPUT;
12200 /* Change window state from mapped to iconified. */
12202 void
12203 x_iconify_frame (f)
12204 struct frame *f;
12206 int result;
12207 Lisp_Object type;
12209 /* Don't keep the highlight on an invisible frame. */
12210 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12211 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12213 if (f->async_iconified)
12214 return;
12216 BLOCK_INPUT;
12218 FRAME_SAMPLE_VISIBILITY (f);
12220 type = x_icon_type (f);
12221 if (!NILP (type))
12222 x_bitmap_icon (f, type);
12224 #ifdef USE_X_TOOLKIT
12226 if (! FRAME_VISIBLE_P (f))
12228 if (! EQ (Vx_no_window_manager, Qt))
12229 x_wm_set_window_state (f, IconicState);
12230 /* This was XtPopup, but that did nothing for an iconified frame. */
12231 XtMapWidget (f->output_data.x->widget);
12232 /* The server won't give us any event to indicate
12233 that an invisible frame was changed to an icon,
12234 so we have to record it here. */
12235 f->iconified = 1;
12236 f->visible = 1;
12237 f->async_iconified = 1;
12238 f->async_visible = 0;
12239 UNBLOCK_INPUT;
12240 return;
12243 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12244 XtWindow (f->output_data.x->widget),
12245 DefaultScreen (FRAME_X_DISPLAY (f)));
12246 UNBLOCK_INPUT;
12248 if (!result)
12249 error ("Can't notify window manager of iconification");
12251 f->async_iconified = 1;
12252 f->async_visible = 0;
12255 BLOCK_INPUT;
12256 XFlush (FRAME_X_DISPLAY (f));
12257 UNBLOCK_INPUT;
12258 #else /* not USE_X_TOOLKIT */
12260 /* Make sure the X server knows where the window should be positioned,
12261 in case the user deiconifies with the window manager. */
12262 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12263 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12265 /* Since we don't know which revision of X we're running, we'll use both
12266 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12268 /* X11R4: send a ClientMessage to the window manager using the
12269 WM_CHANGE_STATE type. */
12271 XEvent message;
12273 message.xclient.window = FRAME_X_WINDOW (f);
12274 message.xclient.type = ClientMessage;
12275 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12276 message.xclient.format = 32;
12277 message.xclient.data.l[0] = IconicState;
12279 if (! XSendEvent (FRAME_X_DISPLAY (f),
12280 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12281 False,
12282 SubstructureRedirectMask | SubstructureNotifyMask,
12283 &message))
12285 UNBLOCK_INPUT_RESIGNAL;
12286 error ("Can't notify window manager of iconification");
12290 /* X11R3: set the initial_state field of the window manager hints to
12291 IconicState. */
12292 x_wm_set_window_state (f, IconicState);
12294 if (!FRAME_VISIBLE_P (f))
12296 /* If the frame was withdrawn, before, we must map it. */
12297 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12300 f->async_iconified = 1;
12301 f->async_visible = 0;
12303 XFlush (FRAME_X_DISPLAY (f));
12304 UNBLOCK_INPUT;
12305 #endif /* not USE_X_TOOLKIT */
12308 /* Destroy the X window of frame F. */
12310 void
12311 x_destroy_window (f)
12312 struct frame *f;
12314 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12316 BLOCK_INPUT;
12318 /* If a display connection is dead, don't try sending more
12319 commands to the X server. */
12320 if (dpyinfo->display != 0)
12322 if (f->output_data.x->icon_desc != 0)
12323 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12324 #ifdef HAVE_X_I18N
12325 if (FRAME_XIC (f))
12326 free_frame_xic (f);
12327 #endif
12328 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
12329 #ifdef USE_X_TOOLKIT
12330 if (f->output_data.x->widget)
12331 XtDestroyWidget (f->output_data.x->widget);
12332 free_frame_menubar (f);
12333 #endif /* USE_X_TOOLKIT */
12335 unload_color (f, f->output_data.x->foreground_pixel);
12336 unload_color (f, f->output_data.x->background_pixel);
12337 unload_color (f, f->output_data.x->cursor_pixel);
12338 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12339 unload_color (f, f->output_data.x->border_pixel);
12340 unload_color (f, f->output_data.x->mouse_pixel);
12341 if (f->output_data.x->scroll_bar_background_pixel != -1)
12342 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12343 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12344 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12345 if (f->output_data.x->white_relief.allocated_p)
12346 unload_color (f, f->output_data.x->white_relief.pixel);
12347 if (f->output_data.x->black_relief.allocated_p)
12348 unload_color (f, f->output_data.x->black_relief.pixel);
12350 free_frame_faces (f);
12351 XFlush (FRAME_X_DISPLAY (f));
12354 if (f->output_data.x->saved_menu_event)
12355 xfree (f->output_data.x->saved_menu_event);
12357 xfree (f->output_data.x);
12358 f->output_data.x = 0;
12359 if (f == dpyinfo->x_focus_frame)
12360 dpyinfo->x_focus_frame = 0;
12361 if (f == dpyinfo->x_focus_event_frame)
12362 dpyinfo->x_focus_event_frame = 0;
12363 if (f == dpyinfo->x_highlight_frame)
12364 dpyinfo->x_highlight_frame = 0;
12366 dpyinfo->reference_count--;
12368 if (f == dpyinfo->mouse_face_mouse_frame)
12370 dpyinfo->mouse_face_beg_row
12371 = dpyinfo->mouse_face_beg_col = -1;
12372 dpyinfo->mouse_face_end_row
12373 = dpyinfo->mouse_face_end_col = -1;
12374 dpyinfo->mouse_face_window = Qnil;
12375 dpyinfo->mouse_face_deferred_gc = 0;
12376 dpyinfo->mouse_face_mouse_frame = 0;
12379 UNBLOCK_INPUT;
12382 /* Setting window manager hints. */
12384 /* Set the normal size hints for the window manager, for frame F.
12385 FLAGS is the flags word to use--or 0 meaning preserve the flags
12386 that the window now has.
12387 If USER_POSITION is nonzero, we set the USPosition
12388 flag (this is useful when FLAGS is 0). */
12390 void
12391 x_wm_set_size_hint (f, flags, user_position)
12392 struct frame *f;
12393 long flags;
12394 int user_position;
12396 XSizeHints size_hints;
12398 #ifdef USE_X_TOOLKIT
12399 Arg al[2];
12400 int ac = 0;
12401 Dimension widget_width, widget_height;
12402 Window window = XtWindow (f->output_data.x->widget);
12403 #else /* not USE_X_TOOLKIT */
12404 Window window = FRAME_X_WINDOW (f);
12405 #endif /* not USE_X_TOOLKIT */
12407 /* Setting PMaxSize caused various problems. */
12408 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12410 size_hints.x = f->output_data.x->left_pos;
12411 size_hints.y = f->output_data.x->top_pos;
12413 #ifdef USE_X_TOOLKIT
12414 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12415 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12416 XtGetValues (f->output_data.x->widget, al, ac);
12417 size_hints.height = widget_height;
12418 size_hints.width = widget_width;
12419 #else /* not USE_X_TOOLKIT */
12420 size_hints.height = PIXEL_HEIGHT (f);
12421 size_hints.width = PIXEL_WIDTH (f);
12422 #endif /* not USE_X_TOOLKIT */
12424 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12425 size_hints.height_inc = f->output_data.x->line_height;
12426 size_hints.max_width
12427 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12428 size_hints.max_height
12429 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12431 /* Calculate the base and minimum sizes.
12433 (When we use the X toolkit, we don't do it here.
12434 Instead we copy the values that the widgets are using, below.) */
12435 #ifndef USE_X_TOOLKIT
12437 int base_width, base_height;
12438 int min_rows = 0, min_cols = 0;
12440 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12441 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12443 check_frame_size (f, &min_rows, &min_cols);
12445 /* The window manager uses the base width hints to calculate the
12446 current number of rows and columns in the frame while
12447 resizing; min_width and min_height aren't useful for this
12448 purpose, since they might not give the dimensions for a
12449 zero-row, zero-column frame.
12451 We use the base_width and base_height members if we have
12452 them; otherwise, we set the min_width and min_height members
12453 to the size for a zero x zero frame. */
12455 #ifdef HAVE_X11R4
12456 size_hints.flags |= PBaseSize;
12457 size_hints.base_width = base_width;
12458 size_hints.base_height = base_height;
12459 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12460 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12461 #else
12462 size_hints.min_width = base_width;
12463 size_hints.min_height = base_height;
12464 #endif
12467 /* If we don't need the old flags, we don't need the old hint at all. */
12468 if (flags)
12470 size_hints.flags |= flags;
12471 goto no_read;
12473 #endif /* not USE_X_TOOLKIT */
12476 XSizeHints hints; /* Sometimes I hate X Windows... */
12477 long supplied_return;
12478 int value;
12480 #ifdef HAVE_X11R4
12481 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12482 &supplied_return);
12483 #else
12484 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12485 #endif
12487 #ifdef USE_X_TOOLKIT
12488 size_hints.base_height = hints.base_height;
12489 size_hints.base_width = hints.base_width;
12490 size_hints.min_height = hints.min_height;
12491 size_hints.min_width = hints.min_width;
12492 #endif
12494 if (flags)
12495 size_hints.flags |= flags;
12496 else
12498 if (value == 0)
12499 hints.flags = 0;
12500 if (hints.flags & PSize)
12501 size_hints.flags |= PSize;
12502 if (hints.flags & PPosition)
12503 size_hints.flags |= PPosition;
12504 if (hints.flags & USPosition)
12505 size_hints.flags |= USPosition;
12506 if (hints.flags & USSize)
12507 size_hints.flags |= USSize;
12511 #ifndef USE_X_TOOLKIT
12512 no_read:
12513 #endif
12515 #ifdef PWinGravity
12516 size_hints.win_gravity = f->output_data.x->win_gravity;
12517 size_hints.flags |= PWinGravity;
12519 if (user_position)
12521 size_hints.flags &= ~ PPosition;
12522 size_hints.flags |= USPosition;
12524 #endif /* PWinGravity */
12526 #ifdef HAVE_X11R4
12527 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12528 #else
12529 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12530 #endif
12533 /* Used for IconicState or NormalState */
12535 void
12536 x_wm_set_window_state (f, state)
12537 struct frame *f;
12538 int state;
12540 #ifdef USE_X_TOOLKIT
12541 Arg al[1];
12543 XtSetArg (al[0], XtNinitialState, state);
12544 XtSetValues (f->output_data.x->widget, al, 1);
12545 #else /* not USE_X_TOOLKIT */
12546 Window window = FRAME_X_WINDOW (f);
12548 f->output_data.x->wm_hints.flags |= StateHint;
12549 f->output_data.x->wm_hints.initial_state = state;
12551 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12552 #endif /* not USE_X_TOOLKIT */
12555 void
12556 x_wm_set_icon_pixmap (f, pixmap_id)
12557 struct frame *f;
12558 int pixmap_id;
12560 Pixmap icon_pixmap;
12562 #ifndef USE_X_TOOLKIT
12563 Window window = FRAME_X_WINDOW (f);
12564 #endif
12566 if (pixmap_id > 0)
12568 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12569 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12571 else
12573 /* It seems there is no way to turn off use of an icon pixmap.
12574 The following line does it, only if no icon has yet been created,
12575 for some window managers. But with mwm it crashes.
12576 Some people say it should clear the IconPixmapHint bit in this case,
12577 but that doesn't work, and the X consortium said it isn't the
12578 right thing at all. Since there is no way to win,
12579 best to explicitly give up. */
12580 #if 0
12581 f->output_data.x->wm_hints.icon_pixmap = None;
12582 #else
12583 return;
12584 #endif
12587 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12590 Arg al[1];
12591 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12592 XtSetValues (f->output_data.x->widget, al, 1);
12595 #else /* not USE_X_TOOLKIT */
12597 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12598 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12600 #endif /* not USE_X_TOOLKIT */
12603 void
12604 x_wm_set_icon_position (f, icon_x, icon_y)
12605 struct frame *f;
12606 int icon_x, icon_y;
12608 #ifdef USE_X_TOOLKIT
12609 Window window = XtWindow (f->output_data.x->widget);
12610 #else
12611 Window window = FRAME_X_WINDOW (f);
12612 #endif
12614 f->output_data.x->wm_hints.flags |= IconPositionHint;
12615 f->output_data.x->wm_hints.icon_x = icon_x;
12616 f->output_data.x->wm_hints.icon_y = icon_y;
12618 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12622 /***********************************************************************
12623 Fonts
12624 ***********************************************************************/
12626 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12628 struct font_info *
12629 x_get_font_info (f, font_idx)
12630 FRAME_PTR f;
12631 int font_idx;
12633 return (FRAME_X_FONT_TABLE (f) + font_idx);
12637 /* Return a list of names of available fonts matching PATTERN on frame
12638 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12639 to be listed. Frame F NULL means we have not yet created any
12640 frame on X, and consult the first display in x_display_list.
12641 MAXNAMES sets a limit on how many fonts to match. */
12643 Lisp_Object
12644 x_list_fonts (f, pattern, size, maxnames)
12645 FRAME_PTR f;
12646 Lisp_Object pattern;
12647 int size;
12648 int maxnames;
12650 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12651 Lisp_Object tem, second_best;
12652 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12653 int try_XLoadQueryFont = 0;
12654 int count;
12656 patterns = Fassoc (pattern, Valternate_fontname_alist);
12657 if (NILP (patterns))
12658 patterns = Fcons (pattern, Qnil);
12660 if (maxnames == 1 && !size)
12661 /* We can return any single font matching PATTERN. */
12662 try_XLoadQueryFont = 1;
12664 for (; CONSP (patterns); patterns = XCDR (patterns))
12666 int num_fonts;
12667 char **names = NULL;
12669 pattern = XCAR (patterns);
12670 /* See if we cached the result for this particular query.
12671 The cache is an alist of the form:
12672 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12674 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12675 key = Fcons (pattern, make_number (maxnames)),
12676 !NILP (list = Fassoc (key, tem))))
12678 list = Fcdr_safe (list);
12679 /* We have a cashed list. Don't have to get the list again. */
12680 goto label_cached;
12683 /* At first, put PATTERN in the cache. */
12685 BLOCK_INPUT;
12686 count = x_catch_errors (dpy);
12688 if (try_XLoadQueryFont)
12690 XFontStruct *font;
12691 unsigned long value;
12693 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12694 if (x_had_errors_p (dpy))
12696 /* This error is perhaps due to insufficient memory on X
12697 server. Let's just ignore it. */
12698 font = NULL;
12699 x_clear_errors (dpy);
12702 if (font
12703 && XGetFontProperty (font, XA_FONT, &value))
12705 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12706 int len = strlen (name);
12707 char *tmp;
12709 /* If DXPC (a Differential X Protocol Compressor)
12710 Ver.3.7 is running, XGetAtomName will return null
12711 string. We must avoid such a name. */
12712 if (len == 0)
12713 try_XLoadQueryFont = 0;
12714 else
12716 num_fonts = 1;
12717 names = (char **) alloca (sizeof (char *));
12718 /* Some systems only allow alloca assigned to a
12719 simple var. */
12720 tmp = (char *) alloca (len + 1); names[0] = tmp;
12721 bcopy (name, names[0], len + 1);
12722 XFree (name);
12725 else
12726 try_XLoadQueryFont = 0;
12728 if (font)
12729 XFreeFont (dpy, font);
12732 if (!try_XLoadQueryFont)
12734 /* We try at least 10 fonts because XListFonts will return
12735 auto-scaled fonts at the head. */
12736 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12737 &num_fonts);
12738 if (x_had_errors_p (dpy))
12740 /* This error is perhaps due to insufficient memory on X
12741 server. Let's just ignore it. */
12742 names = NULL;
12743 x_clear_errors (dpy);
12747 x_uncatch_errors (dpy, count);
12748 UNBLOCK_INPUT;
12750 if (names)
12752 int i;
12754 /* Make a list of all the fonts we got back.
12755 Store that in the font cache for the display. */
12756 for (i = 0; i < num_fonts; i++)
12758 int width = 0;
12759 char *p = names[i];
12760 int average_width = -1, dashes = 0;
12762 /* Count the number of dashes in NAMES[I]. If there are
12763 14 dashes, and the field value following 12th dash
12764 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12765 is usually too ugly to be used for editing. Let's
12766 ignore it. */
12767 while (*p)
12768 if (*p++ == '-')
12770 dashes++;
12771 if (dashes == 7) /* PIXEL_SIZE field */
12772 width = atoi (p);
12773 else if (dashes == 12) /* AVERAGE_WIDTH field */
12774 average_width = atoi (p);
12776 if (dashes < 14 || average_width != 0)
12778 tem = build_string (names[i]);
12779 if (NILP (Fassoc (tem, list)))
12781 if (STRINGP (Vx_pixel_size_width_font_regexp)
12782 && ((fast_c_string_match_ignore_case
12783 (Vx_pixel_size_width_font_regexp, names[i]))
12784 >= 0))
12785 /* We can set the value of PIXEL_SIZE to the
12786 width of this font. */
12787 list = Fcons (Fcons (tem, make_number (width)), list);
12788 else
12789 /* For the moment, width is not known. */
12790 list = Fcons (Fcons (tem, Qnil), list);
12794 if (!try_XLoadQueryFont)
12795 XFreeFontNames (names);
12798 /* Now store the result in the cache. */
12799 if (f != NULL)
12800 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12801 = Fcons (Fcons (key, list),
12802 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12804 label_cached:
12805 if (NILP (list)) continue; /* Try the remaining alternatives. */
12807 newlist = second_best = Qnil;
12808 /* Make a list of the fonts that have the right width. */
12809 for (; CONSP (list); list = XCDR (list))
12811 int found_size;
12813 tem = XCAR (list);
12815 if (!CONSP (tem) || NILP (XCAR (tem)))
12816 continue;
12817 if (!size)
12819 newlist = Fcons (XCAR (tem), newlist);
12820 continue;
12823 if (!INTEGERP (XCDR (tem)))
12825 /* Since we have not yet known the size of this font, we
12826 must try slow function call XLoadQueryFont. */
12827 XFontStruct *thisinfo;
12829 BLOCK_INPUT;
12830 count = x_catch_errors (dpy);
12831 thisinfo = XLoadQueryFont (dpy,
12832 XSTRING (XCAR (tem))->data);
12833 if (x_had_errors_p (dpy))
12835 /* This error is perhaps due to insufficient memory on X
12836 server. Let's just ignore it. */
12837 thisinfo = NULL;
12838 x_clear_errors (dpy);
12840 x_uncatch_errors (dpy, count);
12841 UNBLOCK_INPUT;
12843 if (thisinfo)
12845 XCDR (tem)
12846 = (thisinfo->min_bounds.width == 0
12847 ? make_number (0)
12848 : make_number (thisinfo->max_bounds.width));
12849 XFreeFont (dpy, thisinfo);
12851 else
12852 /* For unknown reason, the previous call of XListFont had
12853 returned a font which can't be opened. Record the size
12854 as 0 not to try to open it again. */
12855 XCDR (tem) = make_number (0);
12858 found_size = XINT (XCDR (tem));
12859 if (found_size == size)
12860 newlist = Fcons (XCAR (tem), newlist);
12861 else if (found_size > 0)
12863 if (NILP (second_best))
12864 second_best = tem;
12865 else if (found_size < size)
12867 if (XINT (XCDR (second_best)) > size
12868 || XINT (XCDR (second_best)) < found_size)
12869 second_best = tem;
12871 else
12873 if (XINT (XCDR (second_best)) > size
12874 && XINT (XCDR (second_best)) > found_size)
12875 second_best = tem;
12879 if (!NILP (newlist))
12880 break;
12881 else if (!NILP (second_best))
12883 newlist = Fcons (XCAR (second_best), Qnil);
12884 break;
12888 return newlist;
12892 #if GLYPH_DEBUG
12894 /* Check that FONT is valid on frame F. It is if it can be found in F's
12895 font table. */
12897 static void
12898 x_check_font (f, font)
12899 struct frame *f;
12900 XFontStruct *font;
12902 int i;
12903 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12905 xassert (font != NULL);
12907 for (i = 0; i < dpyinfo->n_fonts; i++)
12908 if (dpyinfo->font_table[i].name
12909 && font == dpyinfo->font_table[i].font)
12910 break;
12912 xassert (i < dpyinfo->n_fonts);
12915 #endif /* GLYPH_DEBUG != 0 */
12917 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12918 Note: There are (broken) X fonts out there with invalid XFontStruct
12919 min_bounds contents. For example, handa@etl.go.jp reports that
12920 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12921 have font->min_bounds.width == 0. */
12923 static INLINE void
12924 x_font_min_bounds (font, w, h)
12925 XFontStruct *font;
12926 int *w, *h;
12928 *h = FONT_HEIGHT (font);
12929 *w = font->min_bounds.width;
12931 /* Try to handle the case where FONT->min_bounds has invalid
12932 contents. Since the only font known to have invalid min_bounds
12933 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12934 if (*w <= 0)
12935 *w = font->max_bounds.width;
12939 /* Compute the smallest character width and smallest font height over
12940 all fonts available on frame F. Set the members smallest_char_width
12941 and smallest_font_height in F's x_display_info structure to
12942 the values computed. Value is non-zero if smallest_font_height or
12943 smallest_char_width become smaller than they were before. */
12945 static int
12946 x_compute_min_glyph_bounds (f)
12947 struct frame *f;
12949 int i;
12950 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12951 XFontStruct *font;
12952 int old_width = dpyinfo->smallest_char_width;
12953 int old_height = dpyinfo->smallest_font_height;
12955 dpyinfo->smallest_font_height = 100000;
12956 dpyinfo->smallest_char_width = 100000;
12958 for (i = 0; i < dpyinfo->n_fonts; ++i)
12959 if (dpyinfo->font_table[i].name)
12961 struct font_info *fontp = dpyinfo->font_table + i;
12962 int w, h;
12964 font = (XFontStruct *) fontp->font;
12965 xassert (font != (XFontStruct *) ~0);
12966 x_font_min_bounds (font, &w, &h);
12968 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12969 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12972 xassert (dpyinfo->smallest_char_width > 0
12973 && dpyinfo->smallest_font_height > 0);
12975 return (dpyinfo->n_fonts == 1
12976 || dpyinfo->smallest_char_width < old_width
12977 || dpyinfo->smallest_font_height < old_height);
12981 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12982 pointer to the structure font_info while allocating it dynamically.
12983 If SIZE is 0, load any size of font.
12984 If loading is failed, return NULL. */
12986 struct font_info *
12987 x_load_font (f, fontname, size)
12988 struct frame *f;
12989 register char *fontname;
12990 int size;
12992 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12993 Lisp_Object font_names;
12994 int count;
12996 /* Get a list of all the fonts that match this name. Once we
12997 have a list of matching fonts, we compare them against the fonts
12998 we already have by comparing names. */
12999 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13001 if (!NILP (font_names))
13003 Lisp_Object tail;
13004 int i;
13006 for (i = 0; i < dpyinfo->n_fonts; i++)
13007 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13008 if (dpyinfo->font_table[i].name
13009 && (!strcmp (dpyinfo->font_table[i].name,
13010 XSTRING (XCAR (tail))->data)
13011 || !strcmp (dpyinfo->font_table[i].full_name,
13012 XSTRING (XCAR (tail))->data)))
13013 return (dpyinfo->font_table + i);
13016 /* Load the font and add it to the table. */
13018 char *full_name;
13019 XFontStruct *font;
13020 struct font_info *fontp;
13021 unsigned long value;
13022 int i;
13024 /* If we have found fonts by x_list_font, load one of them. If
13025 not, we still try to load a font by the name given as FONTNAME
13026 because XListFonts (called in x_list_font) of some X server has
13027 a bug of not finding a font even if the font surely exists and
13028 is loadable by XLoadQueryFont. */
13029 if (size > 0 && !NILP (font_names))
13030 fontname = (char *) XSTRING (XCAR (font_names))->data;
13032 BLOCK_INPUT;
13033 count = x_catch_errors (FRAME_X_DISPLAY (f));
13034 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13035 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13037 /* This error is perhaps due to insufficient memory on X
13038 server. Let's just ignore it. */
13039 font = NULL;
13040 x_clear_errors (FRAME_X_DISPLAY (f));
13042 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13043 UNBLOCK_INPUT;
13044 if (!font)
13045 return NULL;
13047 /* Find a free slot in the font table. */
13048 for (i = 0; i < dpyinfo->n_fonts; ++i)
13049 if (dpyinfo->font_table[i].name == NULL)
13050 break;
13052 /* If no free slot found, maybe enlarge the font table. */
13053 if (i == dpyinfo->n_fonts
13054 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13056 int sz;
13057 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13058 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13059 dpyinfo->font_table
13060 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13063 fontp = dpyinfo->font_table + i;
13064 if (i == dpyinfo->n_fonts)
13065 ++dpyinfo->n_fonts;
13067 /* Now fill in the slots of *FONTP. */
13068 BLOCK_INPUT;
13069 fontp->font = font;
13070 fontp->font_idx = i;
13071 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13072 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13074 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13075 full_name = 0;
13076 if (XGetFontProperty (font, XA_FONT, &value))
13078 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13079 char *p = name;
13080 int dashes = 0;
13082 /* Count the number of dashes in the "full name".
13083 If it is too few, this isn't really the font's full name,
13084 so don't use it.
13085 In X11R4, the fonts did not come with their canonical names
13086 stored in them. */
13087 while (*p)
13089 if (*p == '-')
13090 dashes++;
13091 p++;
13094 if (dashes >= 13)
13096 full_name = (char *) xmalloc (p - name + 1);
13097 bcopy (name, full_name, p - name + 1);
13100 XFree (name);
13103 if (full_name != 0)
13104 fontp->full_name = full_name;
13105 else
13106 fontp->full_name = fontp->name;
13108 fontp->size = font->max_bounds.width;
13109 fontp->height = FONT_HEIGHT (font);
13111 /* For some font, ascent and descent in max_bounds field is
13112 larger than the above value. */
13113 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
13114 if (max_height > fontp->height)
13115 fontp->height = max_height;
13118 if (NILP (font_names))
13120 /* We come here because of a bug of XListFonts mentioned at
13121 the head of this block. Let's store this information in
13122 the cache for x_list_fonts. */
13123 Lisp_Object lispy_name = build_string (fontname);
13124 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13126 XCDR (dpyinfo->name_list_element)
13127 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
13128 Fcons (Fcons (lispy_full_name,
13129 make_number (fontp->size)),
13130 Qnil)),
13131 XCDR (dpyinfo->name_list_element));
13132 if (full_name)
13133 XCDR (dpyinfo->name_list_element)
13134 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13135 Fcons (Fcons (lispy_full_name,
13136 make_number (fontp->size)),
13137 Qnil)),
13138 XCDR (dpyinfo->name_list_element));
13141 /* The slot `encoding' specifies how to map a character
13142 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13143 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13144 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13145 2:0xA020..0xFF7F). For the moment, we don't know which charset
13146 uses this font. So, we set information in fontp->encoding[1]
13147 which is never used by any charset. If mapping can't be
13148 decided, set FONT_ENCODING_NOT_DECIDED. */
13149 fontp->encoding[1]
13150 = (font->max_byte1 == 0
13151 /* 1-byte font */
13152 ? (font->min_char_or_byte2 < 0x80
13153 ? (font->max_char_or_byte2 < 0x80
13154 ? 0 /* 0x20..0x7F */
13155 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13156 : 1) /* 0xA0..0xFF */
13157 /* 2-byte font */
13158 : (font->min_byte1 < 0x80
13159 ? (font->max_byte1 < 0x80
13160 ? (font->min_char_or_byte2 < 0x80
13161 ? (font->max_char_or_byte2 < 0x80
13162 ? 0 /* 0x2020..0x7F7F */
13163 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13164 : 3) /* 0x20A0..0x7FFF */
13165 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13166 : (font->min_char_or_byte2 < 0x80
13167 ? (font->max_char_or_byte2 < 0x80
13168 ? 2 /* 0xA020..0xFF7F */
13169 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13170 : 1))); /* 0xA0A0..0xFFFF */
13172 fontp->baseline_offset
13173 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13174 ? (long) value : 0);
13175 fontp->relative_compose
13176 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13177 ? (long) value : 0);
13178 fontp->default_ascent
13179 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13180 ? (long) value : 0);
13182 /* Set global flag fonts_changed_p to non-zero if the font loaded
13183 has a character with a smaller width than any other character
13184 before, or if the font loaded has a smalle>r height than any
13185 other font loaded before. If this happens, it will make a
13186 glyph matrix reallocation necessary. */
13187 fonts_changed_p = x_compute_min_glyph_bounds (f);
13188 UNBLOCK_INPUT;
13189 return fontp;
13194 /* Return a pointer to struct font_info of a font named FONTNAME for
13195 frame F. If no such font is loaded, return NULL. */
13197 struct font_info *
13198 x_query_font (f, fontname)
13199 struct frame *f;
13200 register char *fontname;
13202 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13203 int i;
13205 for (i = 0; i < dpyinfo->n_fonts; i++)
13206 if (dpyinfo->font_table[i].name
13207 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13208 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13209 return (dpyinfo->font_table + i);
13210 return NULL;
13214 /* Find a CCL program for a font specified by FONTP, and set the member
13215 `encoder' of the structure. */
13217 void
13218 x_find_ccl_program (fontp)
13219 struct font_info *fontp;
13221 Lisp_Object list, elt;
13223 elt = Qnil;
13224 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13226 elt = XCAR (list);
13227 if (CONSP (elt)
13228 && STRINGP (XCAR (elt))
13229 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13230 >= 0)
13231 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13232 >= 0)))
13233 break;
13236 if (! NILP (list))
13238 struct ccl_program *ccl
13239 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13241 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13242 xfree (ccl);
13243 else
13244 fontp->font_encoder = ccl;
13250 /***********************************************************************
13251 Initialization
13252 ***********************************************************************/
13254 #ifdef USE_X_TOOLKIT
13255 static XrmOptionDescRec emacs_options[] = {
13256 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13257 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13259 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13260 XrmoptionSepArg, NULL},
13261 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13263 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13264 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13265 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13266 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13267 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13268 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13269 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13271 #endif /* USE_X_TOOLKIT */
13273 static int x_initialized;
13275 #ifdef MULTI_KBOARD
13276 /* Test whether two display-name strings agree up to the dot that separates
13277 the screen number from the server number. */
13278 static int
13279 same_x_server (name1, name2)
13280 char *name1, *name2;
13282 int seen_colon = 0;
13283 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13284 int system_name_length = strlen (system_name);
13285 int length_until_period = 0;
13287 while (system_name[length_until_period] != 0
13288 && system_name[length_until_period] != '.')
13289 length_until_period++;
13291 /* Treat `unix' like an empty host name. */
13292 if (! strncmp (name1, "unix:", 5))
13293 name1 += 4;
13294 if (! strncmp (name2, "unix:", 5))
13295 name2 += 4;
13296 /* Treat this host's name like an empty host name. */
13297 if (! strncmp (name1, system_name, system_name_length)
13298 && name1[system_name_length] == ':')
13299 name1 += system_name_length;
13300 if (! strncmp (name2, system_name, system_name_length)
13301 && name2[system_name_length] == ':')
13302 name2 += system_name_length;
13303 /* Treat this host's domainless name like an empty host name. */
13304 if (! strncmp (name1, system_name, length_until_period)
13305 && name1[length_until_period] == ':')
13306 name1 += length_until_period;
13307 if (! strncmp (name2, system_name, length_until_period)
13308 && name2[length_until_period] == ':')
13309 name2 += length_until_period;
13311 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13313 if (*name1 == ':')
13314 seen_colon++;
13315 if (seen_colon && *name1 == '.')
13316 return 1;
13318 return (seen_colon
13319 && (*name1 == '.' || *name1 == '\0')
13320 && (*name2 == '.' || *name2 == '\0'));
13322 #endif
13324 struct x_display_info *
13325 x_term_init (display_name, xrm_option, resource_name)
13326 Lisp_Object display_name;
13327 char *xrm_option;
13328 char *resource_name;
13330 int connection;
13331 Display *dpy;
13332 struct x_display_info *dpyinfo;
13333 XrmDatabase xrdb;
13335 BLOCK_INPUT;
13337 if (!x_initialized)
13339 x_initialize ();
13340 x_initialized = 1;
13343 #ifdef USE_X_TOOLKIT
13344 /* weiner@footloose.sps.mot.com reports that this causes
13345 errors with X11R5:
13346 X protocol error: BadAtom (invalid Atom parameter)
13347 on protocol request 18skiloaf.
13348 So let's not use it until R6. */
13349 #ifdef HAVE_X11XTR6
13350 XtSetLanguageProc (NULL, NULL, NULL);
13351 #endif
13354 int argc = 0;
13355 char *argv[3];
13357 argv[0] = "";
13358 argc = 1;
13359 if (xrm_option)
13361 argv[argc++] = "-xrm";
13362 argv[argc++] = xrm_option;
13364 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13365 resource_name, EMACS_CLASS,
13366 emacs_options, XtNumber (emacs_options),
13367 &argc, argv);
13369 #ifdef HAVE_X11XTR6
13370 /* I think this is to compensate for XtSetLanguageProc. */
13371 fixup_locale ();
13372 #endif
13375 #else /* not USE_X_TOOLKIT */
13376 #ifdef HAVE_X11R5
13377 XSetLocaleModifiers ("");
13378 #endif
13379 dpy = XOpenDisplay (XSTRING (display_name)->data);
13380 #endif /* not USE_X_TOOLKIT */
13382 /* Detect failure. */
13383 if (dpy == 0)
13385 UNBLOCK_INPUT;
13386 return 0;
13389 /* We have definitely succeeded. Record the new connection. */
13391 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13392 bzero (dpyinfo, sizeof *dpyinfo);
13394 #ifdef MULTI_KBOARD
13396 struct x_display_info *share;
13397 Lisp_Object tail;
13399 for (share = x_display_list, tail = x_display_name_list; share;
13400 share = share->next, tail = XCDR (tail))
13401 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13402 XSTRING (display_name)->data))
13403 break;
13404 if (share)
13405 dpyinfo->kboard = share->kboard;
13406 else
13408 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13409 init_kboard (dpyinfo->kboard);
13410 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13412 char *vendor = ServerVendor (dpy);
13413 UNBLOCK_INPUT;
13414 dpyinfo->kboard->Vsystem_key_alist
13415 = call1 (Qvendor_specific_keysyms,
13416 build_string (vendor ? vendor : ""));
13417 BLOCK_INPUT;
13420 dpyinfo->kboard->next_kboard = all_kboards;
13421 all_kboards = dpyinfo->kboard;
13422 /* Don't let the initial kboard remain current longer than necessary.
13423 That would cause problems if a file loaded on startup tries to
13424 prompt in the mini-buffer. */
13425 if (current_kboard == initial_kboard)
13426 current_kboard = dpyinfo->kboard;
13428 dpyinfo->kboard->reference_count++;
13430 #endif
13432 /* Put this display on the chain. */
13433 dpyinfo->next = x_display_list;
13434 x_display_list = dpyinfo;
13436 /* Put it on x_display_name_list as well, to keep them parallel. */
13437 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13438 x_display_name_list);
13439 dpyinfo->name_list_element = XCAR (x_display_name_list);
13441 dpyinfo->display = dpy;
13443 #if 0
13444 XSetAfterFunction (x_current_display, x_trace_wire);
13445 #endif /* ! 0 */
13447 dpyinfo->x_id_name
13448 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13449 + STRING_BYTES (XSTRING (Vsystem_name))
13450 + 2);
13451 sprintf (dpyinfo->x_id_name, "%s@%s",
13452 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13454 /* Figure out which modifier bits mean what. */
13455 x_find_modifier_meanings (dpyinfo);
13457 /* Get the scroll bar cursor. */
13458 dpyinfo->vertical_scroll_bar_cursor
13459 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13461 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13462 resource_name, EMACS_CLASS);
13463 #ifdef HAVE_XRMSETDATABASE
13464 XrmSetDatabase (dpyinfo->display, xrdb);
13465 #else
13466 dpyinfo->display->db = xrdb;
13467 #endif
13468 /* Put the rdb where we can find it in a way that works on
13469 all versions. */
13470 dpyinfo->xrdb = xrdb;
13472 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13473 DefaultScreen (dpyinfo->display));
13474 select_visual (dpyinfo);
13475 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13476 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13477 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13478 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13479 dpyinfo->grabbed = 0;
13480 dpyinfo->reference_count = 0;
13481 dpyinfo->icon_bitmap_id = -1;
13482 dpyinfo->font_table = NULL;
13483 dpyinfo->n_fonts = 0;
13484 dpyinfo->font_table_size = 0;
13485 dpyinfo->bitmaps = 0;
13486 dpyinfo->bitmaps_size = 0;
13487 dpyinfo->bitmaps_last = 0;
13488 dpyinfo->scratch_cursor_gc = 0;
13489 dpyinfo->mouse_face_mouse_frame = 0;
13490 dpyinfo->mouse_face_deferred_gc = 0;
13491 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13492 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13493 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13494 dpyinfo->mouse_face_window = Qnil;
13495 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13496 dpyinfo->mouse_face_defer = 0;
13497 dpyinfo->x_focus_frame = 0;
13498 dpyinfo->x_focus_event_frame = 0;
13499 dpyinfo->x_highlight_frame = 0;
13500 dpyinfo->image_cache = make_image_cache ();
13502 /* See if a private colormap is requested. */
13503 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13505 if (dpyinfo->visual->class == PseudoColor)
13507 Lisp_Object value;
13508 value = display_x_get_resource (dpyinfo,
13509 build_string ("privateColormap"),
13510 build_string ("PrivateColormap"),
13511 Qnil, Qnil);
13512 if (STRINGP (value)
13513 && (!strcmp (XSTRING (value)->data, "true")
13514 || !strcmp (XSTRING (value)->data, "on")))
13515 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13518 else
13519 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13520 dpyinfo->visual, AllocNone);
13523 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13524 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13525 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13526 dpyinfo->resy = pixels * 25.4 / mm;
13527 pixels = DisplayWidth (dpyinfo->display, screen_number);
13528 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13529 dpyinfo->resx = pixels * 25.4 / mm;
13532 dpyinfo->Xatom_wm_protocols
13533 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13534 dpyinfo->Xatom_wm_take_focus
13535 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13536 dpyinfo->Xatom_wm_save_yourself
13537 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13538 dpyinfo->Xatom_wm_delete_window
13539 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13540 dpyinfo->Xatom_wm_change_state
13541 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13542 dpyinfo->Xatom_wm_configure_denied
13543 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13544 dpyinfo->Xatom_wm_window_moved
13545 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13546 dpyinfo->Xatom_editres
13547 = XInternAtom (dpyinfo->display, "Editres", False);
13548 dpyinfo->Xatom_CLIPBOARD
13549 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13550 dpyinfo->Xatom_TIMESTAMP
13551 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13552 dpyinfo->Xatom_TEXT
13553 = XInternAtom (dpyinfo->display, "TEXT", False);
13554 dpyinfo->Xatom_COMPOUND_TEXT
13555 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13556 dpyinfo->Xatom_DELETE
13557 = XInternAtom (dpyinfo->display, "DELETE", False);
13558 dpyinfo->Xatom_MULTIPLE
13559 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13560 dpyinfo->Xatom_INCR
13561 = XInternAtom (dpyinfo->display, "INCR", False);
13562 dpyinfo->Xatom_EMACS_TMP
13563 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13564 dpyinfo->Xatom_TARGETS
13565 = XInternAtom (dpyinfo->display, "TARGETS", False);
13566 dpyinfo->Xatom_NULL
13567 = XInternAtom (dpyinfo->display, "NULL", False);
13568 dpyinfo->Xatom_ATOM_PAIR
13569 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13570 /* For properties of font. */
13571 dpyinfo->Xatom_PIXEL_SIZE
13572 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13573 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13574 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13575 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13576 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13577 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13578 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13580 /* Ghostscript support. */
13581 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13582 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13584 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13585 False);
13587 dpyinfo->cut_buffers_initialized = 0;
13589 connection = ConnectionNumber (dpyinfo->display);
13590 dpyinfo->connection = connection;
13593 char null_bits[1];
13595 null_bits[0] = 0x00;
13597 dpyinfo->null_pixel
13598 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13599 null_bits, 1, 1, (long) 0, (long) 0,
13604 extern int gray_bitmap_width, gray_bitmap_height;
13605 extern unsigned char *gray_bitmap_bits;
13606 dpyinfo->gray
13607 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13608 gray_bitmap_bits,
13609 gray_bitmap_width, gray_bitmap_height,
13610 (unsigned long) 1, (unsigned long) 0, 1);
13613 #ifdef HAVE_X_I18N
13614 xim_initialize (dpyinfo, resource_name);
13615 #endif
13617 #ifdef subprocesses
13618 /* This is only needed for distinguishing keyboard and process input. */
13619 if (connection != 0)
13620 add_keyboard_wait_descriptor (connection);
13621 #endif
13623 #ifndef F_SETOWN_BUG
13624 #ifdef F_SETOWN
13625 #ifdef F_SETOWN_SOCK_NEG
13626 /* stdin is a socket here */
13627 fcntl (connection, F_SETOWN, -getpid ());
13628 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13629 fcntl (connection, F_SETOWN, getpid ());
13630 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13631 #endif /* ! defined (F_SETOWN) */
13632 #endif /* F_SETOWN_BUG */
13634 #ifdef SIGIO
13635 if (interrupt_input)
13636 init_sigio (connection);
13637 #endif /* ! defined (SIGIO) */
13639 #ifdef USE_LUCID
13640 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13641 /* Make sure that we have a valid font for dialog boxes
13642 so that Xt does not crash. */
13644 Display *dpy = dpyinfo->display;
13645 XrmValue d, fr, to;
13646 Font font;
13647 int count;
13649 d.addr = (XPointer)&dpy;
13650 d.size = sizeof (Display *);
13651 fr.addr = XtDefaultFont;
13652 fr.size = sizeof (XtDefaultFont);
13653 to.size = sizeof (Font *);
13654 to.addr = (XPointer)&font;
13655 count = x_catch_errors (dpy);
13656 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13657 abort ();
13658 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13659 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13660 x_uncatch_errors (dpy, count);
13662 #endif
13663 #endif
13665 /* See if we should run in synchronous mode. This is useful
13666 for debugging X code. */
13668 Lisp_Object value;
13669 value = display_x_get_resource (dpyinfo,
13670 build_string ("synchronous"),
13671 build_string ("Synchronous"),
13672 Qnil, Qnil);
13673 if (STRINGP (value)
13674 && (!strcmp (XSTRING (value)->data, "true")
13675 || !strcmp (XSTRING (value)->data, "on")))
13676 XSynchronize (dpyinfo->display, True);
13679 UNBLOCK_INPUT;
13681 return dpyinfo;
13684 /* Get rid of display DPYINFO, assuming all frames are already gone,
13685 and without sending any more commands to the X server. */
13687 void
13688 x_delete_display (dpyinfo)
13689 struct x_display_info *dpyinfo;
13691 delete_keyboard_wait_descriptor (dpyinfo->connection);
13693 /* Discard this display from x_display_name_list and x_display_list.
13694 We can't use Fdelq because that can quit. */
13695 if (! NILP (x_display_name_list)
13696 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13697 x_display_name_list = XCDR (x_display_name_list);
13698 else
13700 Lisp_Object tail;
13702 tail = x_display_name_list;
13703 while (CONSP (tail) && CONSP (XCDR (tail)))
13705 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13707 XCDR (tail) = XCDR (XCDR (tail));
13708 break;
13710 tail = XCDR (tail);
13714 if (next_noop_dpyinfo == dpyinfo)
13715 next_noop_dpyinfo = dpyinfo->next;
13717 if (x_display_list == dpyinfo)
13718 x_display_list = dpyinfo->next;
13719 else
13721 struct x_display_info *tail;
13723 for (tail = x_display_list; tail; tail = tail->next)
13724 if (tail->next == dpyinfo)
13725 tail->next = tail->next->next;
13728 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13729 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13730 XrmDestroyDatabase (dpyinfo->xrdb);
13731 #endif
13732 #endif
13733 #ifdef MULTI_KBOARD
13734 if (--dpyinfo->kboard->reference_count == 0)
13735 delete_kboard (dpyinfo->kboard);
13736 #endif
13737 #ifdef HAVE_X_I18N
13738 if (dpyinfo->xim)
13739 xim_close_dpy (dpyinfo);
13740 #endif
13742 xfree (dpyinfo->font_table);
13743 xfree (dpyinfo->x_id_name);
13744 xfree (dpyinfo->color_cells);
13745 xfree (dpyinfo);
13749 /* Set up use of X before we make the first connection. */
13751 static struct redisplay_interface x_redisplay_interface =
13753 x_produce_glyphs,
13754 x_write_glyphs,
13755 x_insert_glyphs,
13756 x_clear_end_of_line,
13757 x_scroll_run,
13758 x_after_update_window_line,
13759 x_update_window_begin,
13760 x_update_window_end,
13761 XTcursor_to,
13762 x_flush,
13763 x_clear_mouse_face,
13764 x_get_glyph_overhangs,
13765 x_fix_overlapping_area
13768 void
13769 x_initialize ()
13771 rif = &x_redisplay_interface;
13773 clear_frame_hook = x_clear_frame;
13774 ins_del_lines_hook = x_ins_del_lines;
13775 change_line_highlight_hook = x_change_line_highlight;
13776 delete_glyphs_hook = x_delete_glyphs;
13777 ring_bell_hook = XTring_bell;
13778 reset_terminal_modes_hook = XTreset_terminal_modes;
13779 set_terminal_modes_hook = XTset_terminal_modes;
13780 update_begin_hook = x_update_begin;
13781 update_end_hook = x_update_end;
13782 set_terminal_window_hook = XTset_terminal_window;
13783 read_socket_hook = XTread_socket;
13784 frame_up_to_date_hook = XTframe_up_to_date;
13785 reassert_line_highlight_hook = XTreassert_line_highlight;
13786 mouse_position_hook = XTmouse_position;
13787 frame_rehighlight_hook = XTframe_rehighlight;
13788 frame_raise_lower_hook = XTframe_raise_lower;
13789 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13790 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13791 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13792 judge_scroll_bars_hook = XTjudge_scroll_bars;
13793 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13795 scroll_region_ok = 1; /* we'll scroll partial frames */
13796 char_ins_del_ok = 0; /* just as fast to write the line */
13797 line_ins_del_ok = 1; /* we'll just blt 'em */
13798 fast_clear_end_of_line = 1; /* X does this well */
13799 memory_below_frame = 0; /* we don't remember what scrolls
13800 off the bottom */
13801 baud_rate = 19200;
13803 x_noop_count = 0;
13804 last_tool_bar_item = -1;
13805 any_help_event_p = 0;
13807 /* Try to use interrupt input; if we can't, then start polling. */
13808 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13810 #ifdef USE_X_TOOLKIT
13811 XtToolkitInitialize ();
13812 Xt_app_con = XtCreateApplicationContext ();
13813 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13815 /* Install an asynchronous timer that processes Xt timeout events
13816 every 0.1s. This is necessary because some widget sets use
13817 timeouts internally, for example the LessTif menu bar, or the
13818 Xaw3d scroll bar. When Xt timouts aren't processed, these
13819 widgets don't behave normally. */
13821 EMACS_TIME interval;
13822 EMACS_SET_SECS_USECS (interval, 0, 100000);
13823 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13825 #endif
13827 #if USE_TOOLKIT_SCROLL_BARS
13828 xaw3d_arrow_scroll = False;
13829 xaw3d_pick_top = True;
13830 #endif
13832 /* Note that there is no real way portable across R3/R4 to get the
13833 original error handler. */
13834 XSetErrorHandler (x_error_handler);
13835 XSetIOErrorHandler (x_io_error_quitter);
13837 /* Disable Window Change signals; they are handled by X events. */
13838 #ifdef SIGWINCH
13839 signal (SIGWINCH, SIG_DFL);
13840 #endif /* ! defined (SIGWINCH) */
13842 signal (SIGPIPE, x_connection_signal);
13846 void
13847 syms_of_xterm ()
13849 staticpro (&x_error_message_string);
13850 x_error_message_string = Qnil;
13852 staticpro (&x_display_name_list);
13853 x_display_name_list = Qnil;
13855 staticpro (&last_mouse_scroll_bar);
13856 last_mouse_scroll_bar = Qnil;
13858 staticpro (&Qvendor_specific_keysyms);
13859 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13861 staticpro (&last_mouse_press_frame);
13862 last_mouse_press_frame = Qnil;
13864 help_echo = Qnil;
13865 staticpro (&help_echo);
13866 help_echo_object = Qnil;
13867 staticpro (&help_echo_object);
13868 help_echo_window = Qnil;
13869 staticpro (&help_echo_window);
13870 previous_help_echo = Qnil;
13871 staticpro (&previous_help_echo);
13872 help_echo_pos = -1;
13874 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13875 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13876 For example, if a block cursor is over a tab, it will be drawn as\n\
13877 wide as that tab on the display.");
13878 x_stretch_cursor_p = 0;
13880 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13881 "If not nil, Emacs uses toolkit scroll bars.");
13882 #if USE_TOOLKIT_SCROLL_BARS
13883 x_toolkit_scroll_bars_p = 1;
13884 #else
13885 x_toolkit_scroll_bars_p = 0;
13886 #endif
13888 staticpro (&last_mouse_motion_frame);
13889 last_mouse_motion_frame = Qnil;
13892 #endif /* not HAVE_X_WINDOWS */