Changed maintainer.
[emacs.git] / src / xterm.c
blobe2f7850829579b4bb62960ffed48ef2942bce7a3
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
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 #ifndef USG
48 /* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
50 #ifndef makedev
51 #include <sys/types.h>
52 #endif /* makedev */
53 #endif /* USG */
55 #ifdef BSD_SYSTEM
56 #include <sys/ioctl.h>
57 #endif /* ! defined (BSD_SYSTEM) */
59 #include "systty.h"
60 #include "systime.h"
62 #ifndef INCLUDED_FCNTL
63 #include <fcntl.h>
64 #endif
65 #include <ctype.h>
66 #include <errno.h>
67 #include <setjmp.h>
68 #include <sys/stat.h>
69 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70 /* #include <sys/param.h> */
72 #include "charset.h"
73 #include "ccl.h"
74 #include "frame.h"
75 #include "fontset.h"
76 #include "dispextern.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #if 0
81 #include "sink.h"
82 #include "sinkmask.h"
83 #endif /* ! 0 */
84 #include "gnu.h"
85 #include "disptab.h"
86 #include "buffer.h"
87 #include "window.h"
88 #include "keyboard.h"
89 #include "intervals.h"
90 #include "process.h"
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
96 #include <sys/types.h>
97 #ifdef HAVE_SYS_TIME_H
98 #include <sys/time.h>
99 #endif
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
104 #ifdef USE_X_TOOLKIT
106 extern void free_frame_menubar ();
107 extern FRAME_PTR x_menubar_window_to_frame ();
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 #elif defined HAVE_XAW3D
122 #include <X11/Xaw3d/Simple.h>
123 #include <X11/Xaw3d/ThreeD.h>
124 #include <X11/Xaw3d/Scrollbar.h>
125 #define ARROW_SCROLLBAR
126 #include <X11/Xaw3d/ScrollbarP.h>
127 #endif /* HAVE_XAW3D */
128 #endif /* USE_TOOLKIT_SCROLL_BARS */
130 #endif /* USE_X_TOOLKIT */
132 #ifndef USE_X_TOOLKIT
133 #define x_any_window_to_frame x_window_to_frame
134 #define x_top_window_to_frame x_window_to_frame
135 #endif
137 #ifdef USE_X_TOOLKIT
138 #include "widget.h"
139 #ifndef XtNinitialState
140 #define XtNinitialState "initialState"
141 #endif
142 #endif
144 #ifdef SOLARIS2
145 /* memmove will be defined as a macro in Xfuncs.h unless
146 <string.h> is included beforehand. The declaration for memmove in
147 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
148 #include <string.h>
149 #endif
151 #ifndef min
152 #define min(a,b) ((a) < (b) ? (a) : (b))
153 #endif
154 #ifndef max
155 #define max(a,b) ((a) > (b) ? (a) : (b))
156 #endif
158 #define abs(x) ((x) < 0 ? -(x) : (x))
160 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
163 /* Bitmaps for truncated lines. */
165 enum bitmap_type
167 NO_BITMAP,
168 LEFT_TRUNCATION_BITMAP,
169 RIGHT_TRUNCATION_BITMAP,
170 OVERLAY_ARROW_BITMAP,
171 CONTINUED_LINE_BITMAP,
172 CONTINUATION_LINE_BITMAP,
173 ZV_LINE_BITMAP
176 /* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
179 #define zv_width 8
180 #define zv_height 8
181 static unsigned char zv_bits[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184 /* An arrow like this: `<-'. */
186 #define left_width 8
187 #define left_height 8
188 static unsigned char left_bits[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191 /* Right truncation arrow bitmap `->'. */
193 #define right_width 8
194 #define right_height 8
195 static unsigned char right_bits[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198 /* Marker for continued lines. */
200 #define continued_width 8
201 #define continued_height 8
202 static unsigned char continued_bits[] = {
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205 /* Marker for continuation lines. */
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits[] = {
210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
212 /* Overlay arrow bitmap. */
214 #if 0
215 /* A bomb. */
216 #define ov_width 8
217 #define ov_height 8
218 static unsigned char ov_bits[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
220 #else
221 /* A triangular arrow. */
222 #define ov_width 8
223 #define ov_height 8
224 static unsigned char ov_bits[] = {
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
227 #endif
229 extern Lisp_Object Qhelp_echo;
232 /* Non-zero means Emacs uses toolkit scroll bars. */
234 int x_toolkit_scroll_bars_p;
236 /* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
239 static Lisp_Object help_echo;
241 /* Temporary variable for XTread_socket. */
243 static Lisp_Object previous_help_echo;
245 /* Non-zero means that a HELP_EVENT has been generated since Emacs
246 start. */
248 static int any_help_event_p;
250 /* Non-zero means draw block and hollow cursor as wide as the glyph
251 under it. For example, if a block cursor is over a tab, it will be
252 drawn as wide as that tab on the display. */
254 int x_stretch_cursor_p;
256 /* This is a chain of structures for all the X displays currently in
257 use. */
259 struct x_display_info *x_display_list;
261 /* This is a list of cons cells, each of the form (NAME
262 . FONT-LIST-CACHE), one for each element of x_display_list and in
263 the same order. NAME is the name of the frame. FONT-LIST-CACHE
264 records previous values returned by x-list-fonts. */
266 Lisp_Object x_display_name_list;
268 /* Frame being updated by update_frame. This is declared in term.c.
269 This is set by update_begin and looked at by all the XT functions.
270 It is zero while not inside an update. In that case, the XT
271 functions assume that `selected_frame' is the frame to apply to. */
273 extern struct frame *updating_frame;
275 extern int waiting_for_input;
277 /* This is a frame waiting to be auto-raised, within XTread_socket. */
279 struct frame *pending_autoraise_frame;
281 #ifdef USE_X_TOOLKIT
282 /* The application context for Xt use. */
283 XtAppContext Xt_app_con;
284 static String Xt_default_resources[] = {0};
285 #endif /* USE_X_TOOLKIT */
287 /* Nominal cursor position -- where to draw output.
288 HPOS and VPOS are window relative glyph matrix coordinates.
289 X and Y are window relative pixel coordinates. */
291 struct cursor_pos output_cursor;
294 /* Mouse movement.
296 Formerly, we used PointerMotionHintMask (in standard_event_mask)
297 so that we would have to call XQueryPointer after each MotionNotify
298 event to ask for another such event. However, this made mouse tracking
299 slow, and there was a bug that made it eventually stop.
301 Simply asking for MotionNotify all the time seems to work better.
303 In order to avoid asking for motion events and then throwing most
304 of them away or busy-polling the server for mouse positions, we ask
305 the server for pointer motion hints. This means that we get only
306 one event per group of mouse movements. "Groups" are delimited by
307 other kinds of events (focus changes and button clicks, for
308 example), or by XQueryPointer calls; when one of these happens, we
309 get another MotionNotify event the next time the mouse moves. This
310 is at least as efficient as getting motion events when mouse
311 tracking is on, and I suspect only negligibly worse when tracking
312 is off. */
314 /* Where the mouse was last time we reported a mouse event. */
316 FRAME_PTR last_mouse_frame;
317 static XRectangle last_mouse_glyph;
318 static Lisp_Object last_mouse_press_frame;
320 /* The scroll bar in which the last X motion event occurred.
322 If the last X motion event occurred in a scroll bar, we set this so
323 XTmouse_position can know whether to report a scroll bar motion or
324 an ordinary motion.
326 If the last X motion event didn't occur in a scroll bar, we set
327 this to Qnil, to tell XTmouse_position to return an ordinary motion
328 event. */
330 static Lisp_Object last_mouse_scroll_bar;
332 /* This is a hack. We would really prefer that XTmouse_position would
333 return the time associated with the position it returns, but there
334 doesn't seem to be any way to wrest the time-stamp from the server
335 along with the position query. So, we just keep track of the time
336 of the last movement we received, and return that in hopes that
337 it's somewhat accurate. */
339 static Time last_mouse_movement_time;
341 /* Incremented by XTread_socket whenever it really tries to read
342 events. */
344 #ifdef __STDC__
345 static int volatile input_signal_count;
346 #else
347 static int input_signal_count;
348 #endif
350 /* Used locally within XTread_socket. */
352 static int x_noop_count;
354 /* Initial values of argv and argc. */
356 extern char **initial_argv;
357 extern int initial_argc;
359 extern Lisp_Object Vcommand_line_args, Vsystem_name;
361 /* Tells if a window manager is present or not. */
363 extern Lisp_Object Vx_no_window_manager;
365 extern Lisp_Object Qface, Qmouse_face;
367 extern int errno;
369 /* A mask of extra modifier bits to put into every keyboard char. */
371 extern int extra_keyboard_modifiers;
373 static Lisp_Object Qvendor_specific_keysyms;
375 extern XrmDatabase x_load_resources ();
376 extern Lisp_Object x_icon_type ();
379 /* Enumeration for overriding/changing the face to use for drawing
380 glyphs in x_draw_glyphs. */
382 enum draw_glyphs_face
384 DRAW_NORMAL_TEXT,
385 DRAW_INVERSE_VIDEO,
386 DRAW_CURSOR,
387 DRAW_MOUSE_FACE,
388 DRAW_IMAGE_RAISED,
389 DRAW_IMAGE_SUNKEN
392 static void x_update_window_end P_ ((struct window *, int));
393 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
394 void x_delete_display P_ ((struct x_display_info *));
395 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
396 unsigned));
397 static int fast_find_position P_ ((struct window *, int, int *, int *,
398 int *, int *));
399 static void set_output_cursor P_ ((struct cursor_pos *));
400 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
401 int *, int *, int *));
402 static void note_mode_line_highlight P_ ((struct window *, int, int));
403 static void x_check_font P_ ((struct frame *, XFontStruct *));
404 static void note_mouse_highlight P_ ((struct frame *, int, int));
405 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
406 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
407 static void show_mouse_face P_ ((struct x_display_info *,
408 enum draw_glyphs_face));
409 static int x_io_error_quitter P_ ((Display *));
410 int x_catch_errors P_ ((Display *));
411 void x_uncatch_errors P_ ((Display *, int));
412 void x_lower_frame P_ ((struct frame *));
413 void x_scroll_bar_clear P_ ((struct frame *));
414 int x_had_errors_p P_ ((Display *));
415 void x_wm_set_size_hint P_ ((struct frame *, long, int));
416 void x_raise_frame P_ ((struct frame *));
417 void x_set_window_size P_ ((struct frame *, int, int, int));
418 void x_wm_set_window_state P_ ((struct frame *, int));
419 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
420 void x_initialize P_ ((void));
421 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
422 static int x_compute_min_glyph_bounds P_ ((struct frame *));
423 static void x_draw_phys_cursor_glyph P_ ((struct window *,
424 struct glyph_row *,
425 enum draw_glyphs_face));
426 static void x_update_end P_ ((struct frame *));
427 static void XTframe_up_to_date P_ ((struct frame *));
428 static void XTreassert_line_highlight P_ ((int, int));
429 static void x_change_line_highlight P_ ((int, int, int, int));
430 static void XTset_terminal_modes P_ ((void));
431 static void XTreset_terminal_modes P_ ((void));
432 static void XTcursor_to P_ ((int, int, int, int));
433 static void x_write_glyphs P_ ((struct glyph *, int));
434 static void x_clear_end_of_line P_ ((int));
435 static void x_clear_frame P_ ((void));
436 static void x_clear_cursor P_ ((struct window *));
437 static void frame_highlight P_ ((struct frame *));
438 static void frame_unhighlight P_ ((struct frame *));
439 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
440 static void XTframe_rehighlight P_ ((struct frame *));
441 static void x_frame_rehighlight P_ ((struct x_display_info *));
442 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
443 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
444 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
445 XRectangle *));
446 static void expose_frame P_ ((struct frame *, int, int, int, int));
447 static void expose_window_tree P_ ((struct window *, XRectangle *));
448 static void expose_window P_ ((struct window *, XRectangle *));
449 static void expose_area P_ ((struct window *, struct glyph_row *,
450 XRectangle *, enum glyph_row_area));
451 static void expose_line P_ ((struct window *, struct glyph_row *,
452 XRectangle *));
453 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
454 static void x_update_window_cursor P_ ((struct window *, int));
455 static void x_erase_phys_cursor P_ ((struct window *));
456 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
457 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
458 enum bitmap_type));
460 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
461 GC, int));
462 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
463 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
464 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
465 static void x_flush P_ ((struct frame *f));
468 /* Flush display of frame F, or of all frames if F is null. */
470 static void
471 x_flush (f)
472 struct frame *f;
474 BLOCK_INPUT;
475 if (f == NULL)
477 Lisp_Object rest, frame;
478 FOR_EACH_FRAME (rest, frame)
479 x_flush (XFRAME (frame));
481 else if (FRAME_X_P (f))
482 XFlush (FRAME_X_DISPLAY (f));
483 UNBLOCK_INPUT;
487 /* Remove calls to XFlush by defining XFlush to an empty replacement.
488 Calls to XFlush should be unnecessary because the X output buffer
489 is flushed automatically as needed by calls to XPending,
490 XNextEvent, or XWindowEvent according to the XFlush man page.
491 XTread_socket calls XPending. Removing XFlush improves
492 performance. */
494 #define XFlush(DISPLAY) (void) 0
497 /***********************************************************************
498 Debugging
499 ***********************************************************************/
501 #if 0
503 /* This is a function useful for recording debugging information about
504 the sequence of occurrences in this file. */
506 struct record
508 char *locus;
509 int type;
512 struct record event_record[100];
514 int event_record_index;
516 record_event (locus, type)
517 char *locus;
518 int type;
520 if (event_record_index == sizeof (event_record) / sizeof (struct record))
521 event_record_index = 0;
523 event_record[event_record_index].locus = locus;
524 event_record[event_record_index].type = type;
525 event_record_index++;
528 #endif /* 0 */
532 /* Return the struct x_display_info corresponding to DPY. */
534 struct x_display_info *
535 x_display_info_for_display (dpy)
536 Display *dpy;
538 struct x_display_info *dpyinfo;
540 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
541 if (dpyinfo->display == dpy)
542 return dpyinfo;
544 return 0;
549 /***********************************************************************
550 Starting and ending an update
551 ***********************************************************************/
553 /* Start an update of frame F. This function is installed as a hook
554 for update_begin, i.e. it is called when update_begin is called.
555 This function is called prior to calls to x_update_window_begin for
556 each window being updated. Currently, there is nothing to do here
557 because all interesting stuff is done on a window basis. */
559 static void
560 x_update_begin (f)
561 struct frame *f;
563 /* Nothing to do. */
567 /* Start update of window W. Set the global variable updated_window
568 to the window being updated and set output_cursor to the cursor
569 position of W. */
571 static void
572 x_update_window_begin (w)
573 struct window *w;
575 struct frame *f = XFRAME (WINDOW_FRAME (w));
576 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
578 updated_window = w;
579 set_output_cursor (&w->cursor);
581 BLOCK_INPUT;
583 if (f == display_info->mouse_face_mouse_frame)
585 /* Don't do highlighting for mouse motion during the update. */
586 display_info->mouse_face_defer = 1;
588 /* If F needs to be redrawn, simply forget about any prior mouse
589 highlighting. */
590 if (FRAME_GARBAGED_P (f))
591 display_info->mouse_face_window = Qnil;
593 /* Can we tell that this update does not affect the window
594 where the mouse highlight is? If so, no need to turn off.
595 Likewise, don't do anything if the frame is garbaged;
596 in that case, the frame's current matrix that we would use
597 is all wrong, and we will redisplay that line anyway. */
598 if (!NILP (display_info->mouse_face_window)
599 && w == XWINDOW (display_info->mouse_face_window))
601 int i;
603 for (i = 0; i < w->desired_matrix->nrows; ++i)
604 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
605 break;
607 if (i < w->desired_matrix->nrows)
608 clear_mouse_face (display_info);
612 UNBLOCK_INPUT;
616 /* Draw a vertical window border to the right of window W if W doesn't
617 have vertical scroll bars. */
619 static void
620 x_draw_vertical_border (w)
621 struct window *w;
623 struct frame *f = XFRAME (WINDOW_FRAME (w));
625 /* Redraw borders between horizontally adjacent windows. Don't
626 do it for frames with vertical scroll bars because either the
627 right scroll bar of a window, or the left scroll bar of its
628 neighbor will suffice as a border. */
629 if (!WINDOW_RIGHTMOST_P (w)
630 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
632 int x0, x1, y0, y1;
634 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
635 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
636 y1 -= 1;
638 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
639 f->output_data.x->normal_gc, x1, y0, x1, y1);
644 /* End update of window W (which is equal to updated_window). Draw
645 vertical borders between horizontally adjacent windows, and display
646 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
647 pseudo-window in case we don't have X toolkit support. Such
648 windows don't have a cursor, so don't display it here. */
650 static void
651 x_update_window_end (w, cursor_on_p)
652 struct window *w;
653 int cursor_on_p;
655 if (!w->pseudo_window_p)
657 BLOCK_INPUT;
658 if (cursor_on_p)
659 x_display_and_set_cursor (w, 1, output_cursor.hpos,
660 output_cursor.vpos,
661 output_cursor.x, output_cursor.y);
662 x_draw_vertical_border (w);
663 UNBLOCK_INPUT;
666 updated_window = NULL;
670 /* End update of frame F. This function is installed as a hook in
671 update_end. */
673 static void
674 x_update_end (f)
675 struct frame *f;
677 /* Mouse highlight may be displayed again. */
678 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
680 BLOCK_INPUT;
681 XFlush (FRAME_X_DISPLAY (f));
682 UNBLOCK_INPUT;
686 /* This function is called from various places in xdisp.c whenever a
687 complete update has been performed. The global variable
688 updated_window is not available here. */
690 static void
691 XTframe_up_to_date (f)
692 struct frame *f;
694 if (FRAME_X_P (f))
696 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
697 if (dpyinfo->mouse_face_deferred_gc
698 || f == dpyinfo->mouse_face_mouse_frame)
700 BLOCK_INPUT;
701 if (dpyinfo->mouse_face_mouse_frame)
702 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
703 dpyinfo->mouse_face_mouse_x,
704 dpyinfo->mouse_face_mouse_y);
705 dpyinfo->mouse_face_deferred_gc = 0;
706 UNBLOCK_INPUT;
712 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
713 arrow bitmaps, or clear the areas where they would be displayed
714 before DESIRED_ROW is made current. The window being updated is
715 found in updated_window. This function It is called from
716 update_window_line only if it is known that there are differences
717 between bitmaps to be drawn between current row and DESIRED_ROW. */
719 static void
720 x_after_update_window_line (desired_row)
721 struct glyph_row *desired_row;
723 struct window *w = updated_window;
725 xassert (w);
727 if (!desired_row->mode_line_p && !w->pseudo_window_p)
729 BLOCK_INPUT;
730 x_draw_row_bitmaps (w, desired_row);
732 /* When a window has disappeared, make sure that no rest of
733 full-width rows stays visible in the internal border. */
734 if (windows_or_buffers_changed)
736 struct frame *f = XFRAME (w->frame);
737 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
738 int height = desired_row->visible_height;
739 int x = (window_box_right (w, -1)
740 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
741 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
743 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
744 x, y, width, height, False);
747 UNBLOCK_INPUT;
752 /* Draw the bitmap WHICH in one of the areas to the left or right of
753 window W. ROW is the glyph row for which to display the bitmap; it
754 determines the vertical position at which the bitmap has to be
755 drawn. */
757 static void
758 x_draw_bitmap (w, row, which)
759 struct window *w;
760 struct glyph_row *row;
761 enum bitmap_type which;
763 struct frame *f = XFRAME (WINDOW_FRAME (w));
764 Display *display = FRAME_X_DISPLAY (f);
765 Window window = FRAME_X_WINDOW (f);
766 int x, y, wd, h, dy;
767 unsigned char *bits;
768 Pixmap pixmap;
769 GC gc = f->output_data.x->normal_gc;
770 struct face *face;
771 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
773 /* Must clip because of partially visible lines. */
774 x_clip_to_row (w, row, gc, 1);
776 switch (which)
778 case LEFT_TRUNCATION_BITMAP:
779 wd = left_width;
780 h = left_height;
781 bits = left_bits;
782 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
783 - wd
784 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
785 break;
787 case OVERLAY_ARROW_BITMAP:
788 wd = left_width;
789 h = left_height;
790 bits = ov_bits;
791 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
792 - wd
793 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
794 break;
796 case RIGHT_TRUNCATION_BITMAP:
797 wd = right_width;
798 h = right_height;
799 bits = right_bits;
800 x = window_box_right (w, -1);
801 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
802 break;
804 case CONTINUED_LINE_BITMAP:
805 wd = right_width;
806 h = right_height;
807 bits = continued_bits;
808 x = window_box_right (w, -1);
809 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
810 break;
812 case CONTINUATION_LINE_BITMAP:
813 wd = continuation_width;
814 h = continuation_height;
815 bits = continuation_bits;
816 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
817 - wd
818 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
819 break;
821 case ZV_LINE_BITMAP:
822 wd = zv_width;
823 h = zv_height;
824 bits = zv_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 default:
831 abort ();
834 /* Convert to frame coordinates. Set dy to the offset in the row to
835 start drawing the bitmap. */
836 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
837 dy = (row->height - h) / 2;
839 /* Draw the bitmap. I believe these small pixmaps can be cached
840 by the server. */
841 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
842 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
843 face->foreground,
844 face->background, depth);
845 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
846 XFreePixmap (display, pixmap);
847 XSetClipMask (display, gc, None);
851 /* Draw flags bitmaps for glyph row ROW on window W. Call this
852 function with input blocked. */
854 static void
855 x_draw_row_bitmaps (w, row)
856 struct window *w;
857 struct glyph_row *row;
859 struct frame *f = XFRAME (w->frame);
860 enum bitmap_type bitmap;
861 struct face *face;
862 int header_line_height = -1;
864 xassert (interrupt_input_blocked);
866 /* If row is completely invisible, because of vscrolling, we
867 don't have to draw anything. */
868 if (row->visible_height <= 0)
869 return;
871 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
872 PREPARE_FACE_FOR_DISPLAY (f, face);
874 /* Decide which bitmap to draw at the left side. */
875 if (row->overlay_arrow_p)
876 bitmap = OVERLAY_ARROW_BITMAP;
877 else if (row->truncated_on_left_p)
878 bitmap = LEFT_TRUNCATION_BITMAP;
879 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
880 bitmap = CONTINUATION_LINE_BITMAP;
881 else if (row->indicate_empty_line_p)
882 bitmap = ZV_LINE_BITMAP;
883 else
884 bitmap = NO_BITMAP;
886 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
887 the flags area. */
888 if (bitmap == NO_BITMAP
889 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
890 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
892 /* If W has a vertical border to its left, don't draw over it. */
893 int border = ((XFASTINT (w->left) > 0
894 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
895 ? 1 : 0);
896 int left = window_box_left (w, -1);
898 if (header_line_height < 0)
899 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
901 /* In case the same realized face is used for bitmap areas and
902 for something displayed in the text (e.g. face `region' on
903 mono-displays, the fill style may have been changed to
904 FillSolid in x_draw_glyph_string_background. */
905 if (face->stipple)
906 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
907 else
908 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
910 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
911 face->gc,
912 (left
913 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
914 + border),
915 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
916 row->y)),
917 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
918 row->visible_height);
919 if (!face->stipple)
920 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
923 /* Draw the left bitmap. */
924 if (bitmap != NO_BITMAP)
925 x_draw_bitmap (w, row, bitmap);
927 /* Decide which bitmap to draw at the right side. */
928 if (row->truncated_on_right_p)
929 bitmap = RIGHT_TRUNCATION_BITMAP;
930 else if (row->continued_p)
931 bitmap = CONTINUED_LINE_BITMAP;
932 else
933 bitmap = NO_BITMAP;
935 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
936 the flags area. */
937 if (bitmap == NO_BITMAP
938 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
939 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
941 int right = window_box_right (w, -1);
943 if (header_line_height < 0)
944 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
946 /* In case the same realized face is used for bitmap areas and
947 for something displayed in the text (e.g. face `region' on
948 mono-displays, the fill style may have been changed to
949 FillSolid in x_draw_glyph_string_background. */
950 if (face->stipple)
951 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
952 else
953 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
954 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
955 face->gc,
956 right,
957 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
958 row->y)),
959 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
960 row->visible_height);
961 if (!face->stipple)
962 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
965 /* Draw the right bitmap. */
966 if (bitmap != NO_BITMAP)
967 x_draw_bitmap (w, row, bitmap);
971 /***********************************************************************
972 Line Highlighting
973 ***********************************************************************/
975 /* External interface to control of standout mode. Not used for X
976 frames. Aborts when called. */
978 static void
979 XTreassert_line_highlight (new, vpos)
980 int new, vpos;
982 abort ();
986 /* Call this when about to modify line at position VPOS and change
987 whether it is highlighted. Not used for X frames. Aborts when
988 called. */
990 static void
991 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
992 int new_highlight, vpos, y, first_unused_hpos;
994 abort ();
998 /* This is called when starting Emacs and when restarting after
999 suspend. When starting Emacs, no X window is mapped. And nothing
1000 must be done to Emacs's own window if it is suspended (though that
1001 rarely happens). */
1003 static void
1004 XTset_terminal_modes ()
1008 /* This is called when exiting or suspending Emacs. Exiting will make
1009 the X-windows go away, and suspending requires no action. */
1011 static void
1012 XTreset_terminal_modes ()
1018 /***********************************************************************
1019 Output Cursor
1020 ***********************************************************************/
1022 /* Set the global variable output_cursor to CURSOR. All cursor
1023 positions are relative to updated_window. */
1025 static void
1026 set_output_cursor (cursor)
1027 struct cursor_pos *cursor;
1029 output_cursor.hpos = cursor->hpos;
1030 output_cursor.vpos = cursor->vpos;
1031 output_cursor.x = cursor->x;
1032 output_cursor.y = cursor->y;
1036 /* Set a nominal cursor position.
1038 HPOS and VPOS are column/row positions in a window glyph matrix. X
1039 and Y are window text area relative pixel positions.
1041 If this is done during an update, updated_window will contain the
1042 window that is being updated and the position is the future output
1043 cursor position for that window. If updated_window is null, use
1044 selected_window and display the cursor at the given position. */
1046 static void
1047 XTcursor_to (vpos, hpos, y, x)
1048 int vpos, hpos, y, x;
1050 struct window *w;
1052 /* If updated_window is not set, work on selected_window. */
1053 if (updated_window)
1054 w = updated_window;
1055 else
1056 w = XWINDOW (selected_window);
1058 /* Set the output cursor. */
1059 output_cursor.hpos = hpos;
1060 output_cursor.vpos = vpos;
1061 output_cursor.x = x;
1062 output_cursor.y = y;
1064 /* If not called as part of an update, really display the cursor.
1065 This will also set the cursor position of W. */
1066 if (updated_window == NULL)
1068 BLOCK_INPUT;
1069 x_display_cursor (w, 1, hpos, vpos, x, y);
1070 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1071 UNBLOCK_INPUT;
1077 /***********************************************************************
1078 Display Iterator
1079 ***********************************************************************/
1081 /* Function prototypes of this page. */
1083 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1084 struct glyph *,
1085 XChar2b *));
1086 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1087 int, XChar2b *, int));
1088 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1089 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1090 static void x_append_glyph P_ ((struct it *));
1091 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1092 int, int, double));
1093 static void x_produce_glyphs P_ ((struct it *));
1094 static void x_produce_image_glyph P_ ((struct it *it));
1097 /* Return a pointer to per-char metric information in FONT of a
1098 character pointed by B which is a pointer to an XChar2b. */
1100 #define PER_CHAR_METRIC(font, b) \
1101 ((font)->per_char \
1102 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1103 + (((font)->min_byte1 || (font)->max_byte1) \
1104 ? (((b)->byte1 - (font)->min_byte1) \
1105 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1106 : 0)) \
1107 : &((font)->max_bounds))
1110 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1111 If CHAR2B is not contained in FONT, the font's default character
1112 metric is returned. */
1114 static INLINE XCharStruct *
1115 x_per_char_metric (font, char2b)
1116 XFontStruct *font;
1117 XChar2b *char2b;
1119 /* The result metric information. */
1120 XCharStruct *pcm = NULL;
1122 xassert (font && char2b);
1124 if (font->per_char != NULL)
1126 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1128 /* min_char_or_byte2 specifies the linear character index
1129 corresponding to the first element of the per_char array,
1130 max_char_or_byte2 is the index of the last character. A
1131 character with non-zero CHAR2B->byte1 is not in the font.
1132 A character with byte2 less than min_char_or_byte2 or
1133 greater max_char_or_byte2 is not in the font. */
1134 if (char2b->byte1 == 0
1135 && char2b->byte2 >= font->min_char_or_byte2
1136 && char2b->byte2 <= font->max_char_or_byte2)
1137 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1139 else
1141 /* If either min_byte1 or max_byte1 are nonzero, both
1142 min_char_or_byte2 and max_char_or_byte2 are less than
1143 256, and the 2-byte character index values corresponding
1144 to the per_char array element N (counting from 0) are:
1146 byte1 = N/D + min_byte1
1147 byte2 = N\D + min_char_or_byte2
1149 where:
1151 D = max_char_or_byte2 - min_char_or_byte2 + 1
1152 / = integer division
1153 \ = integer modulus */
1154 if (char2b->byte1 >= font->min_byte1
1155 && char2b->byte1 <= font->max_byte1
1156 && char2b->byte2 >= font->min_char_or_byte2
1157 && char2b->byte2 <= font->max_char_or_byte2)
1159 pcm = (font->per_char
1160 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1161 * (char2b->byte1 - font->min_byte1))
1162 + (char2b->byte2 - font->min_char_or_byte2));
1166 else
1168 /* If the per_char pointer is null, all glyphs between the first
1169 and last character indexes inclusive have the same
1170 information, as given by both min_bounds and max_bounds. */
1171 if (char2b->byte2 >= font->min_char_or_byte2
1172 && char2b->byte2 <= font->max_char_or_byte2)
1173 pcm = &font->max_bounds;
1177 if (pcm == NULL || pcm->width == 0)
1179 /* Character not contained in the font. FONT->default_char
1180 gives the character that will be printed. FONT->default_char
1181 is a 16-bit character code with byte1 in the most significant
1182 byte and byte2 in the least significant byte. */
1183 XChar2b default_char;
1184 default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
1185 default_char.byte2 = font->default_char & 0xff;
1187 /* Avoid an endless recursion if FONT->default_char itself
1188 hasn't per char metrics. handa@etl.go.jp reports that some
1189 fonts have this problem. */
1190 if (default_char.byte1 != char2b->byte1
1191 || default_char.byte2 != char2b->byte2)
1192 pcm = x_per_char_metric (font, &default_char);
1193 else
1194 pcm = &font->max_bounds;
1197 return pcm;
1201 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1202 the two-byte form of C. Encoding is returned in *CHAR2B. */
1204 static INLINE void
1205 x_encode_char (c, char2b, font_info)
1206 int c;
1207 XChar2b *char2b;
1208 struct font_info *font_info;
1210 int charset = CHAR_CHARSET (c);
1211 XFontStruct *font = font_info->font;
1213 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1214 This may be either a program in a special encoder language or a
1215 fixed encoding. */
1216 if (font_info->font_encoder)
1218 /* It's a program. */
1219 struct ccl_program *ccl = font_info->font_encoder;
1221 if (CHARSET_DIMENSION (charset) == 1)
1223 ccl->reg[0] = charset;
1224 ccl->reg[1] = char2b->byte2;
1226 else
1228 ccl->reg[0] = charset;
1229 ccl->reg[1] = char2b->byte1;
1230 ccl->reg[2] = char2b->byte2;
1233 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1235 /* We assume that MSBs are appropriately set/reset by CCL
1236 program. */
1237 if (font->max_byte1 == 0) /* 1-byte font */
1238 char2b->byte2 = ccl->reg[1];
1239 else
1240 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1242 else if (font_info->encoding[charset])
1244 /* Fixed encoding scheme. See fontset.h for the meaning of the
1245 encoding numbers. */
1246 int enc = font_info->encoding[charset];
1248 if ((enc == 1 || enc == 2)
1249 && CHARSET_DIMENSION (charset) == 2)
1250 char2b->byte1 |= 0x80;
1252 if (enc == 1 || enc == 3)
1253 char2b->byte2 |= 0x80;
1258 /* Get face and two-byte form of character C in face FACE_ID on frame
1259 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1260 means we want to display multibyte text. Value is a pointer to a
1261 realized face that is ready for display. */
1263 static INLINE struct face *
1264 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1265 struct frame *f;
1266 int c, face_id;
1267 XChar2b *char2b;
1268 int multibyte_p;
1270 struct face *face = FACE_FROM_ID (f, face_id);
1272 if (!multibyte_p)
1274 /* Unibyte case. We don't have to encode, but we have to make
1275 sure to use a face suitable for unibyte. */
1276 char2b->byte1 = 0;
1277 char2b->byte2 = c;
1279 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
1281 face_id = FACE_FOR_CHARSET (f, face_id, -1);
1282 face = FACE_FROM_ID (f, face_id);
1285 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1287 /* Case of ASCII in a face known to fit ASCII. */
1288 char2b->byte1 = 0;
1289 char2b->byte2 = c;
1291 else
1293 int c1, c2, charset;
1295 /* Split characters into bytes. If c2 is -1 afterwards, C is
1296 really a one-byte character so that byte1 is zero. */
1297 SPLIT_CHAR (c, charset, c1, c2);
1298 if (c2 > 0)
1299 char2b->byte1 = c1, char2b->byte2 = c2;
1300 else
1301 char2b->byte1 = 0, char2b->byte2 = c1;
1303 /* Get the face for displaying C. If `face' is not suitable for
1304 charset, get the one that fits. (This can happen for the
1305 translations of composite characters where the glyph
1306 specifies a face for ASCII, but translations have a different
1307 charset.) */
1308 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
1310 face_id = FACE_FOR_CHARSET (f, face_id, charset);
1311 face = FACE_FROM_ID (f, face_id);
1314 /* Maybe encode the character in *CHAR2B. */
1315 if (charset != CHARSET_ASCII)
1317 struct font_info *font_info
1318 = FONT_INFO_FROM_ID (f, face->font_info_id);
1319 if (font_info)
1321 x_encode_char (c, char2b, font_info);
1322 if (charset == charset_latin_iso8859_1)
1324 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
1325 >= 0x80);
1326 char2b->byte2 |= 0x80;
1332 /* Make sure X resources of the face are allocated. */
1333 xassert (face != NULL);
1334 PREPARE_FACE_FOR_DISPLAY (f, face);
1336 return face;
1340 /* Get face and two-byte form of character glyph GLYPH on frame F.
1341 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1342 a pointer to a realized face that is ready for display. */
1344 static INLINE struct face *
1345 x_get_glyph_face_and_encoding (f, glyph, char2b)
1346 struct frame *f;
1347 struct glyph *glyph;
1348 XChar2b *char2b;
1350 struct face *face;
1352 xassert (glyph->type == CHAR_GLYPH);
1353 face = FACE_FROM_ID (f, glyph->u.ch.face_id);
1355 if (!glyph->multibyte_p)
1357 /* Unibyte case. We don't have to encode, but we have to make
1358 sure to use a face suitable for unibyte. */
1359 char2b->byte1 = 0;
1360 char2b->byte2 = glyph->u.ch.code;
1362 else if (glyph->u.ch.code < 128
1363 && glyph->u.ch.face_id < BASIC_FACE_ID_SENTINEL)
1365 /* Case of ASCII in a face known to fit ASCII. */
1366 char2b->byte1 = 0;
1367 char2b->byte2 = glyph->u.ch.code;
1369 else
1371 int c1, c2, charset;
1373 /* Split characters into bytes. If c2 is -1 afterwards, C is
1374 really a one-byte character so that byte1 is zero. */
1375 SPLIT_CHAR (glyph->u.ch.code, charset, c1, c2);
1376 if (c2 > 0)
1377 char2b->byte1 = c1, char2b->byte2 = c2;
1378 else
1379 char2b->byte1 = 0, char2b->byte2 = c1;
1381 /* Maybe encode the character in *CHAR2B. */
1382 if (charset != CHARSET_ASCII)
1384 struct font_info *font_info
1385 = FONT_INFO_FROM_ID (f, face->font_info_id);
1386 if (font_info)
1388 x_encode_char (glyph->u.ch.code, char2b, font_info);
1389 if (charset == charset_latin_iso8859_1)
1390 char2b->byte2 |= 0x80;
1395 /* Make sure X resources of the face are allocated. */
1396 xassert (face != NULL);
1397 PREPARE_FACE_FOR_DISPLAY (f, face);
1398 return face;
1402 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1403 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1405 static INLINE void
1406 x_append_glyph (it)
1407 struct it *it;
1409 struct glyph *glyph;
1410 enum glyph_row_area area = it->area;
1412 xassert (it->glyph_row);
1413 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1415 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1416 if (glyph < it->glyph_row->glyphs[area + 1])
1418 /* Play it safe. If sub-structures of the glyph are not all the
1419 same size, it otherwise be that some bits stay set. This
1420 would prevent a comparison with GLYPH_EQUAL_P. */
1421 glyph->u.val = 0;
1423 glyph->type = CHAR_GLYPH;
1424 glyph->pixel_width = it->pixel_width;
1425 glyph->u.ch.code = it->char_to_display;
1426 glyph->u.ch.face_id = it->face_id;
1427 glyph->charpos = CHARPOS (it->position);
1428 glyph->object = it->object;
1429 glyph->left_box_line_p = it->start_of_box_run_p;
1430 glyph->right_box_line_p = it->end_of_box_run_p;
1431 glyph->voffset = it->voffset;
1432 glyph->multibyte_p = it->multibyte_p;
1433 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1434 || it->phys_descent > it->descent);
1435 ++it->glyph_row->used[area];
1440 /* Change IT->ascent and IT->height according to the setting of
1441 IT->voffset. */
1443 static INLINE void
1444 take_vertical_position_into_account (it)
1445 struct it *it;
1447 if (it->voffset)
1449 if (it->voffset < 0)
1450 /* Increase the ascent so that we can display the text higher
1451 in the line. */
1452 it->ascent += abs (it->voffset);
1453 else
1454 /* Increase the descent so that we can display the text lower
1455 in the line. */
1456 it->descent += it->voffset;
1461 /* Produce glyphs/get display metrics for the image IT is loaded with.
1462 See the description of struct display_iterator in dispextern.h for
1463 an overview of struct display_iterator. */
1465 static void
1466 x_produce_image_glyph (it)
1467 struct it *it;
1469 struct image *img;
1470 struct face *face;
1472 xassert (it->what == IT_IMAGE);
1474 face = FACE_FROM_ID (it->f, it->face_id);
1475 img = IMAGE_FROM_ID (it->f, it->image_id);
1476 xassert (img);
1478 /* Make sure X resources of the face and image are loaded. */
1479 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1480 prepare_image_for_display (it->f, img);
1482 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1483 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1484 it->pixel_width = img->width + 2 * img->margin;
1486 it->nglyphs = 1;
1488 if (face->box != FACE_NO_BOX)
1490 it->ascent += face->box_line_width;
1491 it->descent += face->box_line_width;
1493 if (it->start_of_box_run_p)
1494 it->pixel_width += face->box_line_width;
1495 if (it->end_of_box_run_p)
1496 it->pixel_width += face->box_line_width;
1499 take_vertical_position_into_account (it);
1501 if (it->glyph_row)
1503 struct glyph *glyph;
1504 enum glyph_row_area area = it->area;
1506 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1507 if (glyph < it->glyph_row->glyphs[area + 1])
1509 glyph->type = IMAGE_GLYPH;
1510 glyph->u.img.id = img->id;
1511 glyph->u.img.face_id = it->face_id;
1512 glyph->pixel_width = it->pixel_width;
1513 glyph->charpos = CHARPOS (it->position);
1514 glyph->object = it->object;
1515 glyph->left_box_line_p = it->start_of_box_run_p;
1516 glyph->right_box_line_p = it->end_of_box_run_p;
1517 glyph->voffset = it->voffset;
1518 glyph->multibyte_p = it->multibyte_p;
1519 ++it->glyph_row->used[area];
1525 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1526 of the glyph, WIDTH and HEIGHT are the width and height of the
1527 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1528 ascent of the glyph (0 <= ASCENT <= 1). */
1530 static void
1531 x_append_stretch_glyph (it, object, width, height, ascent)
1532 struct it *it;
1533 Lisp_Object object;
1534 int width, height;
1535 double ascent;
1537 struct glyph *glyph;
1538 enum glyph_row_area area = it->area;
1540 xassert (ascent >= 0 && ascent <= 1);
1542 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1543 if (glyph < it->glyph_row->glyphs[area + 1])
1545 glyph->type = STRETCH_GLYPH;
1546 glyph->u.stretch.ascent = height * ascent;
1547 glyph->u.stretch.height = height;
1548 glyph->u.stretch.face_id = it->face_id;
1549 glyph->pixel_width = width;
1550 glyph->charpos = CHARPOS (it->position);
1551 glyph->object = object;
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->voffset = it->voffset;
1555 glyph->multibyte_p = it->multibyte_p;
1556 ++it->glyph_row->used[area];
1561 /* Produce a stretch glyph for iterator IT. IT->object is the value
1562 of the glyph property displayed. The value must be a list
1563 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1564 being recognized:
1566 1. `:width WIDTH' specifies that the space should be WIDTH *
1567 canonical char width wide. WIDTH may be an integer or floating
1568 point number.
1570 2. `:relative-width FACTOR' specifies that the width of the stretch
1571 should be computed from the width of the first character having the
1572 `glyph' property, and should be FACTOR times that width.
1574 3. `:align-to HPOS' specifies that the space should be wide enough
1575 to reach HPOS, a value in canonical character units.
1577 Exactly one of the above pairs must be present.
1579 4. `:height HEIGHT' specifies that the height of the stretch produced
1580 should be HEIGHT, measured in canonical character units.
1582 5. `:relative-height FACTOR' specifies that the height of the the
1583 stretch should be FACTOR times the height of the characters having
1584 the glyph property.
1586 Either none or exactly one of 4 or 5 must be present.
1588 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1589 of the stretch should be used for the ascent of the stretch.
1590 ASCENT must be in the range 0 <= ASCENT <= 100. */
1592 #define NUMVAL(X) \
1593 ((INTEGERP (X) || FLOATP (X)) \
1594 ? XFLOATINT (X) \
1595 : - 1)
1598 static void
1599 x_produce_stretch_glyph (it)
1600 struct it *it;
1602 /* (space :width WIDTH :height HEIGHT. */
1603 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1604 extern Lisp_Object QCrelative_width, QCrelative_height;
1605 extern Lisp_Object QCalign_to;
1606 Lisp_Object prop, plist;
1607 double width = 0, height = 0, ascent = 0;
1608 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1609 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1611 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1613 /* List should start with `space'. */
1614 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1615 plist = XCDR (it->object);
1617 /* Compute the width of the stretch. */
1618 if (prop = Fplist_get (plist, QCwidth),
1619 NUMVAL (prop) > 0)
1620 /* Absolute width `:width WIDTH' specified and valid. */
1621 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1622 else if (prop = Fplist_get (plist, QCrelative_width),
1623 NUMVAL (prop) > 0)
1625 /* Relative width `:relative-width FACTOR' specified and valid.
1626 Compute the width of the characters having the `glyph'
1627 property. */
1628 struct it it2;
1629 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1631 it2 = *it;
1632 if (it->multibyte_p)
1634 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1635 - IT_BYTEPOS (*it));
1636 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1638 else
1639 it2.c = *p, it2.len = 1;
1641 it2.glyph_row = NULL;
1642 it2.what = IT_CHARACTER;
1643 x_produce_glyphs (&it2);
1644 width = NUMVAL (prop) * it2.pixel_width;
1646 else if (prop = Fplist_get (plist, QCalign_to),
1647 NUMVAL (prop) > 0)
1648 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1649 else
1650 /* Nothing specified -> width defaults to canonical char width. */
1651 width = CANON_X_UNIT (it->f);
1653 /* Compute height. */
1654 if (prop = Fplist_get (plist, QCheight),
1655 NUMVAL (prop) > 0)
1656 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1657 else if (prop = Fplist_get (plist, QCrelative_height),
1658 NUMVAL (prop) > 0)
1659 height = FONT_HEIGHT (font) * NUMVAL (prop);
1660 else
1661 height = FONT_HEIGHT (font);
1663 /* Compute percentage of height used for ascent. If
1664 `:ascent ASCENT' is present and valid, use that. Otherwise,
1665 derive the ascent from the font in use. */
1666 if (prop = Fplist_get (plist, QCascent),
1667 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1668 ascent = NUMVAL (prop) / 100.0;
1669 else
1670 ascent = (double) font->ascent / FONT_HEIGHT (font);
1672 if (width <= 0)
1673 width = 1;
1674 if (height <= 0)
1675 height = 1;
1677 if (it->glyph_row)
1679 Lisp_Object object = it->stack[it->sp - 1].string;
1680 if (!STRINGP (object))
1681 object = it->w->buffer;
1682 x_append_stretch_glyph (it, object, width, height, ascent);
1685 it->pixel_width = width;
1686 it->ascent = it->phys_ascent = height * ascent;
1687 it->descent = it->phys_descent = height - it->ascent;
1688 it->nglyphs = 1;
1690 if (face->box != FACE_NO_BOX)
1692 it->ascent += face->box_line_width;
1693 it->descent += face->box_line_width;
1695 if (it->start_of_box_run_p)
1696 it->pixel_width += face->box_line_width;
1697 if (it->end_of_box_run_p)
1698 it->pixel_width += face->box_line_width;
1701 take_vertical_position_into_account (it);
1705 /* Produce glyphs/get display metrics for the display element IT is
1706 loaded with. See the description of struct display_iterator in
1707 dispextern.h for an overview of struct display_iterator. */
1709 static void
1710 x_produce_glyphs (it)
1711 struct it *it;
1713 if (it->what == IT_CHARACTER)
1715 XChar2b char2b;
1716 XFontStruct *font;
1717 struct face *face;
1718 XCharStruct *pcm;
1719 int font_not_found_p;
1721 /* Maybe translate single-byte characters to multibyte. */
1722 it->char_to_display = it->c;
1723 if (unibyte_display_via_language_environment
1724 && SINGLE_BYTE_CHAR_P (it->c)
1725 && (it->c >= 0240
1726 || (it->c >= 0200
1727 && !NILP (Vnonascii_translation_table))))
1729 it->char_to_display = unibyte_char_to_multibyte (it->c);
1730 it->charset = CHAR_CHARSET (it->char_to_display);
1733 /* Get face and font to use. Encode IT->char_to_display. */
1734 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1735 it->face_id, &char2b,
1736 it->multibyte_p);
1737 font = face->font;
1739 /* When no suitable font found, use the default font. */
1740 font_not_found_p = font == NULL;
1741 if (font_not_found_p)
1742 font = FRAME_FONT (it->f);
1744 if (it->char_to_display >= ' '
1745 && (!it->multibyte_p || it->char_to_display < 128))
1747 /* Either unibyte or ASCII. */
1748 int stretched_p;
1750 it->nglyphs = 1;
1752 pcm = x_per_char_metric (font, &char2b);
1753 it->ascent = font->ascent;
1754 it->descent = font->descent;
1755 it->phys_ascent = pcm->ascent;
1756 it->phys_descent = pcm->descent;
1757 it->pixel_width = pcm->width;
1759 /* If this is a space inside a region of text with
1760 `space-width' property, change its width. */
1761 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1762 if (stretched_p)
1763 it->pixel_width *= XFLOATINT (it->space_width);
1765 /* If face has a box, add the box thickness to the character
1766 height. If character has a box line to the left and/or
1767 right, add the box line width to the character's width. */
1768 if (face->box != FACE_NO_BOX)
1770 int thick = face->box_line_width;
1772 it->ascent += thick;
1773 it->descent += thick;
1775 if (it->start_of_box_run_p)
1776 it->pixel_width += thick;
1777 if (it->end_of_box_run_p)
1778 it->pixel_width += thick;
1781 /* If face has an overline, add the height of the overline
1782 (1 pixel) and a 1 pixel margin to the character height. */
1783 if (face->overline_p)
1784 it->ascent += 2;
1786 take_vertical_position_into_account (it);
1788 /* If we have to actually produce glyphs, do it. */
1789 if (it->glyph_row)
1791 if (stretched_p)
1793 /* Translate a space with a `space-width' property
1794 into a stretch glyph. */
1795 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1796 x_append_stretch_glyph (it, it->object, it->pixel_width,
1797 it->ascent + it->descent, ascent);
1799 else
1800 x_append_glyph (it);
1802 /* If characters with lbearing or rbearing are displayed
1803 in this line, record that fact in a flag of the
1804 glyph row. This is used to optimize X output code. */
1805 if (pcm->lbearing < 0
1806 || pcm->rbearing > pcm->width)
1807 it->glyph_row->contains_overlapping_glyphs_p = 1;
1810 else if (it->char_to_display == '\n')
1812 /* A newline has no width but we need the height of the line. */
1813 it->pixel_width = 0;
1814 it->nglyphs = 0;
1815 it->ascent = it->phys_ascent = font->ascent;
1816 it->descent = it->phys_descent = font->descent;
1818 if (face->box != FACE_NO_BOX)
1820 int thick = face->box_line_width;
1821 it->ascent += thick;
1822 it->descent += thick;
1825 else if (it->char_to_display == '\t')
1827 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1828 int x = (it->current_x
1829 - it->prompt_width
1830 + it->continuation_lines_width);
1831 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1833 it->pixel_width = next_tab_x - x;
1834 it->nglyphs = 1;
1835 it->ascent = it->phys_ascent = font->ascent;
1836 it->descent = it->phys_descent = font->descent;
1838 if (it->glyph_row)
1840 double ascent = (double) it->ascent / (it->ascent + it->descent);
1841 x_append_stretch_glyph (it, it->object, it->pixel_width,
1842 it->ascent + it->descent, ascent);
1845 else
1847 /* A multi-byte character. Assume that the display width of the
1848 character is the width of the character multiplied by the
1849 width of the font. There has to be better support for
1850 variable sizes in cmpchar_info to do anything better than
1851 that.
1853 Note: composite characters are represented as one glyph in
1854 the glyph matrix. There are no padding glyphs. */
1855 if (it->charset == CHARSET_COMPOSITION)
1857 struct cmpchar_info *cmpcharp;
1858 int idx;
1860 idx = COMPOSITE_CHAR_ID (it->char_to_display);
1861 cmpcharp = cmpchar_table[idx];
1862 it->pixel_width = font->max_bounds.width * cmpcharp->width;
1864 /* There are no padding glyphs, so there is only one glyph
1865 to produce for the composite char. Important is that
1866 pixel_width, ascent and descent are the values of what is
1867 drawn by draw_glyphs. */
1868 it->nglyphs = 1;
1870 /* These settings may not be correct. We must have more
1871 information in cmpcharp to do the correct setting. */
1872 it->ascent = font->ascent;
1873 it->descent = font->descent;
1874 it->phys_ascent = font->max_bounds.ascent;
1875 it->phys_descent = font->max_bounds.descent;
1877 else
1879 /* If we found a font, this font should give us the right
1880 metrics. If we didn't find a font, use the frame's
1881 default font and calculate the width of the character
1882 from the charset width; this is what old redisplay code
1883 did. */
1884 pcm = x_per_char_metric (font, &char2b);
1885 it->pixel_width = pcm->width;
1886 if (font_not_found_p)
1887 it->pixel_width *= CHARSET_WIDTH (it->charset);
1888 it->nglyphs = 1;
1889 it->ascent = font->ascent;
1890 it->descent = font->descent;
1891 it->phys_ascent = pcm->ascent;
1892 it->phys_descent = pcm->descent;
1893 if (it->glyph_row
1894 && (pcm->lbearing < 0
1895 || pcm->rbearing > pcm->width))
1896 it->glyph_row->contains_overlapping_glyphs_p = 1;
1899 if (face->box != FACE_NO_BOX)
1901 int thick = face->box_line_width;
1902 it->ascent += thick;
1903 it->descent += thick;
1905 if (it->start_of_box_run_p)
1906 it->pixel_width += thick;
1907 if (it->end_of_box_run_p)
1908 it->pixel_width += thick;
1911 /* If face has an overline, add the height of the overline
1912 (1 pixel) and a 1 pixel margin to the character height. */
1913 if (face->overline_p)
1914 it->ascent += 2;
1916 take_vertical_position_into_account (it);
1918 if (it->glyph_row)
1919 x_append_glyph (it);
1922 else if (it->what == IT_IMAGE)
1923 x_produce_image_glyph (it);
1924 else if (it->what == IT_STRETCH)
1925 x_produce_stretch_glyph (it);
1927 /* Accumulate dimensions. */
1928 xassert (it->ascent >= 0 && it->descent > 0);
1929 if (it->area == TEXT_AREA)
1930 it->current_x += it->pixel_width;
1932 it->max_ascent = max (it->max_ascent, it->ascent);
1933 it->max_descent = max (it->max_descent, it->descent);
1934 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
1935 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
1939 /* Estimate the pixel height of the mode or top line on frame F.
1940 FACE_ID specifies what line's height to estimate. */
1943 x_estimate_mode_line_height (f, face_id)
1944 struct frame *f;
1945 enum face_id face_id;
1947 int height = 1;
1949 /* This function is called so early when Emacs starts that the face
1950 cache and mode line face are not yet initialized. */
1951 if (FRAME_FACE_CACHE (f))
1953 struct face *face = FACE_FROM_ID (f, face_id);
1954 if (face)
1955 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
1958 return height;
1962 /***********************************************************************
1963 Glyph display
1964 ***********************************************************************/
1966 /* A sequence of glyphs to be drawn in the same face.
1968 This data structure is not really completely X specific, so it
1969 could possibly, at least partially, be useful for other systems. It
1970 is currently not part of the external redisplay interface because
1971 it's not clear what other systems will need. */
1973 struct glyph_string
1975 /* X-origin of the string. */
1976 int x;
1978 /* Y-origin and y-position of the base line of this string. */
1979 int y, ybase;
1981 /* The width of the string, not including a face extension. */
1982 int width;
1984 /* The width of the string, including a face extension. */
1985 int background_width;
1987 /* The height of this string. This is the height of the line this
1988 string is drawn in, and can be different from the height of the
1989 font the string is drawn in. */
1990 int height;
1992 /* Number of pixels this string overwrites in front of its x-origin.
1993 This number is zero if the string has an lbearing >= 0; it is
1994 -lbearing, if the string has an lbearing < 0. */
1995 int left_overhang;
1997 /* Number of pixels this string overwrites past its right-most
1998 nominal x-position, i.e. x + width. Zero if the string's
1999 rbearing is <= its nominal width, rbearing - width otherwise. */
2000 int right_overhang;
2002 /* The frame on which the glyph string is drawn. */
2003 struct frame *f;
2005 /* The window on which the glyph string is drawn. */
2006 struct window *w;
2008 /* X display and window for convenience. */
2009 Display *display;
2010 Window window;
2012 /* The glyph row for which this string was built. It determines the
2013 y-origin and height of the string. */
2014 struct glyph_row *row;
2016 /* The area within row. */
2017 enum glyph_row_area area;
2019 /* Characters to be drawn, and number of characters. */
2020 XChar2b *char2b;
2021 int nchars;
2023 /* Character set of this glyph string. */
2024 int charset;
2026 /* A face-override for drawing cursors, mouse face and similar. */
2027 enum draw_glyphs_face hl;
2029 /* Face in which this string is to be drawn. */
2030 struct face *face;
2032 /* Font in which this string is to be drawn. */
2033 XFontStruct *font;
2035 /* Font info for this string. */
2036 struct font_info *font_info;
2038 /* Non-null means this string describes (part of) a composite
2039 character. All characters from char2b are drawn at the same
2040 x-origin in that case. */
2041 struct cmpchar_info *cmpcharp;
2043 /* Index of this glyph string's first character in the glyph
2044 definition of cmpcharp. If this is zero, this glyph string
2045 describes the first character of a composite character. */
2046 int gidx;
2048 /* 1 means this glyph strings face has to be drawn to the right end
2049 of the window's drawing area. */
2050 unsigned extends_to_end_of_line_p : 1;
2052 /* 1 means the background of this string has been drawn. */
2053 unsigned background_filled_p : 1;
2055 /* 1 means glyph string must be drawn with 16-bit functions. */
2056 unsigned two_byte_p : 1;
2058 /* 1 means that the original font determined for drawing this glyph
2059 string could not be loaded. The member `font' has been set to
2060 the frame's default font in this case. */
2061 unsigned font_not_found_p : 1;
2063 /* 1 means that the face in which this glyph string is drawn has a
2064 stipple pattern. */
2065 unsigned stippled_p : 1;
2067 /* 1 means only the foreground of this glyph string must be drawn,
2068 and we should use the physical height of the line this glyph
2069 string appears in as clip rect. */
2070 unsigned for_overlaps_p : 1;
2072 /* The GC to use for drawing this glyph string. */
2073 GC gc;
2075 /* A pointer to the first glyph in the string. This glyph
2076 corresponds to char2b[0]. Needed to draw rectangles if
2077 font_not_found_p is 1. */
2078 struct glyph *first_glyph;
2080 /* Image, if any. */
2081 struct image *img;
2083 struct glyph_string *next, *prev;
2087 #if 0
2089 static void
2090 x_dump_glyph_string (s)
2091 struct glyph_string *s;
2093 fprintf (stderr, "glyph string\n");
2094 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2095 s->x, s->y, s->width, s->height);
2096 fprintf (stderr, " ybase = %d\n", s->ybase);
2097 fprintf (stderr, " hl = %d\n", s->hl);
2098 fprintf (stderr, " left overhang = %d, right = %d\n",
2099 s->left_overhang, s->right_overhang);
2100 fprintf (stderr, " nchars = %d\n", s->nchars);
2101 fprintf (stderr, " extends to end of line = %d\n",
2102 s->extends_to_end_of_line_p);
2103 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2104 fprintf (stderr, " bg width = %d\n", s->background_width);
2107 #endif /* GLYPH_DEBUG */
2111 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2112 struct glyph_string **,
2113 struct glyph_string *,
2114 struct glyph_string *));
2115 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2116 struct glyph_string **,
2117 struct glyph_string *,
2118 struct glyph_string *));
2119 static void x_append_glyph_string P_ ((struct glyph_string **,
2120 struct glyph_string **,
2121 struct glyph_string *));
2122 static int x_left_overwritten P_ ((struct glyph_string *));
2123 static int x_left_overwriting P_ ((struct glyph_string *));
2124 static int x_right_overwritten P_ ((struct glyph_string *));
2125 static int x_right_overwriting P_ ((struct glyph_string *));
2126 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2127 int));
2128 static void x_init_glyph_string P_ ((struct glyph_string *,
2129 XChar2b *, struct window *,
2130 struct glyph_row *,
2131 enum glyph_row_area, int,
2132 enum draw_glyphs_face));
2133 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2134 enum glyph_row_area, int, int,
2135 enum draw_glyphs_face, int *, int *, int));
2136 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2137 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2138 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2139 int));
2140 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2141 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2142 static void x_draw_glyph_string P_ ((struct glyph_string *));
2143 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2144 static void x_set_cursor_gc P_ ((struct glyph_string *));
2145 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2146 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2147 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2148 int *, int *));
2149 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2150 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2151 unsigned long *, double, int));
2152 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2153 double, int, unsigned long));
2154 static void x_setup_relief_colors P_ ((struct glyph_string *));
2155 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2156 static void x_draw_image_relief P_ ((struct glyph_string *));
2157 static void x_draw_image_foreground P_ ((struct glyph_string *));
2158 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2159 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2160 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2161 int, int, int));
2162 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2163 int, int, int, int, XRectangle *));
2164 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2165 int, int, int, XRectangle *));
2166 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2167 enum glyph_row_area));
2170 /* Append the list of glyph strings with head H and tail T to the list
2171 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2173 static INLINE void
2174 x_append_glyph_string_lists (head, tail, h, t)
2175 struct glyph_string **head, **tail;
2176 struct glyph_string *h, *t;
2178 if (h)
2180 if (*head)
2181 (*tail)->next = h;
2182 else
2183 *head = h;
2184 h->prev = *tail;
2185 *tail = t;
2190 /* Prepend the list of glyph strings with head H and tail T to the
2191 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2192 result. */
2194 static INLINE void
2195 x_prepend_glyph_string_lists (head, tail, h, t)
2196 struct glyph_string **head, **tail;
2197 struct glyph_string *h, *t;
2199 if (h)
2201 if (*head)
2202 (*head)->prev = t;
2203 else
2204 *tail = t;
2205 t->next = *head;
2206 *head = h;
2211 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2212 Set *HEAD and *TAIL to the resulting list. */
2214 static INLINE void
2215 x_append_glyph_string (head, tail, s)
2216 struct glyph_string **head, **tail;
2217 struct glyph_string *s;
2219 s->next = s->prev = NULL;
2220 x_append_glyph_string_lists (head, tail, s, s);
2224 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2225 face. */
2227 static void
2228 x_set_cursor_gc (s)
2229 struct glyph_string *s;
2231 if (s->font == FRAME_FONT (s->f)
2232 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2233 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2234 && !s->cmpcharp)
2235 s->gc = s->f->output_data.x->cursor_gc;
2236 else
2238 /* Cursor on non-default face: must merge. */
2239 XGCValues xgcv;
2240 unsigned long mask;
2242 xgcv.background = s->f->output_data.x->cursor_pixel;
2243 xgcv.foreground = s->face->background;
2245 /* If the glyph would be invisible, try a different foreground. */
2246 if (xgcv.foreground == xgcv.background)
2247 xgcv.foreground = s->face->foreground;
2248 if (xgcv.foreground == xgcv.background)
2249 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2250 if (xgcv.foreground == xgcv.background)
2251 xgcv.foreground = s->face->foreground;
2253 /* Make sure the cursor is distinct from text in this face. */
2254 if (xgcv.background == s->face->background
2255 && xgcv.foreground == s->face->foreground)
2257 xgcv.background = s->face->foreground;
2258 xgcv.foreground = s->face->background;
2261 IF_DEBUG (x_check_font (s->f, s->font));
2262 xgcv.font = s->font->fid;
2263 xgcv.graphics_exposures = False;
2264 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2266 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2267 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2268 mask, &xgcv);
2269 else
2270 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2271 = XCreateGC (s->display, s->window, mask, &xgcv);
2273 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2278 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2280 static void
2281 x_set_mouse_face_gc (s)
2282 struct glyph_string *s;
2284 int face_id;
2286 /* What face has to be used for the mouse face? */
2287 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2288 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
2289 s->face = FACE_FROM_ID (s->f, face_id);
2290 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2292 /* If font in this face is same as S->font, use it. */
2293 if (s->font == s->face->font)
2294 s->gc = s->face->gc;
2295 else
2297 /* Otherwise construct scratch_cursor_gc with values from FACE
2298 but font FONT. */
2299 XGCValues xgcv;
2300 unsigned long mask;
2302 xgcv.background = s->face->background;
2303 xgcv.foreground = s->face->foreground;
2304 IF_DEBUG (x_check_font (s->f, s->font));
2305 xgcv.font = s->font->fid;
2306 xgcv.graphics_exposures = False;
2307 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2309 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2310 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2311 mask, &xgcv);
2312 else
2313 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2314 = XCreateGC (s->display, s->window, mask, &xgcv);
2316 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2319 xassert (s->gc != 0);
2323 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2324 Faces to use in the mode line have already been computed when the
2325 matrix was built, so there isn't much to do, here. */
2327 static INLINE void
2328 x_set_mode_line_face_gc (s)
2329 struct glyph_string *s;
2331 s->gc = s->face->gc;
2332 xassert (s->gc != 0);
2336 /* Set S->gc of glyph string S for drawing that glyph string. Set
2337 S->stippled_p to a non-zero value if the face of S has a stipple
2338 pattern. */
2340 static INLINE void
2341 x_set_glyph_string_gc (s)
2342 struct glyph_string *s;
2344 if (s->hl == DRAW_NORMAL_TEXT)
2346 s->gc = s->face->gc;
2347 s->stippled_p = s->face->stipple != 0;
2349 else if (s->hl == DRAW_INVERSE_VIDEO)
2351 x_set_mode_line_face_gc (s);
2352 s->stippled_p = s->face->stipple != 0;
2354 else if (s->hl == DRAW_CURSOR)
2356 x_set_cursor_gc (s);
2357 s->stippled_p = 0;
2359 else if (s->hl == DRAW_MOUSE_FACE)
2361 x_set_mouse_face_gc (s);
2362 s->stippled_p = s->face->stipple != 0;
2364 else if (s->hl == DRAW_IMAGE_RAISED
2365 || s->hl == DRAW_IMAGE_SUNKEN)
2367 s->gc = s->face->gc;
2368 s->stippled_p = s->face->stipple != 0;
2370 else
2372 s->gc = s->face->gc;
2373 s->stippled_p = s->face->stipple != 0;
2376 /* GC must have been set. */
2377 xassert (s->gc != 0);
2381 /* Return in *R the clipping rectangle for glyph string S. */
2383 static void
2384 x_get_glyph_string_clip_rect (s, r)
2385 struct glyph_string *s;
2386 XRectangle *r;
2388 if (s->row->full_width_p)
2390 /* Draw full-width. X coordinates are relative to S->w->left. */
2391 int canon_x = CANON_X_UNIT (s->f);
2393 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2394 r->width = XFASTINT (s->w->width) * canon_x;
2396 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2398 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2399 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2400 r->x -= width;
2403 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2405 /* Unless displaying a mode or menu bar line, which are always
2406 fully visible, clip to the visible part of the row. */
2407 if (s->w->pseudo_window_p)
2408 r->height = s->row->visible_height;
2409 else
2410 r->height = s->height;
2412 else
2414 /* This is a text line that may be partially visible. */
2415 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2416 r->width = window_box_width (s->w, s->area);
2417 r->height = s->row->visible_height;
2420 /* Don't use S->y for clipping because it doesn't take partially
2421 visible lines into account. For example, it can be negative for
2422 partially visible lines at the top of a window. */
2423 if (!s->row->full_width_p
2424 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2425 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2426 else
2427 r->y = max (0, s->row->y);
2429 /* If drawing a tool-bar window, draw it over the internal border
2430 at the top of the window. */
2431 if (s->w == XWINDOW (s->f->tool_bar_window))
2432 r->y -= s->f->output_data.x->internal_border_width;
2434 /* If S draws overlapping rows, it's sufficient to use the top and
2435 bottom of the window for clipping because this glyph string
2436 intentionally draws over other lines. */
2437 if (s->for_overlaps_p)
2439 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2440 r->height = window_text_bottom_y (s->w) - r->y;
2443 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2447 /* Set clipping for output of glyph string S. S may be part of a mode
2448 line or menu if we don't have X toolkit support. */
2450 static INLINE void
2451 x_set_glyph_string_clipping (s)
2452 struct glyph_string *s;
2454 XRectangle r;
2455 x_get_glyph_string_clip_rect (s, &r);
2456 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2460 /* Compute left and right overhang of glyph string S. If S is a glyph
2461 string for a composite character, assume overhangs don't exist. */
2463 static INLINE void
2464 x_compute_glyph_string_overhangs (s)
2465 struct glyph_string *s;
2467 if (s->cmpcharp == NULL
2468 && s->first_glyph->type == CHAR_GLYPH)
2470 XCharStruct cs;
2471 int direction, font_ascent, font_descent;
2472 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2473 &font_ascent, &font_descent, &cs);
2474 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2475 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2480 /* Compute overhangs and x-positions for glyph string S and its
2481 predecessors, or successors. X is the starting x-position for S.
2482 BACKWARD_P non-zero means process predecessors. */
2484 static void
2485 x_compute_overhangs_and_x (s, x, backward_p)
2486 struct glyph_string *s;
2487 int x;
2488 int backward_p;
2490 if (backward_p)
2492 while (s)
2494 x_compute_glyph_string_overhangs (s);
2495 x -= s->width;
2496 s->x = x;
2497 s = s->prev;
2500 else
2502 while (s)
2504 x_compute_glyph_string_overhangs (s);
2505 s->x = x;
2506 x += s->width;
2507 s = s->next;
2513 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2514 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of
2515 character glyphs for composite characters are assumed to be zero. */
2517 static void
2518 x_get_glyph_overhangs (glyph, f, left, right)
2519 struct glyph *glyph;
2520 struct frame *f;
2521 int *left, *right;
2523 int c;
2525 *left = *right = 0;
2527 if (glyph->type == CHAR_GLYPH
2528 && (c = glyph->u.ch.code,
2529 CHAR_CHARSET (c) != CHARSET_COMPOSITION))
2531 XFontStruct *font;
2532 struct face *face;
2533 struct font_info *font_info;
2534 XChar2b char2b;
2536 face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
2537 font = face->font;
2538 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2539 if (font)
2541 XCharStruct *pcm = x_per_char_metric (font, &char2b);
2543 if (pcm->rbearing > pcm->width)
2544 *right = pcm->rbearing - pcm->width;
2545 if (pcm->lbearing < 0)
2546 *left = -pcm->lbearing;
2552 /* Return the index of the first glyph preceding glyph string S that
2553 is overwritten by S because of S's left overhang. Value is -1
2554 if no glyphs are overwritten. */
2556 static int
2557 x_left_overwritten (s)
2558 struct glyph_string *s;
2560 int k;
2562 if (s->left_overhang)
2564 int x = 0, i;
2565 struct glyph *glyphs = s->row->glyphs[s->area];
2566 int first = s->first_glyph - glyphs;
2568 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2569 x -= glyphs[i].pixel_width;
2571 k = i + 1;
2573 else
2574 k = -1;
2576 return k;
2580 /* Return the index of the first glyph preceding glyph string S that
2581 is overwriting S because of its right overhang. Value is -1 if no
2582 glyph in front of S overwrites S. */
2584 static int
2585 x_left_overwriting (s)
2586 struct glyph_string *s;
2588 int i, k, x;
2589 struct glyph *glyphs = s->row->glyphs[s->area];
2590 int first = s->first_glyph - glyphs;
2592 k = -1;
2593 x = 0;
2594 for (i = first - 1; i >= 0; --i)
2596 int left, right;
2597 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2598 if (x + right > 0)
2599 k = i;
2600 x -= glyphs[i].pixel_width;
2603 return k;
2607 /* Return the index of the last glyph following glyph string S that is
2608 not overwritten by S because of S's right overhang. Value is -1 if
2609 no such glyph is found. */
2611 static int
2612 x_right_overwritten (s)
2613 struct glyph_string *s;
2615 int k = -1;
2617 if (s->right_overhang)
2619 int x = 0, i;
2620 struct glyph *glyphs = s->row->glyphs[s->area];
2621 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2622 int end = s->row->used[s->area];
2624 for (i = first; i < end && s->right_overhang > x; ++i)
2625 x += glyphs[i].pixel_width;
2627 k = i;
2630 return k;
2634 /* Return the index of the last glyph following glyph string S that
2635 overwrites S because of its left overhang. Value is negative
2636 if no such glyph is found. */
2638 static int
2639 x_right_overwriting (s)
2640 struct glyph_string *s;
2642 int i, k, x;
2643 int end = s->row->used[s->area];
2644 struct glyph *glyphs = s->row->glyphs[s->area];
2645 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2647 k = -1;
2648 x = 0;
2649 for (i = first; i < end; ++i)
2651 int left, right;
2652 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2653 if (x - left < 0)
2654 k = i;
2655 x += glyphs[i].pixel_width;
2658 return k;
2662 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2664 static INLINE void
2665 x_clear_glyph_string_rect (s, x, y, w, h)
2666 struct glyph_string *s;
2667 int x, y, w, h;
2669 XGCValues xgcv;
2670 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
2671 XSetForeground (s->display, s->gc, xgcv.background);
2672 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2673 XSetForeground (s->display, s->gc, xgcv.foreground);
2677 /* Draw the background of glyph_string S. If S->background_filled_p
2678 is non-zero don't draw it. FORCE_P non-zero means draw the
2679 background even if it wouldn't be drawn normally. This is used
2680 when a string preceding S draws into the background of S. */
2682 static void
2683 x_draw_glyph_string_background (s, force_p)
2684 struct glyph_string *s;
2685 int force_p;
2687 /* Nothing to do if background has already been drawn or if it
2688 shouldn't be drawn in the first place. */
2689 if (!s->background_filled_p)
2691 if (s->cmpcharp
2692 && s->gidx > 0
2693 && !s->font_not_found_p
2694 && !s->extends_to_end_of_line_p)
2696 /* Don't draw background for glyphs of a composite
2697 characters, except for the first one. */
2698 s->background_filled_p = 1;
2700 else if (s->stippled_p)
2702 /* Fill background with a stipple pattern. */
2703 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2704 XFillRectangle (s->display, s->window, s->gc, s->x,
2705 s->y + s->face->box_line_width,
2706 s->background_width,
2707 s->height - 2 * s->face->box_line_width);
2708 XSetFillStyle (s->display, s->gc, FillSolid);
2709 s->background_filled_p = 1;
2711 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2712 || s->font_not_found_p
2713 || s->extends_to_end_of_line_p
2714 || s->cmpcharp
2715 || force_p)
2717 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2718 s->background_width,
2719 s->height - 2 * s->face->box_line_width);
2720 s->background_filled_p = 1;
2726 /* Draw the foreground of glyph string S. */
2728 static void
2729 x_draw_glyph_string_foreground (s)
2730 struct glyph_string *s;
2732 int i, x;
2734 /* If first glyph of S has a left box line, start drawing the text
2735 of S to the right of that box line. */
2736 if (s->face->box != FACE_NO_BOX
2737 && s->first_glyph->left_box_line_p)
2738 x = s->x + s->face->box_line_width;
2739 else
2740 x = s->x;
2742 if (s->cmpcharp == NULL)
2744 /* Not a composite character. Draw characters of S as
2745 rectangles if S's font could not be loaded. */
2746 if (s->font_not_found_p)
2748 for (i = 0; i < s->nchars; ++i)
2750 struct glyph *g = s->first_glyph + i;
2751 XDrawRectangle (s->display, s->window,
2752 s->gc, x, s->y, g->pixel_width - 1,
2753 s->height - 1);
2754 x += g->pixel_width;
2757 else
2759 char *char1b = (char *) s->char2b;
2761 /* If we can use 8-bit functions, condense S->char2b. */
2762 if (!s->two_byte_p)
2763 for (i = 0; i < s->nchars; ++i)
2764 char1b[i] = s->char2b[i].byte2;
2766 /* Draw text with XDrawString if background has already been
2767 filled. Otherwise, use XDrawImageString. (Note that
2768 XDrawImageString is usually faster than XDrawString.)
2769 Always use XDrawImageString when drawing the cursor so
2770 that there is no chance that characters under a box
2771 cursor are invisible. */
2772 if (s->for_overlaps_p
2773 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2775 /* Draw characters with 16-bit or 8-bit functions. */
2776 if (s->two_byte_p)
2777 XDrawString16 (s->display, s->window, s->gc, x, s->ybase,
2778 s->char2b, s->nchars);
2779 else
2780 XDrawString (s->display, s->window, s->gc, x, s->ybase,
2781 char1b, s->nchars);
2783 else
2785 if (s->two_byte_p)
2786 XDrawImageString16 (s->display, s->window, s->gc,
2787 x, s->ybase, s->char2b, s->nchars);
2788 else
2789 XDrawImageString (s->display, s->window, s->gc,
2790 x, s->ybase, char1b, s->nchars);
2794 else
2796 /* S is a glyph string for a composite character. S->gidx is the
2797 index of the first character drawn in the vector
2798 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the
2799 very first component character of a composite char. */
2801 /* Draw a single rectangle for the composite character if S's
2802 font could not be loaded. */
2803 if (s->font_not_found_p && s->gidx == 0)
2804 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
2805 s->width - 1, s->height - 1);
2806 else
2808 XCharStruct *pcm;
2809 int relative_compose, default_ascent, i;
2810 int highest = 0, lowest = 0;
2812 /* The value of font_info my be null if we couldn't find it
2813 in x_get_char_face_and_encoding. */
2814 if (s->cmpcharp->cmp_rule == NULL && s->font_info)
2816 relative_compose = s->font_info->relative_compose;
2817 default_ascent = s->font_info->default_ascent;
2819 else
2820 relative_compose = default_ascent = 0;
2822 if ((s->cmpcharp->cmp_rule || relative_compose)
2823 && s->gidx == 0)
2825 /* This is the first character. Initialize variables.
2826 Highest is the highest position of glyphs ever
2827 written, lowest the lowest position. */
2828 int x_offset = 0;
2829 int first_ch = s->first_glyph->u.ch.code;
2831 if (default_ascent
2832 && CHAR_TABLE_P (Vuse_default_ascent)
2833 && !NILP (Faref (Vuse_default_ascent, first_ch)))
2835 highest = default_ascent;
2836 lowest = 0;
2838 else
2840 pcm = PER_CHAR_METRIC (s->font, s->char2b);
2841 highest = pcm->ascent + 1;
2842 lowest = - pcm->descent;
2845 if (s->cmpcharp->cmp_rule)
2846 x_offset = (s->cmpcharp->col_offset[0]
2847 * FONT_WIDTH (s->f->output_data.x->font));
2849 /* Draw the first character at the normal position. */
2850 XDrawString16 (s->display, s->window, s->gc,
2851 x + x_offset,
2852 s->ybase, s->char2b, 1);
2853 i = 1;
2854 ++s->gidx;
2856 else
2857 i = 0;
2859 for (; i < s->nchars; i++, ++s->gidx)
2861 int x_offset = 0, y_offset = 0;
2863 if (relative_compose)
2865 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2866 if (NILP (Vignore_relative_composition)
2867 || NILP (Faref (Vignore_relative_composition,
2868 make_number (s->cmpcharp->glyph[s->gidx]))))
2870 if (- pcm->descent >= relative_compose)
2872 /* Draw above the current glyphs. */
2873 y_offset = highest + pcm->descent;
2874 highest += pcm->ascent + pcm->descent;
2876 else if (pcm->ascent <= 0)
2878 /* Draw beneath the current glyphs. */
2879 y_offset = lowest - pcm->ascent;
2880 lowest -= pcm->ascent + pcm->descent;
2883 else
2885 /* Draw the glyph at normal position. If
2886 it sticks out of HIGHEST or LOWEST,
2887 update them appropriately. */
2888 if (pcm->ascent > highest)
2889 highest = pcm->ascent;
2890 else if (- pcm->descent < lowest)
2891 lowest = - pcm->descent;
2894 else if (s->cmpcharp->cmp_rule)
2896 int gref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) / 9;
2897 int nref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) % 9;
2898 int bottom, top;
2900 /* Re-encode GREF and NREF so that they specify
2901 only Y-axis information:
2902 0:top, 1:base, 2:bottom, 3:center */
2903 gref = gref / 3 + (gref == 4) * 2;
2904 nref = nref / 3 + (nref == 4) * 2;
2906 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2907 bottom = ((gref == 0 ? highest : gref == 1 ? 0
2908 : gref == 2 ? lowest
2909 : (highest + lowest) / 2)
2910 - (nref == 0 ? pcm->ascent + pcm->descent
2911 : nref == 1 ? pcm->descent : nref == 2 ? 0
2912 : (pcm->ascent + pcm->descent) / 2));
2913 top = bottom + (pcm->ascent + pcm->descent);
2914 if (top > highest)
2915 highest = top;
2916 if (bottom < lowest)
2917 lowest = bottom;
2918 y_offset = bottom + pcm->descent;
2919 x_offset = (s->cmpcharp->col_offset[s->gidx]
2920 * FONT_WIDTH (FRAME_FONT (s->f)));
2923 XDrawString16 (s->display, s->window, s->gc,
2924 x + x_offset, s->ybase - y_offset,
2925 s->char2b + i, 1);
2932 #ifdef USE_X_TOOLKIT
2934 /* Allocate the color COLOR->pixel on the screen and display of
2935 widget WIDGET in colormap CMAP. If an exact match cannot be
2936 allocated, try the nearest color available. Value is non-zero
2937 if successful. This is called from lwlib. */
2940 x_alloc_nearest_color_for_widget (widget, cmap, color)
2941 Widget widget;
2942 Colormap cmap;
2943 XColor *color;
2945 struct frame *f;
2946 struct x_display_info *dpyinfo;
2947 Lisp_Object tail;
2949 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2951 /* Find the top-level shell of the widget. Note that this function
2952 can be called when the widget is not yet realized, so XtWindow
2953 (widget) == 0. That's the reason we can't simply use
2954 x_any_window_to_frame. */
2955 while (!XtIsTopLevelShell (widget))
2956 widget = XtParent (widget);
2958 /* Look for a frame with that top-level widget. Allocate the color
2959 on that frame to get the right gamma correction value. */
2960 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2961 if (GC_FRAMEP (XCAR (tail))
2962 && (f = XFRAME (XCAR (tail)),
2963 (f->output_data.nothing != 1
2964 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2965 && f->output_data.x->widget == widget)
2966 return x_alloc_nearest_color (f, cmap, color);
2968 abort ();
2971 #endif /* USE_X_TOOLKIT */
2974 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2975 CMAP. If an exact match can't be allocated, try the nearest color
2976 available. Value is non-zero if successful. Set *COLOR to the
2977 color allocated. */
2980 x_alloc_nearest_color (f, cmap, color)
2981 struct frame *f;
2982 Colormap cmap;
2983 XColor *color;
2985 Display *display = FRAME_X_DISPLAY (f);
2986 Screen *screen = FRAME_X_SCREEN (f);
2987 int rc;
2989 gamma_correct (f, color);
2990 rc = XAllocColor (display, cmap, color);
2991 if (rc == 0)
2993 /* If we got to this point, the colormap is full, so we're going
2994 to try to get the next closest color. The algorithm used is
2995 a least-squares matching, which is what X uses for closest
2996 color matching with StaticColor visuals. */
2997 int nearest, i;
2998 unsigned long nearest_delta = ~0;
2999 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3000 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3002 for (i = 0; i < ncells; ++i)
3003 cells[i].pixel = i;
3004 XQueryColors (display, cmap, cells, ncells);
3006 for (nearest = i = 0; i < ncells; ++i)
3008 long dred = (color->red >> 8) - (cells[i].red >> 8);
3009 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3010 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3011 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3013 if (delta < nearest_delta)
3015 nearest = i;
3016 nearest_delta = delta;
3020 color->red = cells[nearest].red;
3021 color->green = cells[nearest].green;
3022 color->blue = cells[nearest].blue;
3023 rc = XAllocColor (display, cmap, color);
3026 return rc;
3030 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3031 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3032 If this produces the same color as PIXEL, try a color where all RGB
3033 values have DELTA added. Return the allocated color in *PIXEL.
3034 DISPLAY is the X display, CMAP is the colormap to operate on.
3035 Value is non-zero if successful. */
3037 static int
3038 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3039 struct frame *f;
3040 Display *display;
3041 Colormap cmap;
3042 unsigned long *pixel;
3043 double factor;
3044 int delta;
3046 XColor color, new;
3047 int success_p;
3049 /* Get RGB color values. */
3050 color.pixel = *pixel;
3051 XQueryColor (display, cmap, &color);
3053 /* Change RGB values by specified FACTOR. Avoid overflow! */
3054 xassert (factor >= 0);
3055 new.red = min (0xffff, factor * color.red);
3056 new.green = min (0xffff, factor * color.green);
3057 new.blue = min (0xffff, factor * color.blue);
3059 /* Try to allocate the color. */
3060 success_p = x_alloc_nearest_color (f, cmap, &new);
3061 if (success_p)
3063 if (new.pixel == *pixel)
3065 /* If we end up with the same color as before, try adding
3066 delta to the RGB values. */
3067 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
3069 /* If display has an immutable color map, freeing colors is
3070 not necessary and some servers don't allow it. So don't
3071 do it. */
3072 if (class != StaticColor
3073 && class != StaticGray
3074 && class != TrueColor)
3075 XFreeColors (display, cmap, &new.pixel, 1, 0);
3077 new.red = min (0xffff, delta + color.red);
3078 new.green = min (0xffff, delta + color.green);
3079 new.blue = min (0xffff, delta + color.blue);
3080 success_p = x_alloc_nearest_color (f, cmap, &new);
3082 else
3083 success_p = 1;
3084 *pixel = new.pixel;
3087 return success_p;
3091 /* Set up the foreground color for drawing relief lines of glyph
3092 string S. RELIEF is a pointer to a struct relief containing the GC
3093 with which lines will be drawn. Use a color that is FACTOR or
3094 DELTA lighter or darker than the relief's background which is found
3095 in S->f->output_data.x->relief_background. If such a color cannot
3096 be allocated, use DEFAULT_PIXEL, instead. */
3098 static void
3099 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3100 struct frame *f;
3101 struct relief *relief;
3102 double factor;
3103 int delta;
3104 unsigned long default_pixel;
3106 XGCValues xgcv;
3107 struct x_output *di = f->output_data.x;
3108 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3109 unsigned long pixel;
3110 unsigned long background = di->relief_background;
3111 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
3112 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3113 Display *dpy = FRAME_X_DISPLAY (f);
3115 xgcv.graphics_exposures = False;
3116 xgcv.line_width = 1;
3118 /* Free previously allocated color. The color cell will be reused
3119 when it has been freed as many times as it was allocated, so this
3120 doesn't affect faces using the same colors. */
3121 if (relief->gc
3122 && relief->allocated_p)
3124 /* If display has an immutable color map, freeing colors is not
3125 necessary and some servers don't allow it. So don't do it. */
3126 int class = dpyinfo->visual->class;
3127 if (class != StaticColor
3128 && class != StaticGray
3129 && class != TrueColor)
3130 XFreeColors (dpy, cmap, &relief->pixel, 1, 0);
3131 relief->allocated_p = 0;
3134 /* Allocate new color. */
3135 xgcv.foreground = default_pixel;
3136 pixel = background;
3137 if (dpyinfo->n_planes != 1
3138 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3140 relief->allocated_p = 1;
3141 xgcv.foreground = relief->pixel = pixel;
3144 if (relief->gc == 0)
3146 xgcv.stipple = dpyinfo->gray;
3147 mask |= GCStipple;
3148 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3150 else
3151 XChangeGC (dpy, relief->gc, mask, &xgcv);
3155 /* Set up colors for the relief lines around glyph string S. */
3157 static void
3158 x_setup_relief_colors (s)
3159 struct glyph_string *s;
3161 struct x_output *di = s->f->output_data.x;
3162 unsigned long color;
3164 if (s->face->use_box_color_for_shadows_p)
3165 color = s->face->box_color;
3166 else
3168 XGCValues xgcv;
3170 /* Get the background color of the face. */
3171 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3172 color = xgcv.background;
3175 if (di->white_relief.gc == 0
3176 || color != di->relief_background)
3178 di->relief_background = color;
3179 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3180 WHITE_PIX_DEFAULT (s->f));
3181 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3182 BLACK_PIX_DEFAULT (s->f));
3187 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3188 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3189 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3190 relief. LEFT_P non-zero means draw a relief on the left side of
3191 the rectangle. RIGHT_P non-zero means draw a relief on the right
3192 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3193 when drawing. */
3195 static void
3196 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3197 raised_p, left_p, right_p, clip_rect)
3198 struct frame *f;
3199 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3200 XRectangle *clip_rect;
3202 int i;
3203 GC gc;
3205 if (raised_p)
3206 gc = f->output_data.x->white_relief.gc;
3207 else
3208 gc = f->output_data.x->black_relief.gc;
3209 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3211 /* Top. */
3212 for (i = 0; i < width; ++i)
3213 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3214 left_x + i * left_p, top_y + i,
3215 right_x + 1 - i * right_p, top_y + i);
3217 /* Left. */
3218 if (left_p)
3219 for (i = 0; i < width; ++i)
3220 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3221 left_x + i, top_y + i, left_x + i, bottom_y - i);
3223 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3224 if (raised_p)
3225 gc = f->output_data.x->black_relief.gc;
3226 else
3227 gc = f->output_data.x->white_relief.gc;
3228 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3230 /* Bottom. */
3231 for (i = 0; i < width; ++i)
3232 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3233 left_x + i * left_p, bottom_y - i,
3234 right_x + 1 - i * right_p, bottom_y - i);
3236 /* Right. */
3237 if (right_p)
3238 for (i = 0; i < width; ++i)
3239 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3240 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3242 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3246 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3247 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3248 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3249 left side of the rectangle. RIGHT_P non-zero means draw a line
3250 on the right side of the rectangle. CLIP_RECT is the clipping
3251 rectangle to use when drawing. */
3253 static void
3254 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3255 left_p, right_p, clip_rect)
3256 struct glyph_string *s;
3257 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3258 XRectangle *clip_rect;
3260 XGCValues xgcv;
3262 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3263 XSetForeground (s->display, s->gc, s->face->box_color);
3264 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3266 /* Top. */
3267 XFillRectangle (s->display, s->window, s->gc,
3268 left_x, top_y, right_x - left_x, width);
3270 /* Left. */
3271 if (left_p)
3272 XFillRectangle (s->display, s->window, s->gc,
3273 left_x, top_y, width, bottom_y - top_y);
3275 /* Bottom. */
3276 XFillRectangle (s->display, s->window, s->gc,
3277 left_x, bottom_y - width, right_x - left_x, width);
3279 /* Right. */
3280 if (right_p)
3281 XFillRectangle (s->display, s->window, s->gc,
3282 right_x - width, top_y, width, bottom_y - top_y);
3284 XSetForeground (s->display, s->gc, xgcv.foreground);
3285 XSetClipMask (s->display, s->gc, None);
3289 /* Draw a box around glyph string S. */
3291 static void
3292 x_draw_glyph_string_box (s)
3293 struct glyph_string *s;
3295 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3296 int left_p, right_p;
3297 struct glyph *last_glyph;
3298 XRectangle clip_rect;
3300 last_x = window_box_right (s->w, s->area);
3301 if (s->row->full_width_p
3302 && !s->w->pseudo_window_p)
3304 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3305 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3306 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3309 /* The glyph that may have a right box line. */
3310 last_glyph = (s->cmpcharp || s->img
3311 ? s->first_glyph
3312 : s->first_glyph + s->nchars - 1);
3314 width = s->face->box_line_width;
3315 raised_p = s->face->box == FACE_RAISED_BOX;
3316 left_x = s->x;
3317 right_x = ((s->row->full_width_p
3318 ? last_x - 1
3319 : min (last_x, s->x + s->background_width) - 1));
3320 top_y = s->y;
3321 bottom_y = top_y + s->height - 1;
3323 left_p = (s->first_glyph->left_box_line_p
3324 || (s->hl == DRAW_MOUSE_FACE
3325 && (s->prev == NULL
3326 || s->prev->hl != s->hl)));
3327 right_p = (last_glyph->right_box_line_p
3328 || (s->hl == DRAW_MOUSE_FACE
3329 && (s->next == NULL
3330 || s->next->hl != s->hl)));
3332 x_get_glyph_string_clip_rect (s, &clip_rect);
3334 if (s->face->box == FACE_SIMPLE_BOX)
3335 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3336 left_p, right_p, &clip_rect);
3337 else
3339 x_setup_relief_colors (s);
3340 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3341 width, raised_p, left_p, right_p, &clip_rect);
3346 /* Draw foreground of image glyph string S. */
3348 static void
3349 x_draw_image_foreground (s)
3350 struct glyph_string *s;
3352 int x;
3353 int y = s->ybase - IMAGE_ASCENT (s->img);
3355 /* If first glyph of S has a left box line, start drawing it to the
3356 right of that line. */
3357 if (s->face->box != FACE_NO_BOX
3358 && s->first_glyph->left_box_line_p)
3359 x = s->x + s->face->box_line_width;
3360 else
3361 x = s->x;
3363 /* If there is a margin around the image, adjust x- and y-position
3364 by that margin. */
3365 if (s->img->margin)
3367 x += s->img->margin;
3368 y += s->img->margin;
3371 if (s->img->pixmap)
3373 if (s->img->mask)
3375 /* We can't set both a clip mask and use XSetClipRectangles
3376 because the latter also sets a clip mask. We also can't
3377 trust on the shape extension to be available
3378 (XShapeCombineRegion). So, compute the rectangle to draw
3379 manually. */
3380 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3381 | GCFunction);
3382 XGCValues xgcv;
3383 XRectangle clip_rect, image_rect, r;
3385 xgcv.clip_mask = s->img->mask;
3386 xgcv.clip_x_origin = x;
3387 xgcv.clip_y_origin = y;
3388 xgcv.function = GXcopy;
3389 XChangeGC (s->display, s->gc, mask, &xgcv);
3391 x_get_glyph_string_clip_rect (s, &clip_rect);
3392 image_rect.x = x;
3393 image_rect.y = y;
3394 image_rect.width = s->img->width;
3395 image_rect.height = s->img->height;
3396 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3397 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3398 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3400 else
3402 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3403 0, 0, s->img->width, s->img->height, x, y);
3405 /* When the image has a mask, we can expect that at
3406 least part of a mouse highlight or a block cursor will
3407 be visible. If the image doesn't have a mask, make
3408 a block cursor visible by drawing a rectangle around
3409 the image. I believe it's looking better if we do
3410 nothing here for mouse-face. */
3411 if (s->hl == DRAW_CURSOR)
3412 XDrawRectangle (s->display, s->window, s->gc, x, y,
3413 s->img->width - 1, s->img->height - 1);
3416 else
3417 /* Draw a rectangle if image could not be loaded. */
3418 XDrawRectangle (s->display, s->window, s->gc, x, y,
3419 s->img->width - 1, s->img->height - 1);
3423 /* Draw a relief around the image glyph string S. */
3425 static void
3426 x_draw_image_relief (s)
3427 struct glyph_string *s;
3429 int x0, y0, x1, y1, thick, raised_p;
3430 XRectangle r;
3431 int x;
3432 int y = s->ybase - IMAGE_ASCENT (s->img);
3434 /* If first glyph of S has a left box line, start drawing it to the
3435 right of that line. */
3436 if (s->face->box != FACE_NO_BOX
3437 && s->first_glyph->left_box_line_p)
3438 x = s->x + s->face->box_line_width;
3439 else
3440 x = s->x;
3442 /* If there is a margin around the image, adjust x- and y-position
3443 by that margin. */
3444 if (s->img->margin)
3446 x += s->img->margin;
3447 y += s->img->margin;
3450 if (s->hl == DRAW_IMAGE_SUNKEN
3451 || s->hl == DRAW_IMAGE_RAISED)
3453 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3454 raised_p = s->hl == DRAW_IMAGE_RAISED;
3456 else
3458 thick = abs (s->img->relief);
3459 raised_p = s->img->relief > 0;
3462 x0 = x - thick;
3463 y0 = y - thick;
3464 x1 = x + s->img->width + thick - 1;
3465 y1 = y + s->img->height + thick - 1;
3467 x_setup_relief_colors (s);
3468 x_get_glyph_string_clip_rect (s, &r);
3469 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3473 /* Draw the foreground of image glyph string S to PIXMAP. */
3475 static void
3476 x_draw_image_foreground_1 (s, pixmap)
3477 struct glyph_string *s;
3478 Pixmap pixmap;
3480 int x;
3481 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3483 /* If first glyph of S has a left box line, start drawing it to the
3484 right of that line. */
3485 if (s->face->box != FACE_NO_BOX
3486 && s->first_glyph->left_box_line_p)
3487 x = s->face->box_line_width;
3488 else
3489 x = 0;
3491 /* If there is a margin around the image, adjust x- and y-position
3492 by that margin. */
3493 if (s->img->margin)
3495 x += s->img->margin;
3496 y += s->img->margin;
3499 if (s->img->pixmap)
3501 if (s->img->mask)
3503 /* We can't set both a clip mask and use XSetClipRectangles
3504 because the latter also sets a clip mask. We also can't
3505 trust on the shape extension to be available
3506 (XShapeCombineRegion). So, compute the rectangle to draw
3507 manually. */
3508 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3509 | GCFunction);
3510 XGCValues xgcv;
3512 xgcv.clip_mask = s->img->mask;
3513 xgcv.clip_x_origin = x;
3514 xgcv.clip_y_origin = y;
3515 xgcv.function = GXcopy;
3516 XChangeGC (s->display, s->gc, mask, &xgcv);
3518 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3519 0, 0, s->img->width, s->img->height, x, y);
3520 XSetClipMask (s->display, s->gc, None);
3522 else
3524 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3525 0, 0, s->img->width, s->img->height, x, y);
3527 /* When the image has a mask, we can expect that at
3528 least part of a mouse highlight or a block cursor will
3529 be visible. If the image doesn't have a mask, make
3530 a block cursor visible by drawing a rectangle around
3531 the image. I believe it's looking better if we do
3532 nothing here for mouse-face. */
3533 if (s->hl == DRAW_CURSOR)
3534 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3535 s->img->width - 1, s->img->height - 1);
3538 else
3539 /* Draw a rectangle if image could not be loaded. */
3540 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3541 s->img->width - 1, s->img->height - 1);
3545 /* Draw part of the background of glyph string S. X, Y, W, and H
3546 give the rectangle to draw. */
3548 static void
3549 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3550 struct glyph_string *s;
3551 int x, y, w, h;
3553 if (s->stippled_p)
3555 /* Fill background with a stipple pattern. */
3556 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3557 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3558 XSetFillStyle (s->display, s->gc, FillSolid);
3560 else
3561 x_clear_glyph_string_rect (s, x, y, w, h);
3565 /* Draw image glyph string S.
3567 s->y
3568 s->x +-------------------------
3569 | s->face->box
3571 | +-------------------------
3572 | | s->img->margin
3574 | | +-------------------
3575 | | | the image
3579 static void
3580 x_draw_image_glyph_string (s)
3581 struct glyph_string *s;
3583 int x, y;
3584 int box_line_width = s->face->box_line_width;
3585 int margin = s->img->margin;
3586 int height;
3587 Pixmap pixmap = None;
3589 height = s->height - 2 * box_line_width;
3591 /* Fill background with face under the image. Do it only if row is
3592 taller than image or if image has a clip mask to reduce
3593 flickering. */
3594 s->stippled_p = s->face->stipple != 0;
3595 if (height > s->img->height
3596 || margin
3597 || s->img->mask
3598 || s->img->pixmap == 0
3599 || s->width != s->background_width)
3601 if (box_line_width && s->first_glyph->left_box_line_p)
3602 x = s->x + box_line_width;
3603 else
3604 x = s->x;
3606 y = s->y + box_line_width;
3608 if (s->img->mask)
3610 /* Create a pixmap as large as the glyph string Fill it with
3611 the background color. Copy the image to it, using its
3612 mask. Copy the temporary pixmap to the display. */
3613 Screen *screen = FRAME_X_SCREEN (s->f);
3614 int depth = DefaultDepthOfScreen (screen);
3616 /* Create a pixmap as large as the glyph string. */
3617 pixmap = XCreatePixmap (s->display, s->window,
3618 s->background_width,
3619 s->height, depth);
3621 /* Don't clip in the following because we're working on the
3622 pixmap. */
3623 XSetClipMask (s->display, s->gc, None);
3625 /* Fill the pixmap with the background color/stipple. */
3626 if (s->stippled_p)
3628 /* Fill background with a stipple pattern. */
3629 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3630 XFillRectangle (s->display, pixmap, s->gc,
3631 0, 0, s->background_width, s->height);
3632 XSetFillStyle (s->display, s->gc, FillSolid);
3634 else
3636 XGCValues xgcv;
3637 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3638 &xgcv);
3639 XSetForeground (s->display, s->gc, xgcv.background);
3640 XFillRectangle (s->display, pixmap, s->gc,
3641 0, 0, s->background_width, s->height);
3642 XSetForeground (s->display, s->gc, xgcv.foreground);
3645 else
3646 /* Implementation idea: Is it possible to construct a mask?
3647 We could look at the color at the margins of the image, and
3648 say that this color is probably the background color of the
3649 image. */
3650 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3652 s->background_filled_p = 1;
3655 /* Draw the foreground. */
3656 if (pixmap != None)
3658 x_draw_image_foreground_1 (s, pixmap);
3659 x_set_glyph_string_clipping (s);
3660 XCopyArea (s->display, pixmap, s->window, s->gc,
3661 0, 0, s->background_width, s->height, s->x, s->y);
3662 XFreePixmap (s->display, pixmap);
3664 else
3665 x_draw_image_foreground (s);
3667 /* If we must draw a relief around the image, do it. */
3668 if (s->img->relief
3669 || s->hl == DRAW_IMAGE_RAISED
3670 || s->hl == DRAW_IMAGE_SUNKEN)
3671 x_draw_image_relief (s);
3675 /* Draw stretch glyph string S. */
3677 static void
3678 x_draw_stretch_glyph_string (s)
3679 struct glyph_string *s;
3681 xassert (s->first_glyph->type == STRETCH_GLYPH);
3682 s->stippled_p = s->face->stipple != 0;
3684 if (s->hl == DRAW_CURSOR
3685 && !x_stretch_cursor_p)
3687 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3688 as wide as the stretch glyph. */
3689 int width = min (CANON_X_UNIT (s->f), s->background_width);
3691 /* Draw cursor. */
3692 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3694 /* Clear rest using the GC of the original non-cursor face. */
3695 if (width < s->background_width)
3697 GC gc = s->face->gc;
3698 int x = s->x + width, y = s->y;
3699 int w = s->background_width - width, h = s->height;
3700 XRectangle r;
3702 x_get_glyph_string_clip_rect (s, &r);
3703 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
3705 if (s->face->stipple)
3707 /* Fill background with a stipple pattern. */
3708 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3709 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3710 XSetFillStyle (s->display, gc, FillSolid);
3712 else
3714 XGCValues xgcv;
3715 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3716 XSetForeground (s->display, gc, xgcv.background);
3717 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3718 XSetForeground (s->display, gc, xgcv.foreground);
3722 else
3723 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3724 s->height);
3726 s->background_filled_p = 1;
3730 /* Draw glyph string S. */
3732 static void
3733 x_draw_glyph_string (s)
3734 struct glyph_string *s;
3736 /* If S draws into the background of its successor, draw the
3737 background of the successor first so that S can draw into it.
3738 This makes S->next use XDrawString instead of XDrawImageString. */
3739 if (s->next && s->right_overhang && !s->for_overlaps_p)
3741 xassert (s->next->img == NULL);
3742 x_set_glyph_string_gc (s->next);
3743 x_set_glyph_string_clipping (s->next);
3744 x_draw_glyph_string_background (s->next, 1);
3747 /* Set up S->gc, set clipping and draw S. */
3748 x_set_glyph_string_gc (s);
3749 x_set_glyph_string_clipping (s);
3751 switch (s->first_glyph->type)
3753 case IMAGE_GLYPH:
3754 x_draw_image_glyph_string (s);
3755 break;
3757 case STRETCH_GLYPH:
3758 x_draw_stretch_glyph_string (s);
3759 break;
3761 case CHAR_GLYPH:
3762 if (s->for_overlaps_p)
3763 s->background_filled_p = 1;
3764 else
3765 x_draw_glyph_string_background (s, 0);
3766 x_draw_glyph_string_foreground (s);
3767 break;
3769 default:
3770 abort ();
3773 if (!s->for_overlaps_p)
3775 /* Draw underline. */
3776 if (s->face->underline_p)
3778 unsigned long dy, h;
3780 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3781 h = 1;
3782 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
3783 dy = s->height - h;
3785 if (s->face->underline_defaulted_p)
3786 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3787 s->width, h);
3788 else
3790 XGCValues xgcv;
3791 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3792 XSetForeground (s->display, s->gc, s->face->underline_color);
3793 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3794 s->width, h);
3795 XSetForeground (s->display, s->gc, xgcv.foreground);
3799 /* Draw overline. */
3800 if (s->face->overline_p)
3802 unsigned long dy = 0, h = 1;
3804 if (s->face->overline_color_defaulted_p)
3805 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3806 s->width, h);
3807 else
3809 XGCValues xgcv;
3810 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3811 XSetForeground (s->display, s->gc, s->face->overline_color);
3812 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3813 s->width, h);
3814 XSetForeground (s->display, s->gc, xgcv.foreground);
3818 /* Draw strike-through. */
3819 if (s->face->strike_through_p)
3821 unsigned long h = 1;
3822 unsigned long dy = (s->height - h) / 2;
3824 if (s->face->strike_through_color_defaulted_p)
3825 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3826 s->width, h);
3827 else
3829 XGCValues xgcv;
3830 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3831 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3832 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3833 s->width, h);
3834 XSetForeground (s->display, s->gc, xgcv.foreground);
3838 /* Draw relief. */
3839 if (s->face->box != FACE_NO_BOX)
3840 x_draw_glyph_string_box (s);
3843 /* Reset clipping. */
3844 XSetClipMask (s->display, s->gc, None);
3848 /* A work-list entry used during the construction of glyph_string
3849 structures for a composite character. */
3851 struct work
3853 /* Pointer to composite char info defining has the composite
3854 character is drawn. */
3855 struct cmpchar_info *cmpcharp;
3857 /* Start index in compcharp->glyph[]. */
3858 int gidx;
3860 /* Next in stack. */
3861 struct work *next;
3865 static void x_fill_composite_glyph_string P_ ((struct glyph_string *,
3866 int, struct work **,
3867 struct work **, int));
3870 /* Load glyph string S with information from the top of *STACK for a
3871 composite character. FACE_ID is the id of the face in which S is
3872 drawn. *NEW is a pointer to a struct work not on the stack, that
3873 can be used if this function needs to push a new structure on the
3874 stack. If it uses it, *NEW is set to null. OVERLAPS_P non-zero
3875 means S should draw the foreground only, and use its lines physical
3876 height for clipping. */
3878 static void
3879 x_fill_composite_glyph_string (s, face_id, stack, new, overlaps_p)
3880 struct glyph_string *s;
3881 int face_id;
3882 struct work **stack, **new;
3883 int overlaps_p;
3885 int i, c;
3886 struct work *work;
3888 xassert (s && *new && *stack);
3890 s->for_overlaps_p = 1;
3892 /* Pop the work stack. */
3893 work = *stack;
3894 *stack = work->next;
3896 /* For all glyphs of cmpcharp->glyph, starting at the offset
3897 work->offset, until we reach the end of the definition or
3898 encounter another composite char, get the font and face to use,
3899 and add it to S. */
3900 for (i = work->gidx; i < work->cmpcharp->glyph_len; ++i)
3902 c = FAST_GLYPH_CHAR (work->cmpcharp->glyph[i]);
3903 if (CHAR_CHARSET (c) == CHARSET_COMPOSITION)
3904 break;
3905 s->face = x_get_char_face_and_encoding (s->f, c, face_id,
3906 s->char2b + s->nchars, 1);
3907 s->font = s->face->font;
3908 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3909 ++s->nchars;
3912 /* If we find another composite char in the glyph definition of
3913 work->cmpcharp, put back the rest of the glyphs on the work
3914 stack, and make a new entry for the composite char. */
3915 if (i < work->cmpcharp->glyph_len)
3917 /* Push back an unprocessed rest of this glyph spec. */
3918 if (i < work->cmpcharp->glyph_len - 1)
3920 work->gidx = i + 1;
3921 work->next = *stack;
3922 *stack = work;
3923 work = *new;
3924 *new = NULL;
3927 /* Make an entry for the composite char on the work stack. */
3928 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)];
3929 work->gidx = 0;
3930 work->next = *stack;
3931 *stack = work;
3934 /* The width of this glyph string equals the width of the first
3935 glyph. All characters are drawn at the same x-position. */
3936 s->width = s->first_glyph->pixel_width;
3938 /* If the specified font could not be loaded, use the frame's
3939 default font, but record the fact that we couldn't load it in
3940 the glyph string so that we can draw rectangles for the
3941 characters of the glyph string. */
3942 if (s->font == NULL)
3944 s->font_not_found_p = 1;
3945 s->font = FRAME_FONT (s->f);
3948 /* Adjust base line for subscript/superscript text. */
3949 s->ybase += s->first_glyph->voffset;
3951 xassert (s->face && s->face->gc);
3953 /* This glyph string must always be drawn with 16-bit functions. */
3954 s->two_byte_p = 1;
3958 /* Load glyph string S with a sequence of non-composite characters.
3959 FACE_ID is the face id of the string. START is the index of the
3960 first glyph to consider, END is the index of the last + 1.
3961 OVERLAPS_P non-zero means S should draw the foreground only, and
3962 use its lines physical height for clipping.
3964 Value is the index of the first glyph not in S. */
3966 static int
3967 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
3968 struct glyph_string *s;
3969 int face_id;
3970 int start, end, overlaps_p;
3972 struct glyph *glyph, *last;
3973 int voffset;
3975 xassert (s->charset != CHARSET_COMPOSITION);
3976 xassert (s->f == XFRAME (s->w->frame));
3977 xassert (s->nchars == 0);
3978 xassert (start >= 0 && end > start);
3980 s->for_overlaps_p = overlaps_p,
3981 glyph = s->row->glyphs[s->area] + start;
3982 last = s->row->glyphs[s->area] + end;
3983 voffset = glyph->voffset;
3985 while (glyph < last
3986 && glyph->type == CHAR_GLYPH
3987 && glyph->voffset == voffset
3988 /* Same face id implies same charset, nowadays. */
3989 && glyph->u.ch.face_id == face_id)
3991 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
3992 s->char2b + s->nchars);
3993 if (s->char2b[s->nchars].byte2 != 0)
3994 s->two_byte_p = 1;
3996 ++s->nchars;
3997 xassert (s->nchars <= end - start);
3998 s->width += glyph->pixel_width;
3999 ++glyph;
4002 s->font = s->face->font;
4003 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4005 /* If the specified font could not be loaded, use the frame's font,
4006 but record the fact that we couldn't load it in
4007 S->font_not_found_p so that we can draw rectangles for the
4008 characters of the glyph string. */
4009 if (s->font == NULL)
4011 s->font_not_found_p = 1;
4012 s->font = FRAME_FONT (s->f);
4015 /* Adjust base line for subscript/superscript text. */
4016 s->ybase += voffset;
4018 xassert (s->face && s->face->gc);
4019 return glyph - s->row->glyphs[s->area];
4023 /* Fill glyph string S from image glyph S->first_glyph. */
4025 static void
4026 x_fill_image_glyph_string (s)
4027 struct glyph_string *s;
4029 xassert (s->first_glyph->type == IMAGE_GLYPH);
4030 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img.id);
4031 xassert (s->img);
4032 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.img.face_id);
4033 s->font = s->face->font;
4034 s->width = s->first_glyph->pixel_width;
4036 /* Adjust base line for subscript/superscript text. */
4037 s->ybase += s->first_glyph->voffset;
4041 /* Fill glyph string S from stretch glyph S->first_glyph. */
4043 static void
4044 x_fill_stretch_glyph_string (s)
4045 struct glyph_string *s;
4047 xassert (s->first_glyph->type == STRETCH_GLYPH);
4048 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.stretch.face_id);
4049 s->font = s->face->font;
4050 s->width = s->first_glyph->pixel_width;
4052 /* Adjust base line for subscript/superscript text. */
4053 s->ybase += s->first_glyph->voffset;
4057 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4058 of XChar2b structures for S; it can't be allocated in
4059 x_init_glyph_string because it must be allocated via `alloca'. W
4060 is the window on which S is drawn. ROW and AREA are the glyph row
4061 and area within the row from which S is constructed. START is the
4062 index of the first glyph structure covered by S. HL is a
4063 face-override for drawing S. */
4065 static void
4066 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4067 struct glyph_string *s;
4068 XChar2b *char2b;
4069 struct window *w;
4070 struct glyph_row *row;
4071 enum glyph_row_area area;
4072 int start;
4073 enum draw_glyphs_face hl;
4075 bzero (s, sizeof *s);
4076 s->w = w;
4077 s->f = XFRAME (w->frame);
4078 s->display = FRAME_X_DISPLAY (s->f);
4079 s->window = FRAME_X_WINDOW (s->f);
4080 s->char2b = char2b;
4081 s->hl = hl;
4082 s->row = row;
4083 s->area = area;
4084 s->first_glyph = row->glyphs[area] + start;
4085 s->height = row->height;
4086 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4088 /* Display the internal border below the tool-bar window. */
4089 if (s->w == XWINDOW (s->f->tool_bar_window))
4090 s->y -= s->f->output_data.x->internal_border_width;
4092 s->ybase = s->y + row->ascent;
4096 /* Set background width of glyph string S. START is the index of the
4097 first glyph following S. LAST_X is the right-most x-position + 1
4098 in the drawing area. */
4100 static INLINE void
4101 x_set_glyph_string_background_width (s, start, last_x)
4102 struct glyph_string *s;
4103 int start;
4104 int last_x;
4106 /* If the face of this glyph string has to be drawn to the end of
4107 the drawing area, set S->extends_to_end_of_line_p. */
4108 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4110 if (start == s->row->used[s->area]
4111 && s->hl == DRAW_NORMAL_TEXT
4112 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4113 || s->face->background != default_face->background
4114 || s->face->stipple != default_face->stipple))
4115 s->extends_to_end_of_line_p = 1;
4117 /* If S extends its face to the end of the line, set its
4118 background_width to the distance to the right edge of the drawing
4119 area. */
4120 if (s->extends_to_end_of_line_p)
4121 s->background_width = last_x - s->x + 1;
4122 else
4123 s->background_width = s->width;
4127 /* Add a glyph string for a stretch glyph to the list of strings
4128 between HEAD and TAIL. START is the index of the stretch glyph in
4129 row area AREA of glyph row ROW. END is the index of the last glyph
4130 in that glyph row area. X is the current output position assigned
4131 to the new glyph string constructed. HL overrides that face of the
4132 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4133 is the right-most x-position of the drawing area. */
4135 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4136 and below -- keep them on one line. */
4137 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4138 do \
4140 s = (struct glyph_string *) alloca (sizeof *s); \
4141 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4142 x_fill_stretch_glyph_string (s); \
4143 x_append_glyph_string (&HEAD, &TAIL, s); \
4144 ++START; \
4145 s->x = (X); \
4147 while (0)
4150 /* Add a glyph string for an image glyph to the list of strings
4151 between HEAD and TAIL. START is the index of the image glyph in
4152 row area AREA of glyph row ROW. END is the index of the last glyph
4153 in that glyph row area. X is the current output position assigned
4154 to the new glyph string constructed. HL overrides that face of the
4155 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4156 is the right-most x-position of the drawing area. */
4158 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4159 do \
4161 s = (struct glyph_string *) alloca (sizeof *s); \
4162 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4163 x_fill_image_glyph_string (s); \
4164 x_append_glyph_string (&HEAD, &TAIL, s); \
4165 ++START; \
4166 s->x = (X); \
4168 while (0)
4171 /* Add a glyph string for a sequence of character glyphs to the list
4172 of strings between HEAD and TAIL. START is the index of the first
4173 glyph in row area AREA of glyph row ROW that is part of the new
4174 glyph string. END is the index of the last glyph in that glyph row
4175 area. X is the current output position assigned to the new glyph
4176 string constructed. HL overrides that face of the glyph; e.g. it
4177 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4178 right-most x-position of the drawing area. */
4180 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4181 do \
4183 int c, charset, face_id; \
4184 XChar2b *char2b; \
4186 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4187 charset = CHAR_CHARSET (c); \
4188 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4190 if (charset == CHARSET_COMPOSITION) \
4192 struct work *stack, *work, *new = NULL; \
4193 int n = 0; \
4194 struct glyph_string *first_s = NULL; \
4196 /* Push an initial entry for character c on the stack. */ \
4197 stack = NULL; \
4198 work = (struct work *) alloca (sizeof *work); \
4199 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \
4200 work->gidx = 0; \
4201 work->next = stack; \
4202 stack = work; \
4204 /* While the stack is not empty, append glyph_strings \
4205 to head/tail for glyphs to draw. */ \
4206 while (stack) \
4208 s = (struct glyph_string *) alloca (sizeof *s); \
4209 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \
4210 * sizeof (XChar2b)); \
4211 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4212 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4213 s->cmpcharp = stack->cmpcharp; \
4214 s->gidx = stack->gidx; \
4215 s->charset = charset; \
4216 s->x = (X); \
4218 if (n == 0) \
4220 /* Don't draw the background except for the \
4221 first glyph string. */ \
4222 s->background_filled_p = n > 0; \
4223 first_s = s; \
4225 ++n; \
4227 if (new == NULL) \
4228 new = (struct work *) alloca (sizeof *new); \
4229 x_fill_composite_glyph_string (s, face_id, &stack, \
4230 &new, OVERLAPS_P); \
4233 ++START; \
4234 s = first_s; \
4236 else \
4238 s = (struct glyph_string *) alloca (sizeof *s); \
4239 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4240 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4241 x_append_glyph_string (&HEAD, &TAIL, s); \
4242 s->charset = charset; \
4243 s->x = (X); \
4244 START = x_fill_glyph_string (s, face_id, START, END, \
4245 OVERLAPS_P); \
4248 while (0)
4251 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4252 of AREA of glyph row ROW on window W between indices START and END.
4253 HL overrides the face for drawing glyph strings, e.g. it is
4254 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4255 x-positions of the drawing area.
4257 This is an ugly monster macro construct because we must use alloca
4258 to allocate glyph strings (because x_draw_glyphs can be called
4259 asynchronously). */
4261 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4262 do \
4264 HEAD = TAIL = NULL; \
4265 while (START < END) \
4267 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4268 switch (first_glyph->type) \
4270 case CHAR_GLYPH: \
4271 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4272 TAIL, HL, X, LAST_X, \
4273 OVERLAPS_P); \
4274 break; \
4276 case STRETCH_GLYPH: \
4277 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4278 HEAD, TAIL, HL, X, LAST_X); \
4279 break; \
4281 case IMAGE_GLYPH: \
4282 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4283 TAIL, HL, X, LAST_X); \
4284 break; \
4286 default: \
4287 abort (); \
4290 x_set_glyph_string_background_width (s, START, LAST_X); \
4291 (X) += s->width; \
4294 while (0)
4297 /* Draw glyphs between START and END in AREA of ROW on window W,
4298 starting at x-position X. X is relative to AREA in W. HL is a
4299 face-override with the following meaning:
4301 DRAW_NORMAL_TEXT draw normally
4302 DRAW_CURSOR draw in cursor face
4303 DRAW_MOUSE_FACE draw in mouse face.
4304 DRAW_INVERSE_VIDEO draw in mode line face
4305 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4306 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4308 If REAL_START is non-null, return in *REAL_START the real starting
4309 position for display. This can be different from START in case
4310 overlapping glyphs must be displayed. If REAL_END is non-null,
4311 return in *REAL_END the real end position for display. This can be
4312 different from END in case overlapping glyphs must be displayed.
4314 If OVERLAPS_P is non-zero, draw only the foreground of characters
4315 and clip to the physical height of ROW.
4317 Value is the x-position reached, relative to AREA of W. */
4319 static int
4320 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4321 overlaps_p)
4322 struct window *w;
4323 int x;
4324 struct glyph_row *row;
4325 enum glyph_row_area area;
4326 int start, end;
4327 enum draw_glyphs_face hl;
4328 int *real_start, *real_end;
4329 int overlaps_p;
4331 struct glyph_string *head, *tail;
4332 struct glyph_string *s;
4333 int last_x, area_width;
4334 int x_reached;
4335 int i, j;
4337 /* Let's rather be paranoid than getting a SEGV. */
4338 start = max (0, start);
4339 end = min (end, row->used[area]);
4340 if (real_start)
4341 *real_start = start;
4342 if (real_end)
4343 *real_end = end;
4345 /* Translate X to frame coordinates. Set last_x to the right
4346 end of the drawing area. */
4347 if (row->full_width_p)
4349 /* X is relative to the left edge of W, without scroll bars
4350 or flag areas. */
4351 struct frame *f = XFRAME (w->frame);
4352 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4353 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4355 x += window_left_x;
4356 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4357 last_x = window_left_x + area_width;
4359 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4361 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4362 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4363 last_x += width;
4364 else
4365 x -= width;
4368 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4369 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4371 else
4373 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4374 area_width = window_box_width (w, area);
4375 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4378 /* Build a doubly-linked list of glyph_string structures between
4379 head and tail from what we have to draw. Note that the macro
4380 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4381 the reason we use a separate variable `i'. */
4382 i = start;
4383 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4384 overlaps_p);
4385 if (tail)
4386 x_reached = tail->x + tail->background_width;
4387 else
4388 x_reached = x;
4390 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4391 the row, redraw some glyphs in front or following the glyph
4392 strings built above. */
4393 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4395 int dummy_x = 0;
4396 struct glyph_string *h, *t;
4398 /* Compute overhangs for all glyph strings. */
4399 for (s = head; s; s = s->next)
4400 x_compute_glyph_string_overhangs (s);
4402 /* Prepend glyph strings for glyphs in front of the first glyph
4403 string that are overwritten because of the first glyph
4404 string's left overhang. The background of all strings
4405 prepended must be drawn because the first glyph string
4406 draws over it. */
4407 i = x_left_overwritten (head);
4408 if (i >= 0)
4410 j = i;
4411 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4412 DRAW_NORMAL_TEXT, dummy_x, last_x,
4413 overlaps_p);
4414 start = i;
4415 if (real_start)
4416 *real_start = start;
4417 x_compute_overhangs_and_x (t, head->x, 1);
4418 x_prepend_glyph_string_lists (&head, &tail, h, t);
4421 /* Prepend glyph strings for glyphs in front of the first glyph
4422 string that overwrite that glyph string because of their
4423 right overhang. For these strings, only the foreground must
4424 be drawn, because it draws over the glyph string at `head'.
4425 The background must not be drawn because this would overwrite
4426 right overhangs of preceding glyphs for which no glyph
4427 strings exist. */
4428 i = x_left_overwriting (head);
4429 if (i >= 0)
4431 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4432 DRAW_NORMAL_TEXT, dummy_x, last_x,
4433 overlaps_p);
4434 for (s = h; s; s = s->next)
4435 s->background_filled_p = 1;
4436 if (real_start)
4437 *real_start = i;
4438 x_compute_overhangs_and_x (t, head->x, 1);
4439 x_prepend_glyph_string_lists (&head, &tail, h, t);
4442 /* Append glyphs strings for glyphs following the last glyph
4443 string tail that are overwritten by tail. The background of
4444 these strings has to be drawn because tail's foreground draws
4445 over it. */
4446 i = x_right_overwritten (tail);
4447 if (i >= 0)
4449 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4450 DRAW_NORMAL_TEXT, x, last_x,
4451 overlaps_p);
4452 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4453 x_append_glyph_string_lists (&head, &tail, h, t);
4454 if (real_end)
4455 *real_end = i;
4458 /* Append glyph strings for glyphs following the last glyph
4459 string tail that overwrite tail. The foreground of such
4460 glyphs has to be drawn because it writes into the background
4461 of tail. The background must not be drawn because it could
4462 paint over the foreground of following glyphs. */
4463 i = x_right_overwriting (tail);
4464 if (i >= 0)
4466 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4467 DRAW_NORMAL_TEXT, x, last_x,
4468 overlaps_p);
4469 for (s = h; s; s = s->next)
4470 s->background_filled_p = 1;
4471 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4472 x_append_glyph_string_lists (&head, &tail, h, t);
4473 if (real_end)
4474 *real_end = i;
4478 /* Draw all strings. */
4479 for (s = head; s; s = s->next)
4480 x_draw_glyph_string (s);
4482 /* Value is the x-position up to which drawn, relative to AREA of W.
4483 This doesn't include parts drawn because of overhangs. */
4484 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4485 if (!row->full_width_p)
4487 if (area > LEFT_MARGIN_AREA)
4488 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4489 if (area > TEXT_AREA)
4490 x_reached -= window_box_width (w, TEXT_AREA);
4492 return x_reached;
4496 /* Fix the display of area AREA of overlapping row ROW in window W. */
4498 static void
4499 x_fix_overlapping_area (w, row, area)
4500 struct window *w;
4501 struct glyph_row *row;
4502 enum glyph_row_area area;
4504 int i, x;
4506 BLOCK_INPUT;
4508 if (area == LEFT_MARGIN_AREA)
4509 x = 0;
4510 else if (area == TEXT_AREA)
4511 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4512 else
4513 x = (window_box_width (w, LEFT_MARGIN_AREA)
4514 + window_box_width (w, TEXT_AREA));
4516 for (i = 0; i < row->used[area];)
4518 if (row->glyphs[area][i].overlaps_vertically_p)
4520 int start = i, start_x = x;
4524 x += row->glyphs[area][i].pixel_width;
4525 ++i;
4527 while (i < row->used[area]
4528 && row->glyphs[area][i].overlaps_vertically_p);
4530 x_draw_glyphs (w, start_x, row, area, start, i,
4531 (row->inverse_p
4532 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4533 NULL, NULL, 1);
4535 else
4537 x += row->glyphs[area][i].pixel_width;
4538 ++i;
4542 UNBLOCK_INPUT;
4546 /* Output LEN glyphs starting at START at the nominal cursor position.
4547 Advance the nominal cursor over the text. The global variable
4548 updated_window contains the window being updated, updated_row is
4549 the glyph row being updated, and updated_area is the area of that
4550 row being updated. */
4552 static void
4553 x_write_glyphs (start, len)
4554 struct glyph *start;
4555 int len;
4557 int x, hpos, real_start, real_end;
4559 xassert (updated_window && updated_row);
4560 BLOCK_INPUT;
4562 /* Write glyphs. */
4564 hpos = start - updated_row->glyphs[updated_area];
4565 x = x_draw_glyphs (updated_window, output_cursor.x,
4566 updated_row, updated_area,
4567 hpos, hpos + len,
4568 (updated_row->inverse_p
4569 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4570 &real_start, &real_end, 0);
4572 /* If we drew over the cursor, note that it is not visible any more. */
4573 note_overwritten_text_cursor (updated_window, real_start,
4574 real_end - real_start);
4576 UNBLOCK_INPUT;
4578 /* Advance the output cursor. */
4579 output_cursor.hpos += len;
4580 output_cursor.x = x;
4584 /* Insert LEN glyphs from START at the nominal cursor position. */
4586 static void
4587 x_insert_glyphs (start, len)
4588 struct glyph *start;
4589 register int len;
4591 struct frame *f;
4592 struct window *w;
4593 int line_height, shift_by_width, shifted_region_width;
4594 struct glyph_row *row;
4595 struct glyph *glyph;
4596 int frame_x, frame_y, hpos, real_start, real_end;
4598 xassert (updated_window && updated_row);
4599 BLOCK_INPUT;
4600 w = updated_window;
4601 f = XFRAME (WINDOW_FRAME (w));
4603 /* Get the height of the line we are in. */
4604 row = updated_row;
4605 line_height = row->height;
4607 /* Get the width of the glyphs to insert. */
4608 shift_by_width = 0;
4609 for (glyph = start; glyph < start + len; ++glyph)
4610 shift_by_width += glyph->pixel_width;
4612 /* Get the width of the region to shift right. */
4613 shifted_region_width = (window_box_width (w, updated_area)
4614 - output_cursor.x
4615 - shift_by_width);
4617 /* Shift right. */
4618 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4619 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4620 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4621 f->output_data.x->normal_gc,
4622 frame_x, frame_y,
4623 shifted_region_width, line_height,
4624 frame_x + shift_by_width, frame_y);
4626 /* Write the glyphs. */
4627 hpos = start - row->glyphs[updated_area];
4628 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4629 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4630 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4632 /* Advance the output cursor. */
4633 output_cursor.hpos += len;
4634 output_cursor.x += shift_by_width;
4635 UNBLOCK_INPUT;
4639 /* Delete N glyphs at the nominal cursor position. Not implemented
4640 for X frames. */
4642 static void
4643 x_delete_glyphs (n)
4644 register int n;
4646 abort ();
4650 /* Erase the current text line from the nominal cursor position
4651 (inclusive) to pixel column TO_X (exclusive). The idea is that
4652 everything from TO_X onward is already erased.
4654 TO_X is a pixel position relative to updated_area of
4655 updated_window. TO_X == -1 means clear to the end of this area. */
4657 static void
4658 x_clear_end_of_line (to_x)
4659 int to_x;
4661 struct frame *f;
4662 struct window *w = updated_window;
4663 int max_x, min_y, max_y;
4664 int from_x, from_y, to_y;
4666 xassert (updated_window && updated_row);
4667 f = XFRAME (w->frame);
4669 if (updated_row->full_width_p)
4671 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4672 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4673 && !w->pseudo_window_p)
4674 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4676 else
4677 max_x = window_box_width (w, updated_area);
4678 max_y = window_text_bottom_y (w);
4680 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4681 of window. For TO_X > 0, truncate to end of drawing area. */
4682 if (to_x == 0)
4683 return;
4684 else if (to_x < 0)
4685 to_x = max_x;
4686 else
4687 to_x = min (to_x, max_x);
4689 to_y = min (max_y, output_cursor.y + updated_row->height);
4691 /* Notice if the cursor will be cleared by this operation. */
4692 if (!updated_row->full_width_p)
4693 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4695 from_x = output_cursor.x;
4697 /* Translate to frame coordinates. */
4698 if (updated_row->full_width_p)
4700 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4701 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4703 else
4705 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4706 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4709 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4710 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4711 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4713 /* Prevent inadvertently clearing to end of the X window. */
4714 if (to_x > from_x && to_y > from_y)
4716 BLOCK_INPUT;
4717 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4718 from_x, from_y, to_x - from_x, to_y - from_y,
4719 False);
4720 UNBLOCK_INPUT;
4725 /* Clear entire frame. If updating_frame is non-null, clear that
4726 frame. Otherwise clear the selected frame. */
4728 static void
4729 x_clear_frame ()
4731 struct frame *f;
4733 if (updating_frame)
4734 f = updating_frame;
4735 else
4736 f = SELECTED_FRAME ();
4738 /* Clearing the frame will erase any cursor, so mark them all as no
4739 longer visible. */
4740 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4741 output_cursor.hpos = output_cursor.vpos = 0;
4742 output_cursor.x = -1;
4744 /* We don't set the output cursor here because there will always
4745 follow an explicit cursor_to. */
4746 BLOCK_INPUT;
4747 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4749 /* We have to clear the scroll bars, too. If we have changed
4750 colors or something like that, then they should be notified. */
4751 x_scroll_bar_clear (f);
4753 XFlush (FRAME_X_DISPLAY (f));
4754 UNBLOCK_INPUT;
4759 /* Invert the middle quarter of the frame for .15 sec. */
4761 /* We use the select system call to do the waiting, so we have to make
4762 sure it's available. If it isn't, we just won't do visual bells. */
4764 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4767 /* Subtract the `struct timeval' values X and Y, storing the result in
4768 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4770 static int
4771 timeval_subtract (result, x, y)
4772 struct timeval *result, x, y;
4774 /* Perform the carry for the later subtraction by updating y. This
4775 is safer because on some systems the tv_sec member is unsigned. */
4776 if (x.tv_usec < y.tv_usec)
4778 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4779 y.tv_usec -= 1000000 * nsec;
4780 y.tv_sec += nsec;
4783 if (x.tv_usec - y.tv_usec > 1000000)
4785 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4786 y.tv_usec += 1000000 * nsec;
4787 y.tv_sec -= nsec;
4790 /* Compute the time remaining to wait. tv_usec is certainly
4791 positive. */
4792 result->tv_sec = x.tv_sec - y.tv_sec;
4793 result->tv_usec = x.tv_usec - y.tv_usec;
4795 /* Return indication of whether the result should be considered
4796 negative. */
4797 return x.tv_sec < y.tv_sec;
4800 void
4801 XTflash (f)
4802 struct frame *f;
4804 BLOCK_INPUT;
4807 GC gc;
4809 /* Create a GC that will use the GXxor function to flip foreground
4810 pixels into background pixels. */
4812 XGCValues values;
4814 values.function = GXxor;
4815 values.foreground = (f->output_data.x->foreground_pixel
4816 ^ f->output_data.x->background_pixel);
4818 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4819 GCFunction | GCForeground, &values);
4823 /* Get the height not including a menu bar widget. */
4824 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
4825 /* Height of each line to flash. */
4826 int flash_height = FRAME_LINE_HEIGHT (f);
4827 /* These will be the left and right margins of the rectangles. */
4828 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4829 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4831 int width;
4833 /* Don't flash the area between a scroll bar and the frame
4834 edge it is next to. */
4835 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4837 case vertical_scroll_bar_left:
4838 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4839 break;
4841 case vertical_scroll_bar_right:
4842 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4843 break;
4845 default:
4846 break;
4849 width = flash_right - flash_left;
4851 /* If window is tall, flash top and bottom line. */
4852 if (height > 3 * FRAME_LINE_HEIGHT (f))
4854 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4855 flash_left,
4856 (FRAME_INTERNAL_BORDER_WIDTH (f)
4857 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
4858 width, flash_height);
4859 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4860 flash_left,
4861 (height - flash_height
4862 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4863 width, flash_height);
4865 else
4866 /* If it is short, flash it all. */
4867 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4868 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4869 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4871 x_flush (f);
4874 struct timeval wakeup;
4876 EMACS_GET_TIME (wakeup);
4878 /* Compute time to wait until, propagating carry from usecs. */
4879 wakeup.tv_usec += 150000;
4880 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4881 wakeup.tv_usec %= 1000000;
4883 /* Keep waiting until past the time wakeup. */
4884 while (1)
4886 struct timeval timeout;
4888 EMACS_GET_TIME (timeout);
4890 /* In effect, timeout = wakeup - timeout.
4891 Break if result would be negative. */
4892 if (timeval_subtract (&timeout, wakeup, timeout))
4893 break;
4895 /* Try to wait that long--but we might wake up sooner. */
4896 select (0, NULL, NULL, NULL, &timeout);
4900 /* If window is tall, flash top and bottom line. */
4901 if (height > 3 * FRAME_LINE_HEIGHT (f))
4903 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4904 flash_left,
4905 (FRAME_INTERNAL_BORDER_WIDTH (f)
4906 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
4907 width, flash_height);
4908 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4909 flash_left,
4910 (height - flash_height
4911 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4912 width, flash_height);
4914 else
4915 /* If it is short, flash it all. */
4916 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4917 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4918 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4920 XFreeGC (FRAME_X_DISPLAY (f), gc);
4921 x_flush (f);
4925 UNBLOCK_INPUT;
4928 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4931 /* Make audible bell. */
4933 void
4934 XTring_bell ()
4936 struct frame *f = SELECTED_FRAME ();
4938 if (FRAME_X_DISPLAY (f))
4940 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4941 if (visible_bell)
4942 XTflash (f);
4943 else
4944 #endif
4946 BLOCK_INPUT;
4947 XBell (FRAME_X_DISPLAY (f), 0);
4948 XFlush (FRAME_X_DISPLAY (f));
4949 UNBLOCK_INPUT;
4955 /* Specify how many text lines, from the top of the window,
4956 should be affected by insert-lines and delete-lines operations.
4957 This, and those operations, are used only within an update
4958 that is bounded by calls to x_update_begin and x_update_end. */
4960 static void
4961 XTset_terminal_window (n)
4962 register int n;
4964 /* This function intentionally left blank. */
4969 /***********************************************************************
4970 Line Dance
4971 ***********************************************************************/
4973 /* Perform an insert-lines or delete-lines operation, inserting N
4974 lines or deleting -N lines at vertical position VPOS. */
4976 static void
4977 x_ins_del_lines (vpos, n)
4978 int vpos, n;
4980 abort ();
4984 /* Scroll part of the display as described by RUN. */
4986 static void
4987 x_scroll_run (w, run)
4988 struct window *w;
4989 struct run *run;
4991 struct frame *f = XFRAME (w->frame);
4992 int x, y, width, height, from_y, to_y, bottom_y;
4994 /* Get frame-relative bounding box of the text display area of W,
4995 without mode lines. Include in this box the flags areas to the
4996 left and right of W. */
4997 window_box (w, -1, &x, &y, &width, &height);
4998 width += FRAME_X_FLAGS_AREA_WIDTH (f);
4999 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5001 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5002 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5003 bottom_y = y + height;
5005 if (to_y < from_y)
5007 /* Scrolling up. Make sure we don't copy part of the mode
5008 line at the bottom. */
5009 if (from_y + run->height > bottom_y)
5010 height = bottom_y - from_y;
5011 else
5012 height = run->height;
5014 else
5016 /* Scolling down. Make sure we don't copy over the mode line.
5017 at the bottom. */
5018 if (to_y + run->height > bottom_y)
5019 height = bottom_y - to_y;
5020 else
5021 height = run->height;
5024 BLOCK_INPUT;
5026 /* Cursor off. Will be switched on again in x_update_window_end. */
5027 updated_window = w;
5028 x_clear_cursor (w);
5030 XCopyArea (FRAME_X_DISPLAY (f),
5031 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5032 f->output_data.x->normal_gc,
5033 x, from_y,
5034 width, height,
5035 x, to_y);
5037 UNBLOCK_INPUT;
5042 /***********************************************************************
5043 Exposure Events
5044 ***********************************************************************/
5046 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5047 corner of the exposed rectangle. W and H are width and height of
5048 the exposed area. All are pixel values. W or H zero means redraw
5049 the entire frame. */
5051 static void
5052 expose_frame (f, x, y, w, h)
5053 struct frame *f;
5054 int x, y, w, h;
5056 XRectangle r;
5058 TRACE ((stderr, "expose_frame "));
5060 /* No need to redraw if frame will be redrawn soon. */
5061 if (FRAME_GARBAGED_P (f))
5063 TRACE ((stderr, " garbaged\n"));
5064 return;
5067 /* If basic faces haven't been realized yet, there is no point in
5068 trying to redraw anything. This can happen when we get an expose
5069 event while Emacs is starting, e.g. by moving another window. */
5070 if (FRAME_FACE_CACHE (f) == NULL
5071 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5073 TRACE ((stderr, " no faces\n"));
5074 return;
5077 if (w == 0 || h == 0)
5079 r.x = r.y = 0;
5080 r.width = CANON_X_UNIT (f) * f->width;
5081 r.height = CANON_Y_UNIT (f) * f->height;
5083 else
5085 r.x = x;
5086 r.y = y;
5087 r.width = w;
5088 r.height = h;
5091 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5092 expose_window_tree (XWINDOW (f->root_window), &r);
5094 if (WINDOWP (f->tool_bar_window))
5096 struct window *w = XWINDOW (f->tool_bar_window);
5097 XRectangle window_rect;
5098 XRectangle intersection_rect;
5099 int window_x, window_y, window_width, window_height;
5102 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5103 window_rect.x = window_x;
5104 window_rect.y = window_y;
5105 window_rect.width = window_width;
5106 window_rect.height = window_height;
5108 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5109 expose_window (w, &intersection_rect);
5112 #ifndef USE_X_TOOLKIT
5113 if (WINDOWP (f->menu_bar_window))
5115 struct window *w = XWINDOW (f->menu_bar_window);
5116 XRectangle window_rect;
5117 XRectangle intersection_rect;
5118 int window_x, window_y, window_width, window_height;
5121 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5122 window_rect.x = window_x;
5123 window_rect.y = window_y;
5124 window_rect.width = window_width;
5125 window_rect.height = window_height;
5127 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5128 expose_window (w, &intersection_rect);
5130 #endif /* not USE_X_TOOLKIT */
5134 /* Redraw (parts) of all windows in the window tree rooted at W that
5135 intersect R. R contains frame pixel coordinates. */
5137 static void
5138 expose_window_tree (w, r)
5139 struct window *w;
5140 XRectangle *r;
5142 while (w)
5144 if (!NILP (w->hchild))
5145 expose_window_tree (XWINDOW (w->hchild), r);
5146 else if (!NILP (w->vchild))
5147 expose_window_tree (XWINDOW (w->vchild), r);
5148 else
5150 XRectangle window_rect;
5151 XRectangle intersection_rect;
5152 struct frame *f = XFRAME (w->frame);
5153 int window_x, window_y, window_width, window_height;
5155 /* Frame-relative pixel rectangle of W. */
5156 window_box (w, -1, &window_x, &window_y, &window_width,
5157 &window_height);
5158 window_rect.x
5159 = (window_x
5160 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5161 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5162 window_rect.y = window_y;
5163 window_rect.width
5164 = (window_width
5165 + FRAME_X_FLAGS_AREA_WIDTH (f)
5166 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5167 window_rect.height
5168 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5170 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5171 expose_window (w, &intersection_rect);
5174 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5179 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5180 which intersects rectangle R. R is in window-relative coordinates. */
5182 static void
5183 expose_area (w, row, r, area)
5184 struct window *w;
5185 struct glyph_row *row;
5186 XRectangle *r;
5187 enum glyph_row_area area;
5189 int x;
5190 struct glyph *first = row->glyphs[area];
5191 struct glyph *end = row->glyphs[area] + row->used[area];
5192 struct glyph *last;
5193 int first_x;
5195 /* Set x to the window-relative start position for drawing glyphs of
5196 AREA. The first glyph of the text area can be partially visible.
5197 The first glyphs of other areas cannot. */
5198 if (area == LEFT_MARGIN_AREA)
5199 x = 0;
5200 else if (area == TEXT_AREA)
5201 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5202 else
5203 x = (window_box_width (w, LEFT_MARGIN_AREA)
5204 + window_box_width (w, TEXT_AREA));
5206 if (area == TEXT_AREA && row->fill_line_p)
5207 /* If row extends face to end of line write the whole line. */
5208 x_draw_glyphs (w, x, row, area,
5209 0, row->used[area],
5210 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5211 NULL, NULL, 0);
5212 else
5214 /* Find the first glyph that must be redrawn. */
5215 while (first < end
5216 && x + first->pixel_width < r->x)
5218 x += first->pixel_width;
5219 ++first;
5222 /* Find the last one. */
5223 last = first;
5224 first_x = x;
5225 while (last < end
5226 && x < r->x + r->width)
5228 x += last->pixel_width;
5229 ++last;
5232 /* Repaint. */
5233 if (last > first)
5234 x_draw_glyphs (w, first_x, row, area,
5235 first - row->glyphs[area],
5236 last - row->glyphs[area],
5237 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5238 NULL, NULL, 0);
5243 /* Redraw the parts of the glyph row ROW on window W intersecting
5244 rectangle R. R is in window-relative coordinates. */
5246 static void
5247 expose_line (w, row, r)
5248 struct window *w;
5249 struct glyph_row *row;
5250 XRectangle *r;
5252 xassert (row->enabled_p);
5254 if (row->mode_line_p || w->pseudo_window_p)
5255 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5256 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5257 NULL, NULL, 0);
5258 else
5260 if (row->used[LEFT_MARGIN_AREA])
5261 expose_area (w, row, r, LEFT_MARGIN_AREA);
5262 if (row->used[TEXT_AREA])
5263 expose_area (w, row, r, TEXT_AREA);
5264 if (row->used[RIGHT_MARGIN_AREA])
5265 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5266 x_draw_row_bitmaps (w, row);
5271 /* Return non-zero if W's cursor intersects rectangle R. */
5273 static int
5274 x_phys_cursor_in_rect_p (w, r)
5275 struct window *w;
5276 XRectangle *r;
5278 XRectangle cr, result;
5279 struct glyph *cursor_glyph;
5281 cursor_glyph = get_phys_cursor_glyph (w);
5282 if (cursor_glyph)
5284 cr.x = w->phys_cursor.x;
5285 cr.y = w->phys_cursor.y;
5286 cr.width = cursor_glyph->pixel_width;
5287 cr.height = w->phys_cursor_height;
5288 return x_intersect_rectangles (&cr, r, &result);
5290 else
5291 return 0;
5295 /* Redraw a rectangle of window W. R is a rectangle in window
5296 relative coordinates. Call this function with input blocked. */
5298 static void
5299 expose_window (w, r)
5300 struct window *w;
5301 XRectangle *r;
5303 struct glyph_row *row;
5304 int y;
5305 int yb = window_text_bottom_y (w);
5306 int cursor_cleared_p;
5308 /* If window is not yet fully initialized, do nothing. This can
5309 happen when toolkit scroll bars are used and a window is split.
5310 Reconfiguring the scroll bar will generate an expose for a newly
5311 created window. */
5312 if (w->current_matrix == NULL)
5313 return;
5315 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5316 r->x, r->y, r->width, r->height));
5318 /* Convert to window coordinates. */
5319 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5320 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5322 /* Turn off the cursor. */
5323 if (!w->pseudo_window_p
5324 && x_phys_cursor_in_rect_p (w, r))
5326 x_clear_cursor (w);
5327 cursor_cleared_p = 1;
5329 else
5330 cursor_cleared_p = 0;
5332 /* Find the first row intersecting the rectangle R. */
5333 row = w->current_matrix->rows;
5334 y = 0;
5335 while (row->enabled_p
5336 && y < yb
5337 && y + row->height < r->y)
5339 y += row->height;
5340 ++row;
5343 /* Display the text in the rectangle, one text line at a time. */
5344 while (row->enabled_p
5345 && y < yb
5346 && y < r->y + r->height)
5348 expose_line (w, row, r);
5349 y += row->height;
5350 ++row;
5353 /* Display the mode line if there is one. */
5354 if (WINDOW_WANTS_MODELINE_P (w)
5355 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5356 row->enabled_p)
5357 && row->y < r->y + r->height)
5358 expose_line (w, row, r);
5360 if (!w->pseudo_window_p)
5362 /* Draw border between windows. */
5363 x_draw_vertical_border (w);
5365 /* Turn the cursor on again. */
5366 if (cursor_cleared_p)
5367 x_update_window_cursor (w, 1);
5372 /* Determine the intersection of two rectangles R1 and R2. Return
5373 the intersection in *RESULT. Value is non-zero if RESULT is not
5374 empty. */
5376 static int
5377 x_intersect_rectangles (r1, r2, result)
5378 XRectangle *r1, *r2, *result;
5380 XRectangle *left, *right;
5381 XRectangle *upper, *lower;
5382 int intersection_p = 0;
5384 /* Rearrange so that R1 is the left-most rectangle. */
5385 if (r1->x < r2->x)
5386 left = r1, right = r2;
5387 else
5388 left = r2, right = r1;
5390 /* X0 of the intersection is right.x0, if this is inside R1,
5391 otherwise there is no intersection. */
5392 if (right->x <= left->x + left->width)
5394 result->x = right->x;
5396 /* The right end of the intersection is the minimum of the
5397 the right ends of left and right. */
5398 result->width = (min (left->x + left->width, right->x + right->width)
5399 - result->x);
5401 /* Same game for Y. */
5402 if (r1->y < r2->y)
5403 upper = r1, lower = r2;
5404 else
5405 upper = r2, lower = r1;
5407 /* The upper end of the intersection is lower.y0, if this is inside
5408 of upper. Otherwise, there is no intersection. */
5409 if (lower->y <= upper->y + upper->height)
5411 result->y = lower->y;
5413 /* The lower end of the intersection is the minimum of the lower
5414 ends of upper and lower. */
5415 result->height = (min (lower->y + lower->height,
5416 upper->y + upper->height)
5417 - result->y);
5418 intersection_p = 1;
5422 return intersection_p;
5429 static void
5430 frame_highlight (f)
5431 struct frame *f;
5433 /* We used to only do this if Vx_no_window_manager was non-nil, but
5434 the ICCCM (section 4.1.6) says that the window's border pixmap
5435 and border pixel are window attributes which are "private to the
5436 client", so we can always change it to whatever we want. */
5437 BLOCK_INPUT;
5438 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5439 f->output_data.x->border_pixel);
5440 UNBLOCK_INPUT;
5441 x_update_cursor (f, 1);
5444 static void
5445 frame_unhighlight (f)
5446 struct frame *f;
5448 /* We used to only do this if Vx_no_window_manager was non-nil, but
5449 the ICCCM (section 4.1.6) says that the window's border pixmap
5450 and border pixel are window attributes which are "private to the
5451 client", so we can always change it to whatever we want. */
5452 BLOCK_INPUT;
5453 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5454 f->output_data.x->border_tile);
5455 UNBLOCK_INPUT;
5456 x_update_cursor (f, 1);
5459 /* The focus has changed. Update the frames as necessary to reflect
5460 the new situation. Note that we can't change the selected frame
5461 here, because the Lisp code we are interrupting might become confused.
5462 Each event gets marked with the frame in which it occurred, so the
5463 Lisp code can tell when the switch took place by examining the events. */
5465 static void
5466 x_new_focus_frame (dpyinfo, frame)
5467 struct x_display_info *dpyinfo;
5468 struct frame *frame;
5470 struct frame *old_focus = dpyinfo->x_focus_frame;
5472 if (frame != dpyinfo->x_focus_frame)
5474 /* Set this before calling other routines, so that they see
5475 the correct value of x_focus_frame. */
5476 dpyinfo->x_focus_frame = frame;
5478 if (old_focus && old_focus->auto_lower)
5479 x_lower_frame (old_focus);
5481 #if 0
5482 selected_frame = frame;
5483 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5484 selected_frame);
5485 Fselect_window (selected_frame->selected_window);
5486 choose_minibuf_frame ();
5487 #endif /* ! 0 */
5489 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5490 pending_autoraise_frame = dpyinfo->x_focus_frame;
5491 else
5492 pending_autoraise_frame = 0;
5495 x_frame_rehighlight (dpyinfo);
5498 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5500 void
5501 x_mouse_leave (dpyinfo)
5502 struct x_display_info *dpyinfo;
5504 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5507 /* The focus has changed, or we have redirected a frame's focus to
5508 another frame (this happens when a frame uses a surrogate
5509 mini-buffer frame). Shift the highlight as appropriate.
5511 The FRAME argument doesn't necessarily have anything to do with which
5512 frame is being highlighted or un-highlighted; we only use it to find
5513 the appropriate X display info. */
5515 static void
5516 XTframe_rehighlight (frame)
5517 struct frame *frame;
5519 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5522 static void
5523 x_frame_rehighlight (dpyinfo)
5524 struct x_display_info *dpyinfo;
5526 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5528 if (dpyinfo->x_focus_frame)
5530 dpyinfo->x_highlight_frame
5531 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5532 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5533 : dpyinfo->x_focus_frame);
5534 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5536 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5537 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5540 else
5541 dpyinfo->x_highlight_frame = 0;
5543 if (dpyinfo->x_highlight_frame != old_highlight)
5545 if (old_highlight)
5546 frame_unhighlight (old_highlight);
5547 if (dpyinfo->x_highlight_frame)
5548 frame_highlight (dpyinfo->x_highlight_frame);
5554 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5556 /* Initialize mode_switch_bit and modifier_meaning. */
5557 static void
5558 x_find_modifier_meanings (dpyinfo)
5559 struct x_display_info *dpyinfo;
5561 int min_code, max_code;
5562 KeySym *syms;
5563 int syms_per_code;
5564 XModifierKeymap *mods;
5566 dpyinfo->meta_mod_mask = 0;
5567 dpyinfo->shift_lock_mask = 0;
5568 dpyinfo->alt_mod_mask = 0;
5569 dpyinfo->super_mod_mask = 0;
5570 dpyinfo->hyper_mod_mask = 0;
5572 #ifdef HAVE_X11R4
5573 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5574 #else
5575 min_code = dpyinfo->display->min_keycode;
5576 max_code = dpyinfo->display->max_keycode;
5577 #endif
5579 syms = XGetKeyboardMapping (dpyinfo->display,
5580 min_code, max_code - min_code + 1,
5581 &syms_per_code);
5582 mods = XGetModifierMapping (dpyinfo->display);
5584 /* Scan the modifier table to see which modifier bits the Meta and
5585 Alt keysyms are on. */
5587 int row, col; /* The row and column in the modifier table. */
5589 for (row = 3; row < 8; row++)
5590 for (col = 0; col < mods->max_keypermod; col++)
5592 KeyCode code
5593 = mods->modifiermap[(row * mods->max_keypermod) + col];
5595 /* Zeroes are used for filler. Skip them. */
5596 if (code == 0)
5597 continue;
5599 /* Are any of this keycode's keysyms a meta key? */
5601 int code_col;
5603 for (code_col = 0; code_col < syms_per_code; code_col++)
5605 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5607 switch (sym)
5609 case XK_Meta_L:
5610 case XK_Meta_R:
5611 dpyinfo->meta_mod_mask |= (1 << row);
5612 break;
5614 case XK_Alt_L:
5615 case XK_Alt_R:
5616 dpyinfo->alt_mod_mask |= (1 << row);
5617 break;
5619 case XK_Hyper_L:
5620 case XK_Hyper_R:
5621 dpyinfo->hyper_mod_mask |= (1 << row);
5622 break;
5624 case XK_Super_L:
5625 case XK_Super_R:
5626 dpyinfo->super_mod_mask |= (1 << row);
5627 break;
5629 case XK_Shift_Lock:
5630 /* Ignore this if it's not on the lock modifier. */
5631 if ((1 << row) == LockMask)
5632 dpyinfo->shift_lock_mask = LockMask;
5633 break;
5640 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5641 if (! dpyinfo->meta_mod_mask)
5643 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5644 dpyinfo->alt_mod_mask = 0;
5647 /* If some keys are both alt and meta,
5648 make them just meta, not alt. */
5649 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5651 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5654 XFree ((char *) syms);
5655 XFreeModifiermap (mods);
5658 /* Convert between the modifier bits X uses and the modifier bits
5659 Emacs uses. */
5661 static unsigned int
5662 x_x_to_emacs_modifiers (dpyinfo, state)
5663 struct x_display_info *dpyinfo;
5664 unsigned int state;
5666 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5667 | ((state & ControlMask) ? ctrl_modifier : 0)
5668 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5669 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5670 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5671 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
5674 static unsigned int
5675 x_emacs_to_x_modifiers (dpyinfo, state)
5676 struct x_display_info *dpyinfo;
5677 unsigned int state;
5679 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5680 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5681 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5682 | ((state & shift_modifier) ? ShiftMask : 0)
5683 | ((state & ctrl_modifier) ? ControlMask : 0)
5684 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
5687 /* Convert a keysym to its name. */
5689 char *
5690 x_get_keysym_name (keysym)
5691 KeySym keysym;
5693 char *value;
5695 BLOCK_INPUT;
5696 value = XKeysymToString (keysym);
5697 UNBLOCK_INPUT;
5699 return value;
5704 /* Mouse clicks and mouse movement. Rah. */
5706 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5707 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5708 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5709 not force the value into range. */
5711 void
5712 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5713 FRAME_PTR f;
5714 register int pix_x, pix_y;
5715 register int *x, *y;
5716 XRectangle *bounds;
5717 int noclip;
5719 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5720 even for negative values. */
5721 if (pix_x < 0)
5722 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
5723 if (pix_y < 0)
5724 pix_y -= (f)->output_data.x->line_height - 1;
5726 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5727 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5729 if (bounds)
5731 bounds->width = FONT_WIDTH (f->output_data.x->font);
5732 bounds->height = f->output_data.x->line_height;
5733 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5734 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5737 if (!noclip)
5739 if (pix_x < 0)
5740 pix_x = 0;
5741 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5742 pix_x = FRAME_WINDOW_WIDTH (f);
5744 if (pix_y < 0)
5745 pix_y = 0;
5746 else if (pix_y > f->height)
5747 pix_y = f->height;
5750 *x = pix_x;
5751 *y = pix_y;
5755 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5756 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5757 can't tell the positions because W's display is not up to date,
5758 return 0. */
5761 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5762 struct window *w;
5763 int hpos, vpos;
5764 int *frame_x, *frame_y;
5766 int success_p;
5768 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5769 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5771 if (display_completed)
5773 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5774 struct glyph *glyph = row->glyphs[TEXT_AREA];
5775 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5777 *frame_y = row->y;
5778 *frame_x = row->x;
5779 while (glyph < end)
5781 *frame_x += glyph->pixel_width;
5782 ++glyph;
5785 success_p = 1;
5787 else
5789 *frame_y = *frame_x = 0;
5790 success_p = 0;
5793 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5794 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5795 return success_p;
5799 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5801 If the event is a button press, then note that we have grabbed
5802 the mouse. */
5804 static Lisp_Object
5805 construct_mouse_click (result, event, f)
5806 struct input_event *result;
5807 XButtonEvent *event;
5808 struct frame *f;
5810 /* Make the event type no_event; we'll change that when we decide
5811 otherwise. */
5812 result->kind = mouse_click;
5813 result->code = event->button - Button1;
5814 result->timestamp = event->time;
5815 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5816 event->state)
5817 | (event->type == ButtonRelease
5818 ? up_modifier
5819 : down_modifier));
5821 XSETINT (result->x, event->x);
5822 XSETINT (result->y, event->y);
5823 XSETFRAME (result->frame_or_window, f);
5824 return Qnil;
5827 #if 0 /* This function isn't called. --gerd */
5829 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5831 static Lisp_Object
5832 construct_menu_click (result, event, f)
5833 struct input_event *result;
5834 XButtonEvent *event;
5835 struct frame *f;
5837 /* Make the event type no_event; we'll change that when we decide
5838 otherwise. */
5839 result->kind = mouse_click;
5840 result->code = event->button - Button1;
5841 result->timestamp = event->time;
5842 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5843 event->state)
5844 | (event->type == ButtonRelease
5845 ? up_modifier
5846 : down_modifier));
5848 XSETINT (result->x, event->x);
5849 XSETINT (result->y, -1);
5850 XSETFRAME (result->frame_or_window, f);
5853 #endif /* 0 */
5856 /* Function to report a mouse movement to the mainstream Emacs code.
5857 The input handler calls this.
5859 We have received a mouse movement event, which is given in *event.
5860 If the mouse is over a different glyph than it was last time, tell
5861 the mainstream emacs code by setting mouse_moved. If not, ask for
5862 another motion event, so we can check again the next time it moves. */
5864 static XMotionEvent last_mouse_motion_event;
5865 static Lisp_Object last_mouse_motion_frame;
5867 static void
5868 note_mouse_movement (frame, event)
5869 FRAME_PTR frame;
5870 XMotionEvent *event;
5872 last_mouse_movement_time = event->time;
5873 last_mouse_motion_event = *event;
5874 XSETFRAME (last_mouse_motion_frame, frame);
5876 if (event->window != FRAME_X_WINDOW (frame))
5878 frame->mouse_moved = 1;
5879 last_mouse_scroll_bar = Qnil;
5880 note_mouse_highlight (frame, -1, -1);
5883 /* Has the mouse moved off the glyph it was on at the last sighting? */
5884 else if (event->x < last_mouse_glyph.x
5885 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
5886 || event->y < last_mouse_glyph.y
5887 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
5889 frame->mouse_moved = 1;
5890 last_mouse_scroll_bar = Qnil;
5891 note_mouse_highlight (frame, event->x, event->y);
5895 /* This is used for debugging, to turn off note_mouse_highlight. */
5897 int disable_mouse_highlight;
5901 /************************************************************************
5902 Mouse Face
5903 ************************************************************************/
5905 /* Find the glyph under window-relative coordinates X/Y in window W.
5906 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5907 strings. Return in *HPOS and *VPOS the row and column number of
5908 the glyph found. Return in *AREA the glyph area containing X.
5909 Value is a pointer to the glyph found or null if X/Y is not on
5910 text, or we can't tell because W's current matrix is not up to
5911 date. */
5913 static struct glyph *
5914 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5915 struct window *w;
5916 int x, y;
5917 int *hpos, *vpos, *area;
5919 struct glyph *glyph, *end;
5920 struct glyph_row *row;
5921 int x0, i, left_area_width;
5923 /* Find row containing Y. Give up if some row is not enabled. */
5924 for (i = 0; i < w->current_matrix->nrows; ++i)
5926 row = MATRIX_ROW (w->current_matrix, i);
5927 if (!row->enabled_p)
5928 return NULL;
5929 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5930 break;
5933 *vpos = i;
5934 *hpos = 0;
5936 /* Give up if Y is not in the window. */
5937 if (i == w->current_matrix->nrows)
5938 return NULL;
5940 /* Get the glyph area containing X. */
5941 if (w->pseudo_window_p)
5943 *area = TEXT_AREA;
5944 x0 = 0;
5946 else
5948 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5949 if (x < left_area_width)
5951 *area = LEFT_MARGIN_AREA;
5952 x0 = 0;
5954 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5956 *area = TEXT_AREA;
5957 x0 = row->x + left_area_width;
5959 else
5961 *area = RIGHT_MARGIN_AREA;
5962 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5966 /* Find glyph containing X. */
5967 glyph = row->glyphs[*area];
5968 end = glyph + row->used[*area];
5969 while (glyph < end)
5971 if (x < x0 + glyph->pixel_width)
5973 if (w->pseudo_window_p)
5974 break;
5975 else if (BUFFERP (glyph->object))
5976 break;
5979 x0 += glyph->pixel_width;
5980 ++glyph;
5983 if (glyph == end)
5984 return NULL;
5986 *hpos = glyph - row->glyphs[*area];
5987 return glyph;
5991 /* Convert frame-relative x/y to coordinates relative to window W.
5992 Takes pseudo-windows into account. */
5994 static void
5995 frame_to_window_pixel_xy (w, x, y)
5996 struct window *w;
5997 int *x, *y;
5999 if (w->pseudo_window_p)
6001 /* A pseudo-window is always full-width, and starts at the
6002 left edge of the frame, plus a frame border. */
6003 struct frame *f = XFRAME (w->frame);
6004 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6005 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6007 else
6009 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6010 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6015 /* Take proper action when mouse has moved to the mode or top line of
6016 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6017 mode line. X is relative to the start of the text display area of
6018 W, so the width of bitmap areas and scroll bars must be subtracted
6019 to get a position relative to the start of the mode line. */
6021 static void
6022 note_mode_line_highlight (w, x, mode_line_p)
6023 struct window *w;
6024 int x, mode_line_p;
6026 struct frame *f = XFRAME (w->frame);
6027 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6028 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6029 struct glyph_row *row;
6031 if (mode_line_p)
6032 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6033 else
6034 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6036 if (row->enabled_p)
6038 struct glyph *glyph, *end;
6039 Lisp_Object help, map;
6040 int x0;
6042 /* Find the glyph under X. */
6043 glyph = row->glyphs[TEXT_AREA];
6044 end = glyph + row->used[TEXT_AREA];
6045 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6046 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6047 while (glyph < end
6048 && x >= x0 + glyph->pixel_width)
6050 x0 += glyph->pixel_width;
6051 ++glyph;
6054 if (glyph < end
6055 && STRINGP (glyph->object)
6056 && XSTRING (glyph->object)->intervals
6057 && glyph->charpos >= 0
6058 && glyph->charpos < XSTRING (glyph->object)->size)
6060 /* If we're on a string with `help-echo' text property,
6061 arrange for the help to be displayed. This is done by
6062 setting the global variable help_echo to the help string. */
6063 help = Fget_text_property (make_number (glyph->charpos),
6064 Qhelp_echo, glyph->object);
6065 if (STRINGP (help))
6066 help_echo = help;
6068 /* Change the mouse pointer according to what is under X/Y. */
6069 map = Fget_text_property (make_number (glyph->charpos),
6070 Qlocal_map, glyph->object);
6071 if (!NILP (Fkeymapp (map)))
6072 cursor = f->output_data.x->nontext_cursor;
6076 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6080 /* Take proper action when the mouse has moved to position X, Y on
6081 frame F as regards highlighting characters that have mouse-face
6082 properties. Also de-highlighting chars where the mouse was before.
6083 X and Y can be negative or out of range. */
6085 static void
6086 note_mouse_highlight (f, x, y)
6087 struct frame *f;
6088 int x, y;
6090 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6091 int portion;
6092 Lisp_Object window;
6093 struct window *w;
6095 /* When a menu is active, don't highlight because this looks odd. */
6096 #ifdef USE_X_TOOLKIT
6097 if (popup_activated ())
6098 return;
6099 #endif
6101 if (disable_mouse_highlight)
6102 return;
6104 dpyinfo->mouse_face_mouse_x = x;
6105 dpyinfo->mouse_face_mouse_y = y;
6106 dpyinfo->mouse_face_mouse_frame = f;
6108 if (dpyinfo->mouse_face_defer)
6109 return;
6111 if (gc_in_progress)
6113 dpyinfo->mouse_face_deferred_gc = 1;
6114 return;
6117 /* Which window is that in? */
6118 window = window_from_coordinates (f, x, y, &portion, 1);
6120 /* If we were displaying active text in another window, clear that. */
6121 if (! EQ (window, dpyinfo->mouse_face_window))
6122 clear_mouse_face (dpyinfo);
6124 /* Not on a window -> return. */
6125 if (!WINDOWP (window))
6126 return;
6128 /* Convert to window-relative pixel coordinates. */
6129 w = XWINDOW (window);
6130 frame_to_window_pixel_xy (w, &x, &y);
6132 /* Handle tool-bar window differently since it doesn't display a
6133 buffer. */
6134 if (EQ (window, f->tool_bar_window))
6136 note_tool_bar_highlight (f, x, y);
6137 return;
6140 if (portion == 1 || portion == 3)
6142 /* Mouse is on the mode or top line. */
6143 note_mode_line_highlight (w, x, portion == 1);
6144 return;
6146 else
6147 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6148 f->output_data.x->text_cursor);
6150 /* Are we in a window whose display is up to date?
6151 And verify the buffer's text has not changed. */
6152 if (/* Within text portion of the window. */
6153 portion == 0
6154 && EQ (w->window_end_valid, w->buffer)
6155 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6156 && (XFASTINT (w->last_overlay_modified)
6157 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6159 int hpos, vpos, pos, i, area;
6160 struct glyph *glyph;
6162 /* Find the glyph under X/Y. */
6163 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6165 /* Clear mouse face if X/Y not over text. */
6166 if (glyph == NULL
6167 || area != TEXT_AREA
6168 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6170 clear_mouse_face (dpyinfo);
6171 return;
6174 pos = glyph->charpos;
6175 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6177 /* Check for mouse-face and help-echo. */
6179 Lisp_Object mouse_face, overlay, position;
6180 Lisp_Object *overlay_vec;
6181 int len, noverlays;
6182 struct buffer *obuf;
6183 int obegv, ozv;
6185 /* If we get an out-of-range value, return now; avoid an error. */
6186 if (pos > BUF_Z (XBUFFER (w->buffer)))
6187 return;
6189 /* Make the window's buffer temporarily current for
6190 overlays_at and compute_char_face. */
6191 obuf = current_buffer;
6192 current_buffer = XBUFFER (w->buffer);
6193 obegv = BEGV;
6194 ozv = ZV;
6195 BEGV = BEG;
6196 ZV = Z;
6198 /* Is this char mouse-active or does it have help-echo? */
6199 XSETINT (position, pos);
6201 /* Put all the overlays we want in a vector in overlay_vec.
6202 Store the length in len. If there are more than 10, make
6203 enough space for all, and try again. */
6204 len = 10;
6205 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6206 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6207 if (noverlays > len)
6209 len = noverlays;
6210 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6211 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6214 noverlays = sort_overlays (overlay_vec, noverlays, w);
6216 /* Check mouse-face highlighting. */
6217 if (! (EQ (window, dpyinfo->mouse_face_window)
6218 && vpos >= dpyinfo->mouse_face_beg_row
6219 && vpos <= dpyinfo->mouse_face_end_row
6220 && (vpos > dpyinfo->mouse_face_beg_row
6221 || hpos >= dpyinfo->mouse_face_beg_col)
6222 && (vpos < dpyinfo->mouse_face_end_row
6223 || hpos < dpyinfo->mouse_face_end_col
6224 || dpyinfo->mouse_face_past_end)))
6226 /* Clear the display of the old active region, if any. */
6227 clear_mouse_face (dpyinfo);
6229 /* Find the highest priority overlay that has a mouse-face prop. */
6230 overlay = Qnil;
6231 for (i = 0; i < noverlays; i++)
6233 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6234 if (!NILP (mouse_face))
6236 overlay = overlay_vec[i];
6237 break;
6241 /* If no overlay applies, get a text property. */
6242 if (NILP (overlay))
6243 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6245 /* Handle the overlay case. */
6246 if (! NILP (overlay))
6248 /* Find the range of text around this char that
6249 should be active. */
6250 Lisp_Object before, after;
6251 int ignore;
6253 before = Foverlay_start (overlay);
6254 after = Foverlay_end (overlay);
6255 /* Record this as the current active region. */
6256 fast_find_position (w, XFASTINT (before),
6257 &dpyinfo->mouse_face_beg_col,
6258 &dpyinfo->mouse_face_beg_row,
6259 &dpyinfo->mouse_face_beg_x,
6260 &dpyinfo->mouse_face_beg_y);
6261 dpyinfo->mouse_face_past_end
6262 = !fast_find_position (w, XFASTINT (after),
6263 &dpyinfo->mouse_face_end_col,
6264 &dpyinfo->mouse_face_end_row,
6265 &dpyinfo->mouse_face_end_x,
6266 &dpyinfo->mouse_face_end_y);
6267 dpyinfo->mouse_face_window = window;
6268 dpyinfo->mouse_face_face_id
6269 = face_at_buffer_position (w, pos, 0, 0,
6270 &ignore, pos + 1, 1);
6272 /* Display it as active. */
6273 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6275 /* Handle the text property case. */
6276 else if (! NILP (mouse_face))
6278 /* Find the range of text around this char that
6279 should be active. */
6280 Lisp_Object before, after, beginning, end;
6281 int ignore;
6283 beginning = Fmarker_position (w->start);
6284 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6285 - XFASTINT (w->window_end_pos)));
6286 before
6287 = Fprevious_single_property_change (make_number (pos + 1),
6288 Qmouse_face,
6289 w->buffer, beginning);
6290 after
6291 = Fnext_single_property_change (position, Qmouse_face,
6292 w->buffer, end);
6293 /* Record this as the current active region. */
6294 fast_find_position (w, XFASTINT (before),
6295 &dpyinfo->mouse_face_beg_col,
6296 &dpyinfo->mouse_face_beg_row,
6297 &dpyinfo->mouse_face_beg_x,
6298 &dpyinfo->mouse_face_beg_y);
6299 dpyinfo->mouse_face_past_end
6300 = !fast_find_position (w, XFASTINT (after),
6301 &dpyinfo->mouse_face_end_col,
6302 &dpyinfo->mouse_face_end_row,
6303 &dpyinfo->mouse_face_end_x,
6304 &dpyinfo->mouse_face_end_y);
6305 dpyinfo->mouse_face_window = window;
6306 dpyinfo->mouse_face_face_id
6307 = face_at_buffer_position (w, pos, 0, 0,
6308 &ignore, pos + 1, 1);
6310 /* Display it as active. */
6311 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6315 /* Look for a `help-echo' property. */
6317 Lisp_Object help;
6319 /* Check overlays first. */
6320 help = Qnil;
6321 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6322 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6324 /* Try text properties. */
6325 if (!STRINGP (help)
6326 && ((STRINGP (glyph->object)
6327 && glyph->charpos >= 0
6328 && glyph->charpos < XSTRING (glyph->object)->size)
6329 || (BUFFERP (glyph->object)
6330 && glyph->charpos >= BEGV
6331 && glyph->charpos < ZV)))
6332 help = Fget_text_property (make_number (glyph->charpos),
6333 Qhelp_echo, glyph->object);
6335 if (STRINGP (help))
6336 help_echo = help;
6339 BEGV = obegv;
6340 ZV = ozv;
6341 current_buffer = obuf;
6346 static void
6347 redo_mouse_highlight ()
6349 if (!NILP (last_mouse_motion_frame)
6350 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6351 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6352 last_mouse_motion_event.x,
6353 last_mouse_motion_event.y);
6358 /***********************************************************************
6359 Tool-bars
6360 ***********************************************************************/
6362 static int x_tool_bar_item P_ ((struct frame *, int, int,
6363 struct glyph **, int *, int *, int *));
6365 /* Tool-bar item index of the item on which a mouse button was pressed
6366 or -1. */
6368 static int last_tool_bar_item;
6371 /* Get information about the tool-bar item at position X/Y on frame F.
6372 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6373 the current matrix of the tool-bar window of F, or NULL if not
6374 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6375 item in F->current_tool_bar_items. Value is
6377 -1 if X/Y is not on a tool-bar item
6378 0 if X/Y is on the same item that was highlighted before.
6379 1 otherwise. */
6381 static int
6382 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6383 struct frame *f;
6384 int x, y;
6385 struct glyph **glyph;
6386 int *hpos, *vpos, *prop_idx;
6388 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6389 struct window *w = XWINDOW (f->tool_bar_window);
6390 int area;
6392 /* Find the glyph under X/Y. */
6393 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6394 if (*glyph == NULL)
6395 return -1;
6397 /* Get the start of this tool-bar item's properties in
6398 f->current_tool_bar_items. */
6399 if (!tool_bar_item_info (f, *glyph, prop_idx))
6400 return -1;
6402 /* Is mouse on the highlighted item? */
6403 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6404 && *vpos >= dpyinfo->mouse_face_beg_row
6405 && *vpos <= dpyinfo->mouse_face_end_row
6406 && (*vpos > dpyinfo->mouse_face_beg_row
6407 || *hpos >= dpyinfo->mouse_face_beg_col)
6408 && (*vpos < dpyinfo->mouse_face_end_row
6409 || *hpos < dpyinfo->mouse_face_end_col
6410 || dpyinfo->mouse_face_past_end))
6411 return 0;
6413 return 1;
6417 /* Handle mouse button event on the tool-bar of frame F, at
6418 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6419 or ButtonRelase. */
6421 static void
6422 x_handle_tool_bar_click (f, button_event)
6423 struct frame *f;
6424 XButtonEvent *button_event;
6426 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6427 struct window *w = XWINDOW (f->tool_bar_window);
6428 int hpos, vpos, prop_idx;
6429 struct glyph *glyph;
6430 Lisp_Object enabled_p;
6431 int x = button_event->x;
6432 int y = button_event->y;
6434 /* If not on the highlighted tool-bar item, return. */
6435 frame_to_window_pixel_xy (w, &x, &y);
6436 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6437 return;
6439 /* If item is disabled, do nothing. */
6440 enabled_p = (XVECTOR (f->current_tool_bar_items)
6441 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6442 if (NILP (enabled_p))
6443 return;
6445 if (button_event->type == ButtonPress)
6447 /* Show item in pressed state. */
6448 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6449 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6450 last_tool_bar_item = prop_idx;
6452 else
6454 Lisp_Object key, frame;
6455 struct input_event event;
6457 /* Show item in released state. */
6458 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6459 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6461 key = (XVECTOR (f->current_tool_bar_items)
6462 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6464 XSETFRAME (frame, f);
6465 event.kind = TOOL_BAR_EVENT;
6466 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6467 kbd_buffer_store_event (&event);
6469 event.kind = TOOL_BAR_EVENT;
6470 event.frame_or_window = Fcons (frame, key);
6471 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6472 button_event->state);
6473 kbd_buffer_store_event (&event);
6474 last_tool_bar_item = -1;
6479 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6480 tool-bar window-relative coordinates X/Y. Called from
6481 note_mouse_highlight. */
6483 static void
6484 note_tool_bar_highlight (f, x, y)
6485 struct frame *f;
6486 int x, y;
6488 Lisp_Object window = f->tool_bar_window;
6489 struct window *w = XWINDOW (window);
6490 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6491 int hpos, vpos;
6492 struct glyph *glyph;
6493 struct glyph_row *row;
6494 int i;
6495 Lisp_Object enabled_p;
6496 int prop_idx;
6497 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6498 int mouse_down_p, rc;
6500 /* Function note_mouse_highlight is called with negative x(y
6501 values when mouse moves outside of the frame. */
6502 if (x <= 0 || y <= 0)
6504 clear_mouse_face (dpyinfo);
6505 return;
6508 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6509 if (rc < 0)
6511 /* Not on tool-bar item. */
6512 clear_mouse_face (dpyinfo);
6513 return;
6515 else if (rc == 0)
6516 /* On same tool-bar item as before. */
6517 goto set_help_echo;
6519 clear_mouse_face (dpyinfo);
6521 /* Mouse is down, but on different tool-bar item? */
6522 mouse_down_p = (dpyinfo->grabbed
6523 && f == last_mouse_frame
6524 && FRAME_LIVE_P (f));
6525 if (mouse_down_p
6526 && last_tool_bar_item != prop_idx)
6527 return;
6529 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6530 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6532 /* If tool-bar item is not enabled, don't highlight it. */
6533 enabled_p = (XVECTOR (f->current_tool_bar_items)
6534 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6535 if (!NILP (enabled_p))
6537 /* Compute the x-position of the glyph. In front and past the
6538 image is a space. We include this is the highlighted area. */
6539 row = MATRIX_ROW (w->current_matrix, vpos);
6540 for (i = x = 0; i < hpos; ++i)
6541 x += row->glyphs[TEXT_AREA][i].pixel_width;
6543 /* Record this as the current active region. */
6544 dpyinfo->mouse_face_beg_col = hpos;
6545 dpyinfo->mouse_face_beg_row = vpos;
6546 dpyinfo->mouse_face_beg_x = x;
6547 dpyinfo->mouse_face_beg_y = row->y;
6548 dpyinfo->mouse_face_past_end = 0;
6550 dpyinfo->mouse_face_end_col = hpos + 1;
6551 dpyinfo->mouse_face_end_row = vpos;
6552 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6553 dpyinfo->mouse_face_end_y = row->y;
6554 dpyinfo->mouse_face_window = window;
6555 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6557 /* Display it as active. */
6558 show_mouse_face (dpyinfo, draw);
6559 dpyinfo->mouse_face_image_state = draw;
6562 set_help_echo:
6564 /* Set help_echo to a help string.to display for this tool-bar item.
6565 XTread_socket does the rest. */
6566 help_echo = (XVECTOR (f->current_tool_bar_items)
6567 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6568 if (!STRINGP (help_echo))
6569 help_echo = (XVECTOR (f->current_tool_bar_items)
6570 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6575 /* Find the glyph matrix position of buffer position POS in window W.
6576 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6577 current glyphs must be up to date. If POS is above window start
6578 return (0, 0, 0, 0). If POS is after end of W, return end of
6579 last line in W. */
6581 static int
6582 fast_find_position (w, pos, hpos, vpos, x, y)
6583 struct window *w;
6584 int pos;
6585 int *hpos, *vpos, *x, *y;
6587 int i;
6588 int lastcol;
6589 int maybe_next_line_p = 0;
6590 int line_start_position;
6591 int yb = window_text_bottom_y (w);
6592 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6593 struct glyph_row *best_row = row;
6594 int row_vpos = 0, best_row_vpos = 0;
6595 int current_x;
6597 while (row->y < yb)
6599 if (row->used[TEXT_AREA])
6600 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6601 else
6602 line_start_position = 0;
6604 if (line_start_position > pos)
6605 break;
6606 /* If the position sought is the end of the buffer,
6607 don't include the blank lines at the bottom of the window. */
6608 else if (line_start_position == pos
6609 && pos == BUF_ZV (XBUFFER (w->buffer)))
6611 maybe_next_line_p = 1;
6612 break;
6614 else if (line_start_position > 0)
6616 best_row = row;
6617 best_row_vpos = row_vpos;
6620 ++row;
6621 ++row_vpos;
6624 /* Find the right column within BEST_ROW. */
6625 lastcol = 0;
6626 current_x = best_row->x;
6627 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6629 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6630 int charpos;
6632 charpos = glyph->charpos;
6633 if (charpos == pos)
6635 *hpos = i;
6636 *vpos = best_row_vpos;
6637 *x = current_x;
6638 *y = best_row->y;
6639 return 1;
6641 else if (charpos > pos)
6642 break;
6643 else if (charpos > 0)
6644 lastcol = i;
6646 current_x += glyph->pixel_width;
6649 /* If we're looking for the end of the buffer,
6650 and we didn't find it in the line we scanned,
6651 use the start of the following line. */
6652 if (maybe_next_line_p)
6654 ++best_row;
6655 ++best_row_vpos;
6656 lastcol = 0;
6657 current_x = best_row->x;
6660 *vpos = best_row_vpos;
6661 *hpos = lastcol + 1;
6662 *x = current_x;
6663 *y = best_row->y;
6664 return 0;
6668 /* Display the active region described by mouse_face_*
6669 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6671 static void
6672 show_mouse_face (dpyinfo, draw)
6673 struct x_display_info *dpyinfo;
6674 enum draw_glyphs_face draw;
6676 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6677 struct frame *f = XFRAME (WINDOW_FRAME (w));
6678 int i;
6679 int cursor_off_p = 0;
6680 struct cursor_pos saved_cursor;
6682 saved_cursor = output_cursor;
6684 /* If window is in the process of being destroyed, don't bother
6685 to do anything. */
6686 if (w->current_matrix == NULL)
6687 goto set_x_cursor;
6689 /* Recognize when we are called to operate on rows that don't exist
6690 anymore. This can happen when a window is split. */
6691 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6692 goto set_x_cursor;
6694 set_output_cursor (&w->phys_cursor);
6696 /* Note that mouse_face_beg_row etc. are window relative. */
6697 for (i = dpyinfo->mouse_face_beg_row;
6698 i <= dpyinfo->mouse_face_end_row;
6699 i++)
6701 int start_hpos, end_hpos, start_x;
6702 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6704 /* Don't do anything if row doesn't have valid contents. */
6705 if (!row->enabled_p)
6706 continue;
6708 /* For all but the first row, the highlight starts at column 0. */
6709 if (i == dpyinfo->mouse_face_beg_row)
6711 start_hpos = dpyinfo->mouse_face_beg_col;
6712 start_x = dpyinfo->mouse_face_beg_x;
6714 else
6716 start_hpos = 0;
6717 start_x = 0;
6720 if (i == dpyinfo->mouse_face_end_row)
6721 end_hpos = dpyinfo->mouse_face_end_col;
6722 else
6723 end_hpos = row->used[TEXT_AREA];
6725 /* If the cursor's in the text we are about to rewrite, turn the
6726 cursor off. */
6727 if (!w->pseudo_window_p
6728 && i == output_cursor.vpos
6729 && output_cursor.hpos >= start_hpos - 1
6730 && output_cursor.hpos <= end_hpos)
6732 x_update_window_cursor (w, 0);
6733 cursor_off_p = 1;
6736 if (end_hpos > start_hpos)
6737 x_draw_glyphs (w, start_x, row, updated_area,
6738 start_hpos, end_hpos, draw, NULL, NULL, 0);
6741 /* If we turned the cursor off, turn it back on. */
6742 if (cursor_off_p)
6743 x_display_cursor (w, 1,
6744 output_cursor.hpos, output_cursor.vpos,
6745 output_cursor.x, output_cursor.y);
6747 output_cursor = saved_cursor;
6749 set_x_cursor:
6751 /* Change the mouse cursor. */
6752 if (draw == DRAW_NORMAL_TEXT)
6753 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6754 f->output_data.x->text_cursor);
6755 else if (draw == DRAW_MOUSE_FACE)
6756 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6757 f->output_data.x->cross_cursor);
6758 else
6759 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6760 f->output_data.x->nontext_cursor);
6763 /* Clear out the mouse-highlighted active region.
6764 Redraw it un-highlighted first. */
6766 void
6767 clear_mouse_face (dpyinfo)
6768 struct x_display_info *dpyinfo;
6770 if (tip_frame)
6771 return;
6773 if (! NILP (dpyinfo->mouse_face_window))
6774 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6776 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6777 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6778 dpyinfo->mouse_face_window = Qnil;
6781 /* Just discard the mouse face information for frame F, if any.
6782 This is used when the size of F is changed. */
6784 void
6785 cancel_mouse_face (f)
6786 FRAME_PTR f;
6788 Lisp_Object window;
6789 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6791 window = dpyinfo->mouse_face_window;
6792 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6794 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6795 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6796 dpyinfo->mouse_face_window = Qnil;
6800 static struct scroll_bar *x_window_to_scroll_bar ();
6801 static void x_scroll_bar_report_motion ();
6803 /* Return the current position of the mouse.
6804 *fp should be a frame which indicates which display to ask about.
6806 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6807 and *part to the frame, window, and scroll bar part that the mouse
6808 is over. Set *x and *y to the portion and whole of the mouse's
6809 position on the scroll bar.
6811 If the mouse movement started elsewhere, set *fp to the frame the
6812 mouse is on, *bar_window to nil, and *x and *y to the character cell
6813 the mouse is over.
6815 Set *time to the server time-stamp for the time at which the mouse
6816 was at this position.
6818 Don't store anything if we don't have a valid set of values to report.
6820 This clears the mouse_moved flag, so we can wait for the next mouse
6821 movement. */
6823 static void
6824 XTmouse_position (fp, insist, bar_window, part, x, y, time)
6825 FRAME_PTR *fp;
6826 int insist;
6827 Lisp_Object *bar_window;
6828 enum scroll_bar_part *part;
6829 Lisp_Object *x, *y;
6830 unsigned long *time;
6832 FRAME_PTR f1;
6834 BLOCK_INPUT;
6836 if (! NILP (last_mouse_scroll_bar) && insist == 0)
6837 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
6838 else
6840 Window root;
6841 int root_x, root_y;
6843 Window dummy_window;
6844 int dummy;
6846 Lisp_Object frame, tail;
6848 /* Clear the mouse-moved flag for every frame on this display. */
6849 FOR_EACH_FRAME (tail, frame)
6850 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
6851 XFRAME (frame)->mouse_moved = 0;
6853 last_mouse_scroll_bar = Qnil;
6855 /* Figure out which root window we're on. */
6856 XQueryPointer (FRAME_X_DISPLAY (*fp),
6857 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
6859 /* The root window which contains the pointer. */
6860 &root,
6862 /* Trash which we can't trust if the pointer is on
6863 a different screen. */
6864 &dummy_window,
6866 /* The position on that root window. */
6867 &root_x, &root_y,
6869 /* More trash we can't trust. */
6870 &dummy, &dummy,
6872 /* Modifier keys and pointer buttons, about which
6873 we don't care. */
6874 (unsigned int *) &dummy);
6876 /* Now we have a position on the root; find the innermost window
6877 containing the pointer. */
6879 Window win, child;
6880 int win_x, win_y;
6881 int parent_x = 0, parent_y = 0;
6882 int count;
6884 win = root;
6886 /* XTranslateCoordinates can get errors if the window
6887 structure is changing at the same time this function
6888 is running. So at least we must not crash from them. */
6890 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
6892 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
6893 && FRAME_LIVE_P (last_mouse_frame))
6895 /* If mouse was grabbed on a frame, give coords for that frame
6896 even if the mouse is now outside it. */
6897 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
6899 /* From-window, to-window. */
6900 root, FRAME_X_WINDOW (last_mouse_frame),
6902 /* From-position, to-position. */
6903 root_x, root_y, &win_x, &win_y,
6905 /* Child of win. */
6906 &child);
6907 f1 = last_mouse_frame;
6909 else
6911 while (1)
6913 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
6915 /* From-window, to-window. */
6916 root, win,
6918 /* From-position, to-position. */
6919 root_x, root_y, &win_x, &win_y,
6921 /* Child of win. */
6922 &child);
6924 if (child == None || child == win)
6925 break;
6927 win = child;
6928 parent_x = win_x;
6929 parent_y = win_y;
6932 /* Now we know that:
6933 win is the innermost window containing the pointer
6934 (XTC says it has no child containing the pointer),
6935 win_x and win_y are the pointer's position in it
6936 (XTC did this the last time through), and
6937 parent_x and parent_y are the pointer's position in win's parent.
6938 (They are what win_x and win_y were when win was child.
6939 If win is the root window, it has no parent, and
6940 parent_{x,y} are invalid, but that's okay, because we'll
6941 never use them in that case.) */
6943 /* Is win one of our frames? */
6944 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
6947 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
6948 f1 = 0;
6950 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
6952 /* If not, is it one of our scroll bars? */
6953 if (! f1)
6955 struct scroll_bar *bar = x_window_to_scroll_bar (win);
6957 if (bar)
6959 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6960 win_x = parent_x;
6961 win_y = parent_y;
6965 if (f1 == 0 && insist > 0)
6966 f1 = SELECTED_FRAME ();
6968 if (f1)
6970 /* Ok, we found a frame. Store all the values.
6971 last_mouse_glyph is a rectangle used to reduce the
6972 generation of mouse events. To not miss any motion
6973 events, we must divide the frame into rectangles of the
6974 size of the smallest character that could be displayed
6975 on it, i.e. into the same rectangles that matrices on
6976 the frame are divided into. */
6978 #if OLD_REDISPLAY_CODE
6979 int ignore1, ignore2;
6980 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
6981 &last_mouse_glyph,
6982 FRAME_X_DISPLAY_INFO (f1)->grabbed
6983 || insist);
6984 #else
6986 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6987 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6988 int x = win_x;
6989 int y = win_y;
6991 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6992 round down even for negative values. */
6993 if (x < 0)
6994 x -= width - 1;
6995 if (y < 0)
6996 y -= height - 1;
6998 last_mouse_glyph.width = width;
6999 last_mouse_glyph.height = height;
7000 last_mouse_glyph.x = (x + width - 1) / width * width;
7001 last_mouse_glyph.y = (y + height - 1) / height * height;
7003 #endif
7005 *bar_window = Qnil;
7006 *part = 0;
7007 *fp = f1;
7008 XSETINT (*x, win_x);
7009 XSETINT (*y, win_y);
7010 *time = last_mouse_movement_time;
7015 UNBLOCK_INPUT;
7019 DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts,
7020 0, 0, 0,
7021 "Arrange for Xt timeout callbacks to be called.")
7024 #ifdef USE_X_TOOLKIT
7025 BLOCK_INPUT;
7026 while (XtAppPending (Xt_app_con) & XtIMTimer)
7027 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7028 UNBLOCK_INPUT;
7029 #endif /* USE_X_TOOLKIT */
7031 return Qnil;
7036 /* Scroll bar support. */
7038 /* Given an X window ID, find the struct scroll_bar which manages it.
7039 This can be called in GC, so we have to make sure to strip off mark
7040 bits. */
7041 static struct scroll_bar *
7042 x_window_to_scroll_bar (window_id)
7043 Window window_id;
7045 Lisp_Object tail;
7047 for (tail = Vframe_list;
7048 XGCTYPE (tail) == Lisp_Cons;
7049 tail = XCDR (tail))
7051 Lisp_Object frame, bar, condemned;
7053 frame = XCAR (tail);
7054 /* All elements of Vframe_list should be frames. */
7055 if (! GC_FRAMEP (frame))
7056 abort ();
7058 /* Scan this frame's scroll bar list for a scroll bar with the
7059 right window ID. */
7060 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7061 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7062 /* This trick allows us to search both the ordinary and
7063 condemned scroll bar lists with one loop. */
7064 ! GC_NILP (bar) || (bar = condemned,
7065 condemned = Qnil,
7066 ! GC_NILP (bar));
7067 bar = XSCROLL_BAR (bar)->next)
7068 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7069 return XSCROLL_BAR (bar);
7072 return 0;
7077 /************************************************************************
7078 Toolkit scroll bars
7079 ************************************************************************/
7081 #if USE_TOOLKIT_SCROLL_BARS
7083 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7084 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7085 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7086 struct scroll_bar *));
7087 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7088 int, int, int));
7091 /* Id of action hook installed for scroll bars. */
7093 static XtActionHookId action_hook_id;
7095 /* Lisp window being scrolled. Set when starting to interact with
7096 a toolkit scroll bar, reset to nil when ending the interaction. */
7098 static Lisp_Object window_being_scrolled;
7100 /* Last scroll bar part sent in xm_scroll_callback. */
7102 static int last_scroll_bar_part;
7105 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7106 bars are used.. The hoos is responsible for detecting when
7107 the user ends an interaction with the scroll bar, and generates
7108 a `end-scroll' scroll_bar_click' event if so. */
7110 static void
7111 xt_action_hook (widget, client_data, action_name, event, params,
7112 num_params)
7113 Widget widget;
7114 XtPointer client_data;
7115 String action_name;
7116 XEvent *event;
7117 String *params;
7118 Cardinal *num_params;
7120 int scroll_bar_p;
7121 char *end_action;
7123 #ifdef USE_MOTIF
7124 scroll_bar_p = XmIsScrollBar (widget);
7125 end_action = "Release";
7126 #elif defined HAVE_XAW3D
7127 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7128 end_action = "EndScroll";
7129 #else
7130 #error unknown scroll bar toolkit
7131 #endif /* HAVE_XAW3D */
7133 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
7134 let Xt timeouts be processed doesn't work. */
7135 if (scroll_bar_p
7136 && strcmp (action_name, end_action) == 0
7137 && WINDOWP (window_being_scrolled))
7139 struct window *w;
7141 x_send_scroll_bar_event (window_being_scrolled,
7142 scroll_bar_end_scroll, 0, 0);
7143 w = XWINDOW (window_being_scrolled);
7144 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7145 window_being_scrolled = Qnil;
7146 last_scroll_bar_part = -1;
7151 /* Send a client message with message type Xatom_Scrollbar for a
7152 scroll action to the frame of WINDOW. PART is a value identifying
7153 the part of the scroll bar that was clicked on. PORTION is the
7154 amount to scroll of a whole of WHOLE. */
7156 static void
7157 x_send_scroll_bar_event (window, part, portion, whole)
7158 Lisp_Object window;
7159 int part, portion, whole;
7161 XEvent event;
7162 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7163 struct frame *f = XFRAME (XWINDOW (window)->frame);
7165 /* Construct a ClientMessage event to send to the frame. */
7166 ev->type = ClientMessage;
7167 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7168 ev->display = FRAME_X_DISPLAY (f);
7169 ev->window = FRAME_X_WINDOW (f);
7170 ev->format = 32;
7171 ev->data.l[0] = (long) window;
7172 ev->data.l[1] = (long) part;
7173 ev->data.l[2] = (long) 0;
7174 ev->data.l[3] = (long) portion;
7175 ev->data.l[4] = (long) whole;
7177 /* Setting the event mask to zero means that the message will
7178 be sent to the client that created the window, and if that
7179 window no longer exists, no event will be sent. */
7180 BLOCK_INPUT;
7181 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7182 UNBLOCK_INPUT;
7186 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7187 in *IEVENT. */
7189 static void
7190 x_scroll_bar_to_input_event (event, ievent)
7191 XEvent *event;
7192 struct input_event *ievent;
7194 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7195 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7196 struct frame *f = XFRAME (XWINDOW (window)->frame);
7198 ievent->kind = scroll_bar_click;
7199 ievent->frame_or_window = window;
7200 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7201 ievent->part = ev->data.l[1];
7202 ievent->code = ev->data.l[2];
7203 ievent->x = make_number ((int) ev->data.l[3]);
7204 ievent->y = make_number ((int) ev->data.l[4]);
7205 ievent->modifiers = 0;
7209 #ifdef USE_MOTIF
7211 /* Minimum and maximum values used for Motif scroll bars. */
7213 #define XM_SB_MIN 1
7214 #define XM_SB_MAX 10000000
7215 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7218 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7219 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7220 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7222 static void
7223 xm_scroll_callback (widget, client_data, call_data)
7224 Widget widget;
7225 XtPointer client_data, call_data;
7227 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7228 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7229 double percent;
7230 int part = -1, whole = 0, portion = 0;
7232 switch (cs->reason)
7234 case XmCR_DECREMENT:
7235 bar->dragging = Qnil;
7236 part = scroll_bar_up_arrow;
7237 break;
7239 case XmCR_INCREMENT:
7240 bar->dragging = Qnil;
7241 part = scroll_bar_down_arrow;
7242 break;
7244 case XmCR_PAGE_DECREMENT:
7245 bar->dragging = Qnil;
7246 part = scroll_bar_above_handle;
7247 break;
7249 case XmCR_PAGE_INCREMENT:
7250 bar->dragging = Qnil;
7251 part = scroll_bar_below_handle;
7252 break;
7254 case XmCR_TO_TOP:
7255 bar->dragging = Qnil;
7256 part = scroll_bar_to_top;
7257 break;
7259 case XmCR_TO_BOTTOM:
7260 bar->dragging = Qnil;
7261 part = scroll_bar_to_bottom;
7262 break;
7264 case XmCR_DRAG:
7266 int slider_size;
7267 int dragging_down_p = (INTEGERP (bar->dragging)
7268 && XINT (bar->dragging) <= cs->value);
7270 /* Get the slider size. */
7271 BLOCK_INPUT;
7272 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7273 UNBLOCK_INPUT;
7275 /* At the max position of the scroll bar, do a line-wise
7276 movement. Without doing anything, the LessTif scroll bar
7277 calls us with the same cs->value again and again. If we
7278 want to make sure that we can reach the end of the buffer,
7279 we have to do something.
7281 Implementation note: setting bar->dragging always to
7282 cs->value gives a smoother movement at the max position.
7283 Setting it to nil when doing line-wise movement gives
7284 a better slider behavior. */
7286 if (cs->value + slider_size == XM_SB_MAX
7287 || (dragging_down_p
7288 && last_scroll_bar_part == scroll_bar_down_arrow))
7290 part = scroll_bar_down_arrow;
7291 bar->dragging = Qnil;
7293 else
7295 whole = XM_SB_RANGE;
7296 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7297 part = scroll_bar_handle;
7298 bar->dragging = make_number (cs->value);
7301 break;
7303 case XmCR_VALUE_CHANGED:
7304 break;
7307 if (part >= 0)
7309 window_being_scrolled = bar->window;
7310 last_scroll_bar_part = part;
7311 x_send_scroll_bar_event (bar->window, part, portion, whole);
7316 #else /* not USE_MOTIF, i.e. XAW3D. */
7319 /* Xaw3d scroll bar callback. Invoked when the thumb is dragged.
7320 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7321 scroll bar struct. CALL_DATA is a pointer to a float saying where
7322 the thumb is. */
7324 static void
7325 xaw3d_jump_callback (widget, client_data, call_data)
7326 Widget widget;
7327 XtPointer client_data, call_data;
7329 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7330 float top = *(float *) call_data;
7331 float shown;
7332 int whole, portion;
7333 int dragging_down_p, part;
7334 double epsilon = 0.01;
7336 /* Get the size of the thumb, a value between 0 and 1. */
7337 BLOCK_INPUT;
7338 XtVaGetValues (widget, XtNshown, &shown, NULL);
7339 UNBLOCK_INPUT;
7341 whole = 10000000;
7342 portion = shown < 1 ? top * whole : 0;
7343 dragging_down_p = (INTEGERP (bar->dragging)
7344 && XINT (bar->dragging) < portion);
7346 if (shown < 1
7347 && (abs (top + shown - 1) < epsilon
7348 || (dragging_down_p
7349 && last_scroll_bar_part == scroll_bar_down_arrow)))
7350 part = scroll_bar_down_arrow;
7351 else
7352 part = scroll_bar_handle;
7354 window_being_scrolled = bar->window;
7355 bar->dragging = make_number (portion);
7356 last_scroll_bar_part = part;
7357 x_send_scroll_bar_event (bar->window, part, portion, whole);
7361 /* Xaw3d scroll bar callback. Invoked for incremental scrolling.,
7362 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar
7363 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7364 the scroll bar. CALL_DATA is an integer specifying the action that
7365 has taken place. It's magnitude is in the range 0..height of the
7366 scroll bar. Negative values mean scroll towards buffer start.
7367 Values < height of scroll bar mean line-wise movement. */
7369 static void
7370 xaw3d_scroll_callback (widget, client_data, call_data)
7371 Widget widget;
7372 XtPointer client_data, call_data;
7374 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7375 int position = (int) call_data;
7376 Dimension height;
7377 int part;
7379 /* Get the height of the scroll bar. */
7380 BLOCK_INPUT;
7381 XtVaGetValues (widget, XtNheight, &height, NULL);
7382 UNBLOCK_INPUT;
7384 if (position < 0)
7386 if (abs (position) < height)
7387 part = scroll_bar_up_arrow;
7388 else
7389 part = scroll_bar_above_handle;
7391 else
7393 if (abs (position) < height)
7394 part = scroll_bar_down_arrow;
7395 else
7396 part = scroll_bar_below_handle;
7399 window_being_scrolled = bar->window;
7400 bar->dragging = Qnil;
7401 last_scroll_bar_part = part;
7402 x_send_scroll_bar_event (bar->window, part, 0, 0);
7406 #endif /* not USE_MOTIF */
7409 /* Create the widget for scroll bar BAR on frame F. Record the widget
7410 and X window of the scroll bar in BAR. */
7412 static void
7413 x_create_toolkit_scroll_bar (f, bar)
7414 struct frame *f;
7415 struct scroll_bar *bar;
7417 Window xwindow;
7418 Widget widget;
7419 Arg av[20];
7420 int ac = 0;
7421 char *scroll_bar_name = "verticalScrollBar";
7422 unsigned long pixel;
7424 BLOCK_INPUT;
7426 #ifdef USE_MOTIF
7427 /* LessTif 0.85, problems:
7429 1. When the mouse if over the scroll bar, the scroll bar will
7430 get keyboard events. I didn't find a way to turn this off.
7432 2. Do we have to explicitly set the cursor to get an arrow
7433 cursor (see below)? */
7435 /* Set resources. Create the widget. */
7436 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7437 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7438 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7439 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7440 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7441 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7442 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7444 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7445 if (pixel != -1)
7447 XtSetArg (av[ac], XmNforeground, pixel);
7448 ++ac;
7451 pixel = f->output_data.x->scroll_bar_background_pixel;
7452 if (pixel != -1)
7454 XtSetArg (av[ac], XmNbackground, pixel);
7455 ++ac;
7458 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7459 scroll_bar_name, av, ac);
7461 /* Add one callback for everything that can happen. */
7462 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7463 (XtPointer) bar);
7464 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7465 (XtPointer) bar);
7466 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7467 (XtPointer) bar);
7468 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7469 (XtPointer) bar);
7470 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7471 (XtPointer) bar);
7472 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7473 (XtPointer) bar);
7474 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7475 (XtPointer) bar);
7477 /* Realize the widget. Only after that is the X window created. */
7478 XtRealizeWidget (widget);
7480 /* Set the cursor to an arrow. I didn't find a resource to do that.
7481 And I'm wondering why it hasn't an arrow cursor by default. */
7482 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7483 f->output_data.x->nontext_cursor);
7485 #elif defined HAVE_XAW3D
7487 /* Set resources. Create the widget. The background of the
7488 Xaw3d scroll bar widget is a little bit light for my taste.
7489 We don't alter it here to let users change it according
7490 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7491 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7492 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7493 XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac;
7494 XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac;
7496 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7497 if (pixel != -1)
7499 XtSetArg (av[ac], XtNforeground, pixel);
7500 ++ac;
7503 pixel = f->output_data.x->scroll_bar_background_pixel;
7504 if (pixel != -1)
7506 XtSetArg (av[ac], XtNbackground, pixel);
7507 ++ac;
7510 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7511 f->output_data.x->edit_widget, av, ac);
7513 /* Define callbacks. */
7514 XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar);
7515 XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback,
7516 (XtPointer) bar);
7518 /* Realize the widget. Only after that is the X window created. */
7519 XtRealizeWidget (widget);
7521 #endif /* HAVE_XAW3D */
7523 /* Install an action hook that let's us detect when the user
7524 finishes interacting with a scroll bar. */
7525 if (action_hook_id == 0)
7526 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7528 /* Remember X window and widget in the scroll bar vector. */
7529 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7530 xwindow = XtWindow (widget);
7531 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7533 UNBLOCK_INPUT;
7537 /* Set the thumb size and position of scroll bar BAR. We are currently
7538 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7540 static void
7541 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7542 struct scroll_bar *bar;
7543 int portion, position, whole;
7545 float top, shown;
7546 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7548 if (whole == 0)
7549 top = 0, shown = 1;
7550 else
7552 top = (float) position / whole;
7553 shown = (float) portion / whole;
7556 BLOCK_INPUT;
7558 #ifdef USE_MOTIF
7560 int size, value;
7561 Boolean arrow1_selected, arrow2_selected;
7562 unsigned char flags;
7563 XmScrollBarWidget sb;
7565 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX
7566 is the scroll bar's maximum and MIN is the scroll bar's minimum
7567 value. */
7568 size = shown * XM_SB_RANGE;
7569 size = min (size, XM_SB_RANGE);
7570 size = max (size, 1);
7572 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7573 value = top * XM_SB_RANGE;
7574 value = min (value, XM_SB_MAX - size);
7575 value = max (value, XM_SB_MIN);
7577 /* LessTif: Calling XmScrollBarSetValues after an increment or
7578 decrement turns off auto-repeat LessTif-internally. This can
7579 be seen in ScrollBar.c which resets Arrow1Selected and
7580 Arrow2Selected. It also sets internal flags so that LessTif
7581 believes the mouse is in the slider. We either have to change
7582 our code, or work around that by accessing private data. */
7584 sb = (XmScrollBarWidget) widget;
7585 arrow1_selected = sb->scrollBar.arrow1_selected;
7586 arrow2_selected = sb->scrollBar.arrow2_selected;
7587 flags = sb->scrollBar.flags;
7589 if (NILP (bar->dragging))
7590 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7591 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7592 /* This has the negative side effect that the slider value is
7593 not would it would be if we scrolled here using line-wise or
7594 page-wise movement. */
7595 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7596 else
7598 /* If currently dragging, only update the slider size.
7599 This reduces flicker effects. */
7600 int old_value, old_size, increment, page_increment;
7602 XmScrollBarGetValues (widget, &old_value, &old_size,
7603 &increment, &page_increment);
7604 XmScrollBarSetValues (widget, old_value,
7605 min (size, XM_SB_RANGE - old_value),
7606 0, 0, False);
7609 sb->scrollBar.arrow1_selected = arrow1_selected;
7610 sb->scrollBar.arrow2_selected = arrow2_selected;
7611 sb->scrollBar.flags = flags;
7613 #elif defined HAVE_XAW3D
7615 /* Restrict to [0 1]. */
7616 top = max (0, min (1, top));
7617 shown = max (0, min (1, shown));
7619 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7620 check that your system's configuration file contains a define
7621 for `NARROWPROTO'. See s/freebsd.h for an example. */
7622 if (NILP (bar->dragging))
7624 float old_top, old_shown;
7625 XtVaGetValues (widget, XtNtopOfThumb, &old_top, XtNshown, &old_shown,
7626 NULL);
7627 if (top != old_top || shown != old_shown)
7628 XawScrollbarSetThumb (widget, top, shown);
7630 else
7632 ScrollbarWidget sb = (ScrollbarWidget) widget;
7633 int scroll_mode = sb->scrollbar.scroll_mode;
7635 sb->scrollbar.scroll_mode = 0;
7637 if (last_scroll_bar_part == scroll_bar_down_arrow)
7638 XawScrollbarSetThumb (widget, top, 1 - top);
7639 else
7641 float old_top;
7642 XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL);
7643 XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top));
7646 sb->scrollbar.scroll_mode = scroll_mode;
7649 #endif /* HAVE_XAW3D */
7651 UNBLOCK_INPUT;
7654 #endif /* USE_TOOLKIT_SCROLL_BARS */
7658 /************************************************************************
7659 Scroll bars, general
7660 ************************************************************************/
7662 /* Create a scroll bar and return the scroll bar vector for it. W is
7663 the Emacs window on which to create the scroll bar. TOP, LEFT,
7664 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7665 scroll bar. */
7667 static struct scroll_bar *
7668 x_scroll_bar_create (w, top, left, width, height)
7669 struct window *w;
7670 int top, left, width, height;
7672 struct frame *f = XFRAME (w->frame);
7673 struct scroll_bar *bar
7674 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7676 BLOCK_INPUT;
7678 #if USE_TOOLKIT_SCROLL_BARS
7679 x_create_toolkit_scroll_bar (f, bar);
7680 #else /* not USE_TOOLKIT_SCROLL_BARS */
7682 XSetWindowAttributes a;
7683 unsigned long mask;
7684 Window window;
7686 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7687 if (a.background_pixel == -1)
7688 a.background_pixel = f->output_data.x->background_pixel;
7690 a.event_mask = (ButtonPressMask | ButtonReleaseMask
7691 | ButtonMotionMask | PointerMotionHintMask
7692 | ExposureMask);
7693 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
7695 mask = (CWBackPixel | CWEventMask | CWCursor);
7697 /* Clear the area of W that will serve as a scroll bar. This is
7698 for the case that a window has been split horizontally. In
7699 this case, no clear_frame is generated to reduce flickering. */
7700 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7701 left, top, width,
7702 window_box_height (w), False);
7704 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7705 /* Position and size of scroll bar. */
7706 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7707 top,
7708 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7709 height,
7710 /* Border width, depth, class, and visual. */
7712 CopyFromParent,
7713 CopyFromParent,
7714 CopyFromParent,
7715 /* Attributes. */
7716 mask, &a);
7717 SET_SCROLL_BAR_X_WINDOW (bar, window);
7719 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7721 XSETWINDOW (bar->window, w);
7722 XSETINT (bar->top, top);
7723 XSETINT (bar->left, left);
7724 XSETINT (bar->width, width);
7725 XSETINT (bar->height, height);
7726 XSETINT (bar->start, 0);
7727 XSETINT (bar->end, 0);
7728 bar->dragging = Qnil;
7730 /* Add bar to its frame's list of scroll bars. */
7731 bar->next = FRAME_SCROLL_BARS (f);
7732 bar->prev = Qnil;
7733 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7734 if (!NILP (bar->next))
7735 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7737 /* Map the window/widget. */
7738 #if USE_TOOLKIT_SCROLL_BARS
7739 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
7740 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7741 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7742 top,
7743 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7744 height, 0);
7745 #else /* not USE_TOOLKIT_SCROLL_BARS */
7746 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
7747 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7749 UNBLOCK_INPUT;
7750 return bar;
7754 /* Draw BAR's handle in the proper position.
7756 If the handle is already drawn from START to END, don't bother
7757 redrawing it, unless REBUILD is non-zero; in that case, always
7758 redraw it. (REBUILD is handy for drawing the handle after expose
7759 events.)
7761 Normally, we want to constrain the start and end of the handle to
7762 fit inside its rectangle, but if the user is dragging the scroll
7763 bar handle, we want to let them drag it down all the way, so that
7764 the bar's top is as far down as it goes; otherwise, there's no way
7765 to move to the very end of the buffer. */
7767 #ifndef USE_TOOLKIT_SCROLL_BARS
7769 static void
7770 x_scroll_bar_set_handle (bar, start, end, rebuild)
7771 struct scroll_bar *bar;
7772 int start, end;
7773 int rebuild;
7775 int dragging = ! NILP (bar->dragging);
7776 Window w = SCROLL_BAR_X_WINDOW (bar);
7777 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7778 GC gc = f->output_data.x->normal_gc;
7780 /* If the display is already accurate, do nothing. */
7781 if (! rebuild
7782 && start == XINT (bar->start)
7783 && end == XINT (bar->end))
7784 return;
7786 BLOCK_INPUT;
7789 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
7790 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
7791 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7793 /* Make sure the values are reasonable, and try to preserve
7794 the distance between start and end. */
7796 int length = end - start;
7798 if (start < 0)
7799 start = 0;
7800 else if (start > top_range)
7801 start = top_range;
7802 end = start + length;
7804 if (end < start)
7805 end = start;
7806 else if (end > top_range && ! dragging)
7807 end = top_range;
7810 /* Store the adjusted setting in the scroll bar. */
7811 XSETINT (bar->start, start);
7812 XSETINT (bar->end, end);
7814 /* Clip the end position, just for display. */
7815 if (end > top_range)
7816 end = top_range;
7818 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
7819 below top positions, to make sure the handle is always at least
7820 that many pixels tall. */
7821 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
7823 /* Draw the empty space above the handle. Note that we can't clear
7824 zero-height areas; that means "clear to end of window." */
7825 if (0 < start)
7826 XClearArea (FRAME_X_DISPLAY (f), w,
7828 /* x, y, width, height, and exposures. */
7829 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7830 VERTICAL_SCROLL_BAR_TOP_BORDER,
7831 inside_width, start,
7832 False);
7834 /* Change to proper foreground color if one is specified. */
7835 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7836 XSetForeground (FRAME_X_DISPLAY (f), gc,
7837 f->output_data.x->scroll_bar_foreground_pixel);
7839 /* Draw the handle itself. */
7840 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
7842 /* x, y, width, height */
7843 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7844 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
7845 inside_width, end - start);
7847 /* Restore the foreground color of the GC if we changed it above. */
7848 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7849 XSetForeground (FRAME_X_DISPLAY (f), gc,
7850 f->output_data.x->foreground_pixel);
7852 /* Draw the empty space below the handle. Note that we can't
7853 clear zero-height areas; that means "clear to end of window." */
7854 if (end < inside_height)
7855 XClearArea (FRAME_X_DISPLAY (f), w,
7857 /* x, y, width, height, and exposures. */
7858 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7859 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
7860 inside_width, inside_height - end,
7861 False);
7865 UNBLOCK_INPUT;
7868 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7870 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7871 nil. */
7873 static void
7874 x_scroll_bar_remove (bar)
7875 struct scroll_bar *bar;
7877 BLOCK_INPUT;
7879 #if USE_TOOLKIT_SCROLL_BARS
7880 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
7881 #else /* not USE_TOOLKIT_SCROLL_BARS */
7883 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7884 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
7886 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7888 /* Disassociate this scroll bar from its window. */
7889 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7891 UNBLOCK_INPUT;
7895 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7896 that we are displaying PORTION characters out of a total of WHOLE
7897 characters, starting at POSITION. If WINDOW has no scroll bar,
7898 create one. */
7900 static void
7901 XTset_vertical_scroll_bar (w, portion, whole, position)
7902 struct window *w;
7903 int portion, whole, position;
7905 struct frame *f = XFRAME (w->frame);
7906 struct scroll_bar *bar;
7907 int top, height, left, sb_left, width, sb_width;
7908 int window_x, window_y, window_width, window_height;
7910 /* Get window dimensions. */
7911 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7912 top = window_y;
7913 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7914 height = window_height;
7916 /* Compute the left edge of the scroll bar area. */
7917 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7918 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7919 else
7920 left = XFASTINT (w->left);
7921 left *= CANON_X_UNIT (f);
7922 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7924 /* Compute the width of the scroll bar which might be less than
7925 the width of the area reserved for the scroll bar. */
7926 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7927 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7928 else
7929 sb_width = width;
7931 /* Compute the left edge of the scroll bar. */
7932 #ifdef USE_TOOLKIT_SCROLL_BARS
7933 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7934 sb_left = left + width - sb_width - (width - sb_width) / 2;
7935 else
7936 sb_left = left + (width - sb_width) / 2;
7937 #else
7938 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7939 sb_left = left + width - sb_width;
7940 else
7941 sb_left = left;
7942 #endif
7944 /* Does the scroll bar exist yet? */
7945 if (NILP (w->vertical_scroll_bar))
7947 BLOCK_INPUT;
7948 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7949 left, top, width, height, False);
7950 UNBLOCK_INPUT;
7951 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
7953 else
7955 /* It may just need to be moved and resized. */
7956 unsigned int mask = 0;
7958 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7960 BLOCK_INPUT;
7962 if (sb_left != XINT (bar->left))
7963 mask |= CWX;
7964 if (top != XINT (bar->top))
7965 mask |= CWY;
7966 if (sb_width != XINT (bar->width))
7967 mask |= CWWidth;
7968 if (height != XINT (bar->height))
7969 mask |= CWHeight;
7971 #ifdef USE_TOOLKIT_SCROLL_BARS
7973 /* Since toolkit scroll bars are smaller than the space reserved
7974 for them on the frame, we have to clear "under" them. */
7975 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7976 left, top, width, height, False);
7978 /* Move/size the scroll bar widget. */
7979 if (mask)
7980 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7981 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7982 top,
7983 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7984 height, 0);
7986 #else /* not USE_TOOLKIT_SCROLL_BARS */
7988 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
7990 /* Clear areas not covered by the scroll bar. This makes sure a
7991 previous mode line display is cleared after C-x 2 C-x 1, for
7992 example. Non-toolkit scroll bars are as wide as the area
7993 reserved for scroll bars - trim at both sides. */
7994 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7995 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7996 height, False);
7997 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7998 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7999 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8000 height, False);
8003 /* Move/size the scroll bar window. */
8004 if (mask)
8006 XWindowChanges wc;
8008 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8009 wc.y = top;
8010 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8011 wc.height = height;
8012 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8013 mask, &wc);
8016 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8018 /* Remember new settings. */
8019 XSETINT (bar->left, sb_left);
8020 XSETINT (bar->top, top);
8021 XSETINT (bar->width, sb_width);
8022 XSETINT (bar->height, height);
8024 UNBLOCK_INPUT;
8027 #if USE_TOOLKIT_SCROLL_BARS
8028 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8029 #else /* not USE_TOOLKIT_SCROLL_BARS */
8030 /* Set the scroll bar's current state, unless we're currently being
8031 dragged. */
8032 if (NILP (bar->dragging))
8034 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8036 if (whole == 0)
8037 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8038 else
8040 int start = ((double) position * top_range) / whole;
8041 int end = ((double) (position + portion) * top_range) / whole;
8042 x_scroll_bar_set_handle (bar, start, end, 0);
8045 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8047 XSETVECTOR (w->vertical_scroll_bar, bar);
8051 /* The following three hooks are used when we're doing a thorough
8052 redisplay of the frame. We don't explicitly know which scroll bars
8053 are going to be deleted, because keeping track of when windows go
8054 away is a real pain - "Can you say set-window-configuration, boys
8055 and girls?" Instead, we just assert at the beginning of redisplay
8056 that *all* scroll bars are to be removed, and then save a scroll bar
8057 from the fiery pit when we actually redisplay its window. */
8059 /* Arrange for all scroll bars on FRAME to be removed at the next call
8060 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8061 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8063 static void
8064 XTcondemn_scroll_bars (frame)
8065 FRAME_PTR frame;
8067 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8068 while (! NILP (FRAME_SCROLL_BARS (frame)))
8070 Lisp_Object bar;
8071 bar = FRAME_SCROLL_BARS (frame);
8072 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8073 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8074 XSCROLL_BAR (bar)->prev = Qnil;
8075 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8076 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8077 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8081 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8082 Note that WINDOW isn't necessarily condemned at all. */
8083 static void
8084 XTredeem_scroll_bar (window)
8085 struct window *window;
8087 struct scroll_bar *bar;
8089 /* We can't redeem this window's scroll bar if it doesn't have one. */
8090 if (NILP (window->vertical_scroll_bar))
8091 abort ();
8093 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8095 /* Unlink it from the condemned list. */
8097 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8099 if (NILP (bar->prev))
8101 /* If the prev pointer is nil, it must be the first in one of
8102 the lists. */
8103 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8104 /* It's not condemned. Everything's fine. */
8105 return;
8106 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8107 window->vertical_scroll_bar))
8108 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8109 else
8110 /* If its prev pointer is nil, it must be at the front of
8111 one or the other! */
8112 abort ();
8114 else
8115 XSCROLL_BAR (bar->prev)->next = bar->next;
8117 if (! NILP (bar->next))
8118 XSCROLL_BAR (bar->next)->prev = bar->prev;
8120 bar->next = FRAME_SCROLL_BARS (f);
8121 bar->prev = Qnil;
8122 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8123 if (! NILP (bar->next))
8124 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8128 /* Remove all scroll bars on FRAME that haven't been saved since the
8129 last call to `*condemn_scroll_bars_hook'. */
8131 static void
8132 XTjudge_scroll_bars (f)
8133 FRAME_PTR f;
8135 Lisp_Object bar, next;
8137 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8139 /* Clear out the condemned list now so we won't try to process any
8140 more events on the hapless scroll bars. */
8141 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8143 for (; ! NILP (bar); bar = next)
8145 struct scroll_bar *b = XSCROLL_BAR (bar);
8147 x_scroll_bar_remove (b);
8149 next = b->next;
8150 b->next = b->prev = Qnil;
8153 /* Now there should be no references to the condemned scroll bars,
8154 and they should get garbage-collected. */
8158 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8159 is a no-op when using toolkit scroll bars.
8161 This may be called from a signal handler, so we have to ignore GC
8162 mark bits. */
8164 static void
8165 x_scroll_bar_expose (bar, event)
8166 struct scroll_bar *bar;
8167 XEvent *event;
8169 #ifndef USE_TOOLKIT_SCROLL_BARS
8171 Window w = SCROLL_BAR_X_WINDOW (bar);
8172 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8173 GC gc = f->output_data.x->normal_gc;
8174 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8176 BLOCK_INPUT;
8178 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8180 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8181 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8183 /* x, y, width, height */
8184 0, 0,
8185 XINT (bar->width) - 1 - width_trim - width_trim,
8186 XINT (bar->height) - 1);
8188 UNBLOCK_INPUT;
8190 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8193 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8194 is set to something other than no_event, it is enqueued.
8196 This may be called from a signal handler, so we have to ignore GC
8197 mark bits. */
8199 #ifndef USE_TOOLKIT_SCROLL_BARS
8201 static void
8202 x_scroll_bar_handle_click (bar, event, emacs_event)
8203 struct scroll_bar *bar;
8204 XEvent *event;
8205 struct input_event *emacs_event;
8207 if (! GC_WINDOWP (bar->window))
8208 abort ();
8210 emacs_event->kind = scroll_bar_click;
8211 emacs_event->code = event->xbutton.button - Button1;
8212 emacs_event->modifiers
8213 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8214 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8215 event->xbutton.state)
8216 | (event->type == ButtonRelease
8217 ? up_modifier
8218 : down_modifier));
8219 emacs_event->frame_or_window = bar->window;
8220 emacs_event->timestamp = event->xbutton.time;
8222 #if 0
8223 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8224 int internal_height
8225 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8226 #endif
8227 int top_range
8228 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8229 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8231 if (y < 0) y = 0;
8232 if (y > top_range) y = top_range;
8234 if (y < XINT (bar->start))
8235 emacs_event->part = scroll_bar_above_handle;
8236 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8237 emacs_event->part = scroll_bar_handle;
8238 else
8239 emacs_event->part = scroll_bar_below_handle;
8241 /* Just because the user has clicked on the handle doesn't mean
8242 they want to drag it. Lisp code needs to be able to decide
8243 whether or not we're dragging. */
8244 #if 0
8245 /* If the user has just clicked on the handle, record where they're
8246 holding it. */
8247 if (event->type == ButtonPress
8248 && emacs_event->part == scroll_bar_handle)
8249 XSETINT (bar->dragging, y - XINT (bar->start));
8250 #endif
8252 /* If the user has released the handle, set it to its final position. */
8253 if (event->type == ButtonRelease
8254 && ! NILP (bar->dragging))
8256 int new_start = y - XINT (bar->dragging);
8257 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8259 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8260 bar->dragging = Qnil;
8263 /* Same deal here as the other #if 0. */
8264 #if 0
8265 /* Clicks on the handle are always reported as occurring at the top of
8266 the handle. */
8267 if (emacs_event->part == scroll_bar_handle)
8268 emacs_event->x = bar->start;
8269 else
8270 XSETINT (emacs_event->x, y);
8271 #else
8272 XSETINT (emacs_event->x, y);
8273 #endif
8275 XSETINT (emacs_event->y, top_range);
8279 /* Handle some mouse motion while someone is dragging the scroll bar.
8281 This may be called from a signal handler, so we have to ignore GC
8282 mark bits. */
8284 static void
8285 x_scroll_bar_note_movement (bar, event)
8286 struct scroll_bar *bar;
8287 XEvent *event;
8289 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8291 last_mouse_movement_time = event->xmotion.time;
8293 f->mouse_moved = 1;
8294 XSETVECTOR (last_mouse_scroll_bar, bar);
8296 /* If we're dragging the bar, display it. */
8297 if (! GC_NILP (bar->dragging))
8299 /* Where should the handle be now? */
8300 int new_start = event->xmotion.y - XINT (bar->dragging);
8302 if (new_start != XINT (bar->start))
8304 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8306 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8311 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8313 /* Return information to the user about the current position of the mouse
8314 on the scroll bar. */
8316 static void
8317 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8318 FRAME_PTR *fp;
8319 Lisp_Object *bar_window;
8320 enum scroll_bar_part *part;
8321 Lisp_Object *x, *y;
8322 unsigned long *time;
8324 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8325 Window w = SCROLL_BAR_X_WINDOW (bar);
8326 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8327 int win_x, win_y;
8328 Window dummy_window;
8329 int dummy_coord;
8330 unsigned int dummy_mask;
8332 BLOCK_INPUT;
8334 /* Get the mouse's position relative to the scroll bar window, and
8335 report that. */
8336 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8338 /* Root, child, root x and root y. */
8339 &dummy_window, &dummy_window,
8340 &dummy_coord, &dummy_coord,
8342 /* Position relative to scroll bar. */
8343 &win_x, &win_y,
8345 /* Mouse buttons and modifier keys. */
8346 &dummy_mask))
8348 else
8350 #if 0
8351 int inside_height
8352 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8353 #endif
8354 int top_range
8355 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8357 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8359 if (! NILP (bar->dragging))
8360 win_y -= XINT (bar->dragging);
8362 if (win_y < 0)
8363 win_y = 0;
8364 if (win_y > top_range)
8365 win_y = top_range;
8367 *fp = f;
8368 *bar_window = bar->window;
8370 if (! NILP (bar->dragging))
8371 *part = scroll_bar_handle;
8372 else if (win_y < XINT (bar->start))
8373 *part = scroll_bar_above_handle;
8374 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8375 *part = scroll_bar_handle;
8376 else
8377 *part = scroll_bar_below_handle;
8379 XSETINT (*x, win_y);
8380 XSETINT (*y, top_range);
8382 f->mouse_moved = 0;
8383 last_mouse_scroll_bar = Qnil;
8386 *time = last_mouse_movement_time;
8388 UNBLOCK_INPUT;
8392 /* The screen has been cleared so we may have changed foreground or
8393 background colors, and the scroll bars may need to be redrawn.
8394 Clear out the scroll bars, and ask for expose events, so we can
8395 redraw them. */
8397 void
8398 x_scroll_bar_clear (f)
8399 FRAME_PTR f;
8401 #ifndef USE_TOOLKIT_SCROLL_BARS
8402 Lisp_Object bar;
8404 /* We can have scroll bars even if this is 0,
8405 if we just turned off scroll bar mode.
8406 But in that case we should not clear them. */
8407 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8408 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8409 bar = XSCROLL_BAR (bar)->next)
8410 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8411 0, 0, 0, 0, True);
8412 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8415 /* This processes Expose events from the menu-bar specific X event
8416 loop in xmenu.c. This allows to redisplay the frame if necessary
8417 when handling menu-bar or pop-up items. */
8420 process_expose_from_menu (event)
8421 XEvent event;
8423 FRAME_PTR f;
8424 struct x_display_info *dpyinfo;
8425 int frame_exposed_p = 0;
8427 BLOCK_INPUT;
8429 dpyinfo = x_display_info_for_display (event.xexpose.display);
8430 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8431 if (f)
8433 if (f->async_visible == 0)
8435 f->async_visible = 1;
8436 f->async_iconified = 0;
8437 f->output_data.x->has_been_visible = 1;
8438 SET_FRAME_GARBAGED (f);
8440 else
8442 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8443 event.xexpose.x, event.xexpose.y,
8444 event.xexpose.width, event.xexpose.height);
8445 frame_exposed_p = 1;
8448 else
8450 struct scroll_bar *bar
8451 = x_window_to_scroll_bar (event.xexpose.window);
8453 if (bar)
8454 x_scroll_bar_expose (bar, &event);
8457 UNBLOCK_INPUT;
8458 return frame_exposed_p;
8461 /* Define a queue to save up SelectionRequest events for later handling. */
8463 struct selection_event_queue
8465 XEvent event;
8466 struct selection_event_queue *next;
8469 static struct selection_event_queue *queue;
8471 /* Nonzero means queue up certain events--don't process them yet. */
8473 static int x_queue_selection_requests;
8475 /* Queue up an X event *EVENT, to be processed later. */
8477 static void
8478 x_queue_event (f, event)
8479 FRAME_PTR f;
8480 XEvent *event;
8482 struct selection_event_queue *queue_tmp
8483 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8485 if (queue_tmp != NULL)
8487 queue_tmp->event = *event;
8488 queue_tmp->next = queue;
8489 queue = queue_tmp;
8493 /* Take all the queued events and put them back
8494 so that they get processed afresh. */
8496 static void
8497 x_unqueue_events (display)
8498 Display *display;
8500 while (queue != NULL)
8502 struct selection_event_queue *queue_tmp = queue;
8503 XPutBackEvent (display, &queue_tmp->event);
8504 queue = queue_tmp->next;
8505 xfree ((char *)queue_tmp);
8509 /* Start queuing SelectionRequest events. */
8511 void
8512 x_start_queuing_selection_requests (display)
8513 Display *display;
8515 x_queue_selection_requests++;
8518 /* Stop queuing SelectionRequest events. */
8520 void
8521 x_stop_queuing_selection_requests (display)
8522 Display *display;
8524 x_queue_selection_requests--;
8525 x_unqueue_events (display);
8528 /* The main X event-reading loop - XTread_socket. */
8530 /* Time stamp of enter window event. This is only used by XTread_socket,
8531 but we have to put it out here, since static variables within functions
8532 sometimes don't work. */
8534 static Time enter_timestamp;
8536 /* This holds the state XLookupString needs to implement dead keys
8537 and other tricks known as "compose processing". _X Window System_
8538 says that a portable program can't use this, but Stephen Gildea assures
8539 me that letting the compiler initialize it to zeros will work okay.
8541 This must be defined outside of XTread_socket, for the same reasons
8542 given for enter_time stamp, above. */
8544 static XComposeStatus compose_status;
8546 /* Record the last 100 characters stored
8547 to help debug the loss-of-chars-during-GC problem. */
8549 static int temp_index;
8550 static short temp_buffer[100];
8552 /* Set this to nonzero to fake an "X I/O error"
8553 on a particular display. */
8555 struct x_display_info *XTread_socket_fake_io_error;
8557 /* When we find no input here, we occasionally do a no-op command
8558 to verify that the X server is still running and we can still talk with it.
8559 We try all the open displays, one by one.
8560 This variable is used for cycling thru the displays. */
8562 static struct x_display_info *next_noop_dpyinfo;
8564 #define SET_SAVED_MENU_EVENT(size) \
8565 do \
8567 if (f->output_data.x->saved_menu_event == 0) \
8568 f->output_data.x->saved_menu_event \
8569 = (XEvent *) xmalloc (sizeof (XEvent)); \
8570 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8571 if (numchars >= 1) \
8573 bufp->kind = menu_bar_activate_event; \
8574 XSETFRAME (bufp->frame_or_window, f); \
8575 bufp++; \
8576 count++; \
8577 numchars--; \
8580 while (0)
8582 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8583 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8585 /* Read events coming from the X server.
8586 This routine is called by the SIGIO handler.
8587 We return as soon as there are no more events to be read.
8589 Events representing keys are stored in buffer BUFP,
8590 which can hold up to NUMCHARS characters.
8591 We return the number of characters stored into the buffer,
8592 thus pretending to be `read'.
8594 EXPECTED is nonzero if the caller knows input is available. */
8597 XTread_socket (sd, bufp, numchars, expected)
8598 register int sd;
8599 /* register */ struct input_event *bufp;
8600 /* register */ int numchars;
8601 int expected;
8603 int count = 0;
8604 int nbytes = 0;
8605 XEvent event;
8606 struct frame *f;
8607 int event_found = 0;
8608 struct x_display_info *dpyinfo;
8609 #ifdef HAVE_X_I18N
8610 Status status_return;
8611 #endif
8613 if (interrupt_input_blocked)
8615 interrupt_input_pending = 1;
8616 return -1;
8619 interrupt_input_pending = 0;
8620 BLOCK_INPUT;
8622 /* So people can tell when we have read the available input. */
8623 input_signal_count++;
8625 if (numchars <= 0)
8626 abort (); /* Don't think this happens. */
8628 /* Find the display we are supposed to read input for.
8629 It's the one communicating on descriptor SD. */
8630 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8632 #if 0 /* This ought to be unnecessary; let's verify it. */
8633 #ifdef FIOSNBIO
8634 /* If available, Xlib uses FIOSNBIO to make the socket
8635 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8636 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8637 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8638 fcntl (dpyinfo->connection, F_SETFL, 0);
8639 #endif /* ! defined (FIOSNBIO) */
8640 #endif
8642 #if 0 /* This code can't be made to work, with multiple displays,
8643 and appears not to be used on any system any more.
8644 Also keyboard.c doesn't turn O_NDELAY on and off
8645 for X connections. */
8646 #ifndef SIGIO
8647 #ifndef HAVE_SELECT
8648 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8650 extern int read_alarm_should_throw;
8651 read_alarm_should_throw = 1;
8652 XPeekEvent (dpyinfo->display, &event);
8653 read_alarm_should_throw = 0;
8655 #endif /* HAVE_SELECT */
8656 #endif /* SIGIO */
8657 #endif
8659 /* For debugging, this gives a way to fake an I/O error. */
8660 if (dpyinfo == XTread_socket_fake_io_error)
8662 XTread_socket_fake_io_error = 0;
8663 x_io_error_quitter (dpyinfo->display);
8666 while (XPending (dpyinfo->display))
8668 XNextEvent (dpyinfo->display, &event);
8670 if (display_busy_cursor_p)
8672 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8673 display until the next X event is read and we come
8674 here again. Setting it to 1 inhibits busy-cursor
8675 display for direct commands. */
8676 if (event.type == MotionNotify
8677 || event.type == EnterNotify
8678 || (dpyinfo->grabbed
8679 && event.type != ButtonRelease))
8680 inhibit_busy_cursor = 2;
8681 else
8682 inhibit_busy_cursor = 1;
8685 #ifdef HAVE_X_I18N
8687 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8688 event.xclient.window);
8689 /* The necessity of the following line took me
8690 a full work-day to decipher from the docs!! */
8691 if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
8692 break;
8694 #endif
8695 event_found = 1;
8697 switch (event.type)
8699 case ClientMessage:
8701 if (event.xclient.message_type
8702 == dpyinfo->Xatom_wm_protocols
8703 && event.xclient.format == 32)
8705 if (event.xclient.data.l[0]
8706 == dpyinfo->Xatom_wm_take_focus)
8708 /* Use x_any_window_to_frame because this
8709 could be the shell widget window
8710 if the frame has no title bar. */
8711 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
8712 #ifdef HAVE_X_I18N
8713 /* Not quite sure this is needed -pd */
8714 if (f && FRAME_XIC (f))
8715 XSetICFocus (FRAME_XIC (f));
8716 #endif
8717 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8718 instructs the WM to set the input focus automatically for
8719 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8720 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8721 it has set the focus. So, XSetInputFocus below is not
8722 needed.
8724 The call to XSetInputFocus below has also caused trouble. In
8725 cases where the XSetInputFocus done by the WM and the one
8726 below are temporally close (on a fast machine), the call
8727 below can generate additional FocusIn events which confuse
8728 Emacs. */
8730 /* Since we set WM_TAKE_FOCUS, we must call
8731 XSetInputFocus explicitly. But not if f is null,
8732 since that might be an event for a deleted frame. */
8733 if (f)
8735 Display *d = event.xclient.display;
8736 /* Catch and ignore errors, in case window has been
8737 iconified by a window manager such as GWM. */
8738 int count = x_catch_errors (d);
8739 XSetInputFocus (d, event.xclient.window,
8740 /* The ICCCM says this is
8741 the only valid choice. */
8742 RevertToParent,
8743 event.xclient.data.l[1]);
8744 /* This is needed to detect the error
8745 if there is an error. */
8746 XSync (d, False);
8747 x_uncatch_errors (d, count);
8749 /* Not certain about handling scroll bars here */
8750 #endif /* 0 */
8752 else if (event.xclient.data.l[0]
8753 == dpyinfo->Xatom_wm_save_yourself)
8755 /* Save state modify the WM_COMMAND property to
8756 something which can reinstate us. This notifies
8757 the session manager, who's looking for such a
8758 PropertyNotify. Can restart processing when
8759 a keyboard or mouse event arrives. */
8760 if (numchars > 0)
8762 f = x_top_window_to_frame (dpyinfo,
8763 event.xclient.window);
8765 /* This is just so we only give real data once
8766 for a single Emacs process. */
8767 if (f == SELECTED_FRAME ())
8768 XSetCommand (FRAME_X_DISPLAY (f),
8769 event.xclient.window,
8770 initial_argv, initial_argc);
8771 else if (f)
8772 XSetCommand (FRAME_X_DISPLAY (f),
8773 event.xclient.window,
8774 0, 0);
8777 else if (event.xclient.data.l[0]
8778 == dpyinfo->Xatom_wm_delete_window)
8780 struct frame *f
8781 = x_any_window_to_frame (dpyinfo,
8782 event.xclient.window);
8784 if (f)
8786 if (numchars == 0)
8787 abort ();
8789 bufp->kind = delete_window_event;
8790 XSETFRAME (bufp->frame_or_window, f);
8791 bufp++;
8793 count += 1;
8794 numchars -= 1;
8798 else if (event.xclient.message_type
8799 == dpyinfo->Xatom_wm_configure_denied)
8802 else if (event.xclient.message_type
8803 == dpyinfo->Xatom_wm_window_moved)
8805 int new_x, new_y;
8806 struct frame *f
8807 = x_window_to_frame (dpyinfo, event.xclient.window);
8809 new_x = event.xclient.data.s[0];
8810 new_y = event.xclient.data.s[1];
8812 if (f)
8814 f->output_data.x->left_pos = new_x;
8815 f->output_data.x->top_pos = new_y;
8818 #ifdef HACK_EDITRES
8819 else if (event.xclient.message_type
8820 == dpyinfo->Xatom_editres)
8822 struct frame *f
8823 = x_any_window_to_frame (dpyinfo, event.xclient.window);
8824 _XEditResCheckMessages (f->output_data.x->widget, NULL,
8825 &event, NULL);
8827 #endif /* HACK_EDITRES */
8828 else if ((event.xclient.message_type
8829 == dpyinfo->Xatom_DONE)
8830 || (event.xclient.message_type
8831 == dpyinfo->Xatom_PAGE))
8833 /* Ghostview job completed. Kill it. We could
8834 reply with "Next" if we received "Page", but we
8835 currently never do because we are interested in
8836 images, only, which should have 1 page. */
8837 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
8838 struct frame *f
8839 = x_window_to_frame (dpyinfo, event.xclient.window);
8840 x_kill_gs_process (pixmap, f);
8841 expose_frame (f, 0, 0, 0, 0);
8843 #ifdef USE_TOOLKIT_SCROLL_BARS
8844 /* Scroll bar callbacks send a ClientMessage from which
8845 we construct an input_event. */
8846 else if (event.xclient.message_type
8847 == dpyinfo->Xatom_Scrollbar)
8849 x_scroll_bar_to_input_event (&event, bufp);
8850 ++bufp, ++count, --numchars;
8851 goto out;
8853 #endif /* USE_TOOLKIT_SCROLL_BARS */
8854 else
8855 goto OTHER;
8857 break;
8859 case SelectionNotify:
8860 #ifdef USE_X_TOOLKIT
8861 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
8862 goto OTHER;
8863 #endif /* not USE_X_TOOLKIT */
8864 x_handle_selection_notify (&event.xselection);
8865 break;
8867 case SelectionClear: /* Someone has grabbed ownership. */
8868 #ifdef USE_X_TOOLKIT
8869 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
8870 goto OTHER;
8871 #endif /* USE_X_TOOLKIT */
8873 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
8875 if (numchars == 0)
8876 abort ();
8878 bufp->kind = selection_clear_event;
8879 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8880 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8881 SELECTION_EVENT_TIME (bufp) = eventp->time;
8882 bufp->frame_or_window = Qnil;
8883 bufp++;
8885 count += 1;
8886 numchars -= 1;
8888 break;
8890 case SelectionRequest: /* Someone wants our selection. */
8891 #ifdef USE_X_TOOLKIT
8892 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
8893 goto OTHER;
8894 #endif /* USE_X_TOOLKIT */
8895 if (x_queue_selection_requests)
8896 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
8897 &event);
8898 else
8900 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
8902 if (numchars == 0)
8903 abort ();
8905 bufp->kind = selection_request_event;
8906 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8907 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
8908 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8909 SELECTION_EVENT_TARGET (bufp) = eventp->target;
8910 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
8911 SELECTION_EVENT_TIME (bufp) = eventp->time;
8912 bufp->frame_or_window = Qnil;
8913 bufp++;
8915 count += 1;
8916 numchars -= 1;
8918 break;
8920 case PropertyNotify:
8921 #ifdef USE_X_TOOLKIT
8922 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
8923 goto OTHER;
8924 #endif /* not USE_X_TOOLKIT */
8925 x_handle_property_notify (&event.xproperty);
8926 break;
8928 case ReparentNotify:
8929 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
8930 if (f)
8932 int x, y;
8933 f->output_data.x->parent_desc = event.xreparent.parent;
8934 x_real_positions (f, &x, &y);
8935 f->output_data.x->left_pos = x;
8936 f->output_data.x->top_pos = y;
8938 break;
8940 case Expose:
8941 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8942 if (f)
8944 if (f->async_visible == 0)
8946 f->async_visible = 1;
8947 f->async_iconified = 0;
8948 f->output_data.x->has_been_visible = 1;
8949 SET_FRAME_GARBAGED (f);
8951 else
8952 expose_frame (x_window_to_frame (dpyinfo,
8953 event.xexpose.window),
8954 event.xexpose.x, event.xexpose.y,
8955 event.xexpose.width, event.xexpose.height);
8957 else
8959 #ifdef USE_TOOLKIT_SCROLL_BARS
8960 /* Dispatch event to the widget. */
8961 goto OTHER;
8962 #else /* not USE_TOOLKIT_SCROLL_BARS */
8963 struct scroll_bar *bar
8964 = x_window_to_scroll_bar (event.xexpose.window);
8966 if (bar)
8967 x_scroll_bar_expose (bar, &event);
8968 #ifdef USE_X_TOOLKIT
8969 else
8970 goto OTHER;
8971 #endif /* USE_X_TOOLKIT */
8972 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8974 break;
8976 case GraphicsExpose: /* This occurs when an XCopyArea's
8977 source area was obscured or not
8978 available.*/
8979 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
8980 if (f)
8982 expose_frame (f,
8983 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
8984 event.xgraphicsexpose.width,
8985 event.xgraphicsexpose.height);
8987 #ifdef USE_X_TOOLKIT
8988 else
8989 goto OTHER;
8990 #endif /* USE_X_TOOLKIT */
8991 break;
8993 case NoExpose: /* This occurs when an XCopyArea's
8994 source area was completely
8995 available */
8996 break;
8998 case UnmapNotify:
8999 /* Redo the mouse-highlight after the tooltip has gone. */
9000 if (event.xmap.window == tip_window)
9002 tip_window = 0;
9003 redo_mouse_highlight ();
9006 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9007 if (f) /* F may no longer exist if
9008 the frame was deleted. */
9010 /* While a frame is unmapped, display generation is
9011 disabled; you don't want to spend time updating a
9012 display that won't ever be seen. */
9013 f->async_visible = 0;
9014 /* We can't distinguish, from the event, whether the window
9015 has become iconified or invisible. So assume, if it
9016 was previously visible, than now it is iconified.
9017 But x_make_frame_invisible clears both
9018 the visible flag and the iconified flag;
9019 and that way, we know the window is not iconified now. */
9020 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9022 f->async_iconified = 1;
9024 bufp->kind = iconify_event;
9025 XSETFRAME (bufp->frame_or_window, f);
9026 bufp++;
9027 count++;
9028 numchars--;
9031 goto OTHER;
9033 case MapNotify:
9034 if (event.xmap.window == tip_window)
9035 /* The tooltip has been drawn already. Avoid
9036 the SET_FRAME_GARBAGED below. */
9037 goto OTHER;
9039 /* We use x_top_window_to_frame because map events can
9040 come for sub-windows and they don't mean that the
9041 frame is visible. */
9042 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9043 if (f)
9045 f->async_visible = 1;
9046 f->async_iconified = 0;
9047 f->output_data.x->has_been_visible = 1;
9049 /* wait_reading_process_input will notice this and update
9050 the frame's display structures. */
9051 SET_FRAME_GARBAGED (f);
9053 if (f->iconified)
9055 bufp->kind = deiconify_event;
9056 XSETFRAME (bufp->frame_or_window, f);
9057 bufp++;
9058 count++;
9059 numchars--;
9061 else if (! NILP (Vframe_list)
9062 && ! NILP (XCDR (Vframe_list)))
9063 /* Force a redisplay sooner or later
9064 to update the frame titles
9065 in case this is the second frame. */
9066 record_asynch_buffer_change ();
9068 goto OTHER;
9070 case KeyPress:
9071 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9073 #ifdef USE_MOTIF
9074 /* I couldn't find a way to prevent LessTif scroll bars
9075 from consuming key events. */
9076 if (f == 0)
9078 Widget widget = XtWindowToWidget (dpyinfo->display,
9079 event.xkey.window);
9080 if (widget && XmIsScrollBar (widget))
9082 widget = XtParent (widget);
9083 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9086 #endif /* USE_MOTIF */
9088 if (f != 0)
9090 KeySym keysym, orig_keysym;
9091 /* al%imercury@uunet.uu.net says that making this 81 instead of
9092 80 fixed a bug whereby meta chars made his Emacs hang. */
9093 unsigned char copy_buffer[81];
9094 int modifiers;
9096 event.xkey.state
9097 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9098 extra_keyboard_modifiers);
9099 modifiers = event.xkey.state;
9101 /* This will have to go some day... */
9103 /* make_lispy_event turns chars into control chars.
9104 Don't do it here because XLookupString is too eager. */
9105 event.xkey.state &= ~ControlMask;
9106 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9107 | dpyinfo->super_mod_mask
9108 | dpyinfo->hyper_mod_mask
9109 | dpyinfo->alt_mod_mask);
9111 /* In case Meta is ComposeCharacter,
9112 clear its status. According to Markus Ehrnsperger
9113 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9114 this enables ComposeCharacter to work whether or
9115 not it is combined with Meta. */
9116 if (modifiers & dpyinfo->meta_mod_mask)
9117 bzero (&compose_status, sizeof (compose_status));
9119 #ifdef HAVE_X_I18N
9120 if (FRAME_XIC (f))
9122 /* The necessity of the following line took me
9123 a full work-day to decipher from the docs!! */
9124 if (XFilterEvent (&event, None))
9125 break;
9126 nbytes = XmbLookupString (FRAME_XIC (f),
9127 &event.xkey, copy_buffer,
9128 80, &keysym,
9129 &status_return);
9130 if (status_return == XLookupNone)
9131 break;
9132 else if (status_return == XLookupChars)
9133 keysym = NoSymbol;
9134 else if (status_return != XLookupKeySym
9135 && status_return != XLookupBoth)
9136 abort ();
9138 else
9139 nbytes = XLookupString (&event.xkey, copy_buffer,
9140 80, &keysym, &compose_status);
9141 #else
9142 nbytes = XLookupString (&event.xkey, copy_buffer,
9143 80, &keysym, &compose_status);
9144 #endif
9146 orig_keysym = keysym;
9148 if (numchars > 1)
9150 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9151 || keysym == XK_Delete
9152 #ifdef XK_ISO_Left_Tab
9153 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9154 #endif
9155 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9156 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9157 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9158 #ifdef HPUX
9159 /* This recognizes the "extended function keys".
9160 It seems there's no cleaner way.
9161 Test IsModifierKey to avoid handling mode_switch
9162 incorrectly. */
9163 || ((unsigned) (keysym) >= XK_Select
9164 && (unsigned)(keysym) < XK_KP_Space)
9165 #endif
9166 #ifdef XK_dead_circumflex
9167 || orig_keysym == XK_dead_circumflex
9168 #endif
9169 #ifdef XK_dead_grave
9170 || orig_keysym == XK_dead_grave
9171 #endif
9172 #ifdef XK_dead_tilde
9173 || orig_keysym == XK_dead_tilde
9174 #endif
9175 #ifdef XK_dead_diaeresis
9176 || orig_keysym == XK_dead_diaeresis
9177 #endif
9178 #ifdef XK_dead_macron
9179 || orig_keysym == XK_dead_macron
9180 #endif
9181 #ifdef XK_dead_degree
9182 || orig_keysym == XK_dead_degree
9183 #endif
9184 #ifdef XK_dead_acute
9185 || orig_keysym == XK_dead_acute
9186 #endif
9187 #ifdef XK_dead_cedilla
9188 || orig_keysym == XK_dead_cedilla
9189 #endif
9190 #ifdef XK_dead_breve
9191 || orig_keysym == XK_dead_breve
9192 #endif
9193 #ifdef XK_dead_ogonek
9194 || orig_keysym == XK_dead_ogonek
9195 #endif
9196 #ifdef XK_dead_caron
9197 || orig_keysym == XK_dead_caron
9198 #endif
9199 #ifdef XK_dead_doubleacute
9200 || orig_keysym == XK_dead_doubleacute
9201 #endif
9202 #ifdef XK_dead_abovedot
9203 || orig_keysym == XK_dead_abovedot
9204 #endif
9205 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9206 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9207 /* Any "vendor-specific" key is ok. */
9208 || (orig_keysym & (1 << 28)))
9209 && ! (IsModifierKey (orig_keysym)
9210 #ifndef HAVE_X11R5
9211 #ifdef XK_Mode_switch
9212 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9213 #endif
9214 #ifdef XK_Num_Lock
9215 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9216 #endif
9217 #endif /* not HAVE_X11R5 */
9220 if (temp_index == sizeof temp_buffer / sizeof (short))
9221 temp_index = 0;
9222 temp_buffer[temp_index++] = keysym;
9223 bufp->kind = non_ascii_keystroke;
9224 bufp->code = keysym;
9225 XSETFRAME (bufp->frame_or_window, f);
9226 bufp->modifiers
9227 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9228 modifiers);
9229 bufp->timestamp = event.xkey.time;
9230 bufp++;
9231 count++;
9232 numchars--;
9234 if (display_busy_cursor_p)
9235 if (keysym != XK_Return || minibuf_level == 0)
9236 inhibit_busy_cursor = 2;
9238 else if (numchars > nbytes)
9240 register int i;
9242 for (i = 0; i < nbytes; i++)
9244 if (temp_index == sizeof temp_buffer / sizeof (short))
9245 temp_index = 0;
9246 temp_buffer[temp_index++] = copy_buffer[i];
9247 bufp->kind = ascii_keystroke;
9248 bufp->code = copy_buffer[i];
9249 XSETFRAME (bufp->frame_or_window, f);
9250 bufp->modifiers
9251 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9252 modifiers);
9253 bufp->timestamp = event.xkey.time;
9254 bufp++;
9257 count += nbytes;
9258 numchars -= nbytes;
9260 if (keysym == NoSymbol)
9261 break;
9263 else
9264 abort ();
9266 else
9267 abort ();
9269 goto OTHER;
9271 /* Here's a possible interpretation of the whole
9272 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9273 you get a FocusIn event, you have to get a FocusOut
9274 event before you relinquish the focus. If you
9275 haven't received a FocusIn event, then a mere
9276 LeaveNotify is enough to free you. */
9278 case EnterNotify:
9280 int from_menu_bar_p = 0;
9282 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9284 #ifdef LESSTIF_VERSION
9285 /* When clicking outside of a menu bar popup to close
9286 it, we get a FocusIn/ EnterNotify sequence of
9287 events. The flag event.xcrossing.focus is not set
9288 in the EnterNotify event of that sequence because
9289 the focus is in the menu bar,
9290 event.xcrossing.window is the frame's X window.
9291 Unconditionally setting the focus frame to null in
9292 this case is not the right thing, because no event
9293 follows that could set the focus frame to the right
9294 value.
9296 This could be a LessTif bug, but I wasn't able to
9297 reproduce the behavior in a simple test program.
9299 (gerd, LessTif 0.88.1). */
9301 if (!event.xcrossing.focus
9302 && f
9303 && f->output_data.x->menubar_widget)
9305 Window focus;
9306 int revert;
9308 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9309 if (focus == XtWindow (f->output_data.x->menubar_widget))
9310 from_menu_bar_p = 1;
9312 #endif /* LESSTIF_VERSION */
9314 if (event.xcrossing.focus || from_menu_bar_p)
9316 /* Avoid nasty pop/raise loops. */
9317 if (f && (!(f->auto_raise)
9318 || !(f->auto_lower)
9319 || (event.xcrossing.time - enter_timestamp) > 500))
9321 x_new_focus_frame (dpyinfo, f);
9322 enter_timestamp = event.xcrossing.time;
9325 else if (f == dpyinfo->x_focus_frame)
9326 x_new_focus_frame (dpyinfo, 0);
9328 /* EnterNotify counts as mouse movement,
9329 so update things that depend on mouse position. */
9330 if (f && !f->output_data.x->busy_p)
9331 note_mouse_movement (f, &event.xmotion);
9332 goto OTHER;
9335 case FocusIn:
9336 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9337 if (event.xfocus.detail != NotifyPointer)
9338 dpyinfo->x_focus_event_frame = f;
9339 if (f)
9340 x_new_focus_frame (dpyinfo, f);
9342 #ifdef HAVE_X_I18N
9343 if (f && FRAME_XIC (f))
9344 XSetICFocus (FRAME_XIC (f));
9345 #endif
9347 goto OTHER;
9349 case LeaveNotify:
9350 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9351 if (f)
9353 Lisp_Object frame;
9354 int from_menu_bar_p = 0;
9356 if (f == dpyinfo->mouse_face_mouse_frame)
9358 /* If we move outside the frame, then we're
9359 certainly no longer on any text in the frame. */
9360 clear_mouse_face (dpyinfo);
9361 dpyinfo->mouse_face_mouse_frame = 0;
9364 /* Generate a nil HELP_EVENT to cancel a help-echo.
9365 Do it only if there's something to cancel.
9366 Otherwise, the startup message is cleared when
9367 the mouse leaves the frame. */
9368 if (any_help_event_p)
9370 XSETFRAME (frame, f);
9371 bufp->kind = HELP_EVENT;
9372 bufp->frame_or_window = Fcons (frame, Qnil);
9373 ++bufp, ++count, --numchars;
9376 #ifdef LESSTIF_VERSION
9377 /* Please see the comment at the start of the
9378 EnterNotify case. */
9379 if (!event.xcrossing.focus
9380 && f->output_data.x->menubar_widget)
9382 Window focus;
9383 int revert;
9384 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9385 if (focus == XtWindow (f->output_data.x->menubar_widget))
9386 from_menu_bar_p = 1;
9388 #endif /* LESSTIF_VERSION */
9390 if (event.xcrossing.focus || from_menu_bar_p)
9391 x_mouse_leave (dpyinfo);
9392 else
9394 if (f == dpyinfo->x_focus_event_frame)
9395 dpyinfo->x_focus_event_frame = 0;
9396 if (f == dpyinfo->x_focus_frame)
9397 x_new_focus_frame (dpyinfo, 0);
9400 goto OTHER;
9402 case FocusOut:
9403 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9404 if (event.xfocus.detail != NotifyPointer
9405 && f == dpyinfo->x_focus_event_frame)
9406 dpyinfo->x_focus_event_frame = 0;
9407 if (f && f == dpyinfo->x_focus_frame)
9408 x_new_focus_frame (dpyinfo, 0);
9410 #ifdef HAVE_X_I18N
9411 if (f && FRAME_XIC (f))
9412 XUnsetICFocus (FRAME_XIC (f));
9413 #endif
9415 goto OTHER;
9417 case MotionNotify:
9419 previous_help_echo = help_echo;
9420 help_echo = Qnil;
9422 if (dpyinfo->grabbed && last_mouse_frame
9423 && FRAME_LIVE_P (last_mouse_frame))
9424 f = last_mouse_frame;
9425 else
9426 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9428 if (f)
9429 note_mouse_movement (f, &event.xmotion);
9430 else
9432 #ifndef USE_TOOLKIT_SCROLL_BARS
9433 struct scroll_bar *bar
9434 = x_window_to_scroll_bar (event.xmotion.window);
9436 if (bar)
9437 x_scroll_bar_note_movement (bar, &event);
9438 #endif /* USE_TOOLKIT_SCROLL_BARS */
9440 /* If we move outside the frame, then we're
9441 certainly no longer on any text in the frame. */
9442 clear_mouse_face (dpyinfo);
9445 /* If the contents of the global variable help_echo
9446 has changed, generate a HELP_EVENT. */
9447 if (STRINGP (help_echo)
9448 || STRINGP (previous_help_echo))
9450 Lisp_Object frame;
9452 if (f)
9453 XSETFRAME (frame, f);
9454 else
9455 frame = Qnil;
9457 any_help_event_p = 1;
9458 bufp->kind = HELP_EVENT;
9459 bufp->frame_or_window = Fcons (frame, help_echo);
9460 ++bufp, ++count, --numchars;
9463 goto OTHER;
9466 case ConfigureNotify:
9467 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9468 if (f)
9470 #ifndef USE_X_TOOLKIT
9471 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9472 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
9474 /* In the toolkit version, change_frame_size
9475 is called by the code that handles resizing
9476 of the EmacsFrame widget. */
9478 /* Even if the number of character rows and columns has
9479 not changed, the font size may have changed, so we need
9480 to check the pixel dimensions as well. */
9481 if (columns != f->width
9482 || rows != f->height
9483 || event.xconfigure.width != f->output_data.x->pixel_width
9484 || event.xconfigure.height != f->output_data.x->pixel_height)
9486 change_frame_size (f, rows, columns, 0, 1, 0);
9487 SET_FRAME_GARBAGED (f);
9488 cancel_mouse_face (f);
9490 #endif
9492 f->output_data.x->pixel_width = event.xconfigure.width;
9493 f->output_data.x->pixel_height = event.xconfigure.height;
9495 /* What we have now is the position of Emacs's own window.
9496 Convert that to the position of the window manager window. */
9497 x_real_positions (f, &f->output_data.x->left_pos,
9498 &f->output_data.x->top_pos);
9500 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9502 /* Since the WM decorations come below top_pos now,
9503 we must put them below top_pos in the future. */
9504 f->output_data.x->win_gravity = NorthWestGravity;
9505 x_wm_set_size_hint (f, (long) 0, 0);
9507 #ifdef USE_MOTIF
9508 /* Some window managers pass (0,0) as the location of
9509 the window, and the Motif event handler stores it
9510 in the emacs widget, which messes up Motif menus. */
9511 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9513 event.xconfigure.x = f->output_data.x->widget->core.x;
9514 event.xconfigure.y = f->output_data.x->widget->core.y;
9516 #endif /* USE_MOTIF */
9518 goto OTHER;
9520 case ButtonPress:
9521 case ButtonRelease:
9523 /* If we decide we want to generate an event to be seen
9524 by the rest of Emacs, we put it here. */
9525 struct input_event emacs_event;
9526 int tool_bar_p = 0;
9528 emacs_event.kind = no_event;
9529 bzero (&compose_status, sizeof (compose_status));
9531 if (dpyinfo->grabbed
9532 && last_mouse_frame
9533 && FRAME_LIVE_P (last_mouse_frame))
9534 f = last_mouse_frame;
9535 else
9536 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9538 if (f)
9540 /* Is this in the tool-bar? */
9541 if (WINDOWP (f->tool_bar_window)
9542 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
9544 Lisp_Object window;
9545 int p, x, y;
9547 x = event.xbutton.x;
9548 y = event.xbutton.y;
9550 /* Set x and y. */
9551 window = window_from_coordinates (f, x, y, &p, 1);
9552 if (EQ (window, f->tool_bar_window))
9554 x_handle_tool_bar_click (f, &event.xbutton);
9555 tool_bar_p = 1;
9559 if (!tool_bar_p)
9560 if (!dpyinfo->x_focus_frame
9561 || f == dpyinfo->x_focus_frame)
9562 construct_mouse_click (&emacs_event, &event, f);
9564 else
9566 #ifndef USE_TOOLKIT_SCROLL_BARS
9567 struct scroll_bar *bar
9568 = x_window_to_scroll_bar (event.xbutton.window);
9570 if (bar)
9571 x_scroll_bar_handle_click (bar, &event, &emacs_event);
9572 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9575 if (event.type == ButtonPress)
9577 dpyinfo->grabbed |= (1 << event.xbutton.button);
9578 last_mouse_frame = f;
9579 /* Ignore any mouse motion that happened
9580 before this event; any subsequent mouse-movement
9581 Emacs events should reflect only motion after
9582 the ButtonPress. */
9583 if (f != 0)
9584 f->mouse_moved = 0;
9586 if (!tool_bar_p)
9587 last_tool_bar_item = -1;
9588 if (display_busy_cursor_p)
9589 inhibit_busy_cursor = 2;
9591 else
9593 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
9596 if (numchars >= 1 && emacs_event.kind != no_event)
9598 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9599 bufp++;
9600 count++;
9601 numchars--;
9604 #ifdef USE_X_TOOLKIT
9605 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9606 /* For a down-event in the menu bar,
9607 don't pass it to Xt right now.
9608 Instead, save it away
9609 and we will pass it to Xt from kbd_buffer_get_event.
9610 That way, we can run some Lisp code first. */
9611 if (f && event.type == ButtonPress
9612 /* Verify the event is really within the menu bar
9613 and not just sent to it due to grabbing. */
9614 && event.xbutton.x >= 0
9615 && event.xbutton.x < f->output_data.x->pixel_width
9616 && event.xbutton.y >= 0
9617 && event.xbutton.y < f->output_data.x->menubar_height
9618 && event.xbutton.same_screen)
9620 SET_SAVED_BUTTON_EVENT;
9621 XSETFRAME (last_mouse_press_frame, f);
9623 else if (event.type == ButtonPress)
9625 last_mouse_press_frame = Qnil;
9626 goto OTHER;
9629 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9630 but I am trying to be cautious. */
9631 else if (event.type == ButtonRelease)
9633 if (!NILP (last_mouse_press_frame))
9635 f = XFRAME (last_mouse_press_frame);
9636 if (f->output_data.x)
9637 SET_SAVED_BUTTON_EVENT;
9639 else
9640 goto OTHER;
9642 #endif /* USE_MOTIF */
9643 else
9644 goto OTHER;
9645 #endif /* USE_X_TOOLKIT */
9647 break;
9649 case CirculateNotify:
9650 goto OTHER;
9652 case CirculateRequest:
9653 goto OTHER;
9655 case VisibilityNotify:
9656 goto OTHER;
9658 case MappingNotify:
9659 /* Someone has changed the keyboard mapping - update the
9660 local cache. */
9661 switch (event.xmapping.request)
9663 case MappingModifier:
9664 x_find_modifier_meanings (dpyinfo);
9665 /* This is meant to fall through. */
9666 case MappingKeyboard:
9667 XRefreshKeyboardMapping (&event.xmapping);
9669 goto OTHER;
9671 default:
9672 OTHER:
9673 #ifdef USE_X_TOOLKIT
9674 BLOCK_INPUT;
9675 XtDispatchEvent (&event);
9676 UNBLOCK_INPUT;
9677 #endif /* USE_X_TOOLKIT */
9678 break;
9683 out:;
9685 /* On some systems, an X bug causes Emacs to get no more events
9686 when the window is destroyed. Detect that. (1994.) */
9687 if (! event_found)
9689 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9690 One XNOOP in 100 loops will make Emacs terminate.
9691 B. Bretthauer, 1994 */
9692 x_noop_count++;
9693 if (x_noop_count >= 100)
9695 x_noop_count=0;
9697 if (next_noop_dpyinfo == 0)
9698 next_noop_dpyinfo = x_display_list;
9700 XNoOp (next_noop_dpyinfo->display);
9702 /* Each time we get here, cycle through the displays now open. */
9703 next_noop_dpyinfo = next_noop_dpyinfo->next;
9707 /* If the focus was just given to an auto-raising frame,
9708 raise it now. */
9709 /* ??? This ought to be able to handle more than one such frame. */
9710 if (pending_autoraise_frame)
9712 x_raise_frame (pending_autoraise_frame);
9713 pending_autoraise_frame = 0;
9716 UNBLOCK_INPUT;
9717 return count;
9723 /***********************************************************************
9724 Text Cursor
9725 ***********************************************************************/
9727 /* Note if the text cursor of window W has been overwritten by a
9728 drawing operation that outputs N glyphs starting at HPOS in the
9729 line given by output_cursor.vpos. N < 0 means all the rest of the
9730 line after HPOS has been written. */
9732 static void
9733 note_overwritten_text_cursor (w, hpos, n)
9734 struct window *w;
9735 int hpos, n;
9737 if (updated_area == TEXT_AREA
9738 && output_cursor.vpos == w->phys_cursor.vpos
9739 && hpos <= w->phys_cursor.hpos
9740 && (n < 0
9741 || hpos + n > w->phys_cursor.hpos))
9742 w->phys_cursor_on_p = 0;
9746 /* Set clipping for output in glyph row ROW. W is the window in which
9747 we operate. GC is the graphics context to set clipping in.
9748 WHOLE_LINE_P non-zero means include the areas used for truncation
9749 mark display and alike in the clipping rectangle.
9751 ROW may be a text row or, e.g., a mode line. Text rows must be
9752 clipped to the interior of the window dedicated to text display,
9753 mode lines must be clipped to the whole window. */
9755 static void
9756 x_clip_to_row (w, row, gc, whole_line_p)
9757 struct window *w;
9758 struct glyph_row *row;
9759 GC gc;
9760 int whole_line_p;
9762 struct frame *f = XFRAME (WINDOW_FRAME (w));
9763 XRectangle clip_rect;
9764 int window_x, window_y, window_width, window_height;
9766 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9768 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9769 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9770 clip_rect.y = max (clip_rect.y, window_y);
9771 clip_rect.width = window_width;
9772 clip_rect.height = row->visible_height;
9774 /* If clipping to the whole line, including trunc marks, extend
9775 the rectangle to the left and increase its width. */
9776 if (whole_line_p)
9778 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
9779 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
9782 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
9786 /* Draw a hollow box cursor on window W in glyph row ROW. */
9788 static void
9789 x_draw_hollow_cursor (w, row)
9790 struct window *w;
9791 struct glyph_row *row;
9793 struct frame *f = XFRAME (WINDOW_FRAME (w));
9794 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9795 Display *dpy = FRAME_X_DISPLAY (f);
9796 int x, y, wd, h;
9797 XGCValues xgcv;
9798 struct glyph *cursor_glyph;
9799 GC gc;
9801 /* Compute frame-relative coordinates from window-relative
9802 coordinates. */
9803 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9804 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9805 + row->ascent - w->phys_cursor_ascent);
9806 h = row->height - 1;
9808 /* Get the glyph the cursor is on. If we can't tell because
9809 the current matrix is invalid or such, give up. */
9810 cursor_glyph = get_phys_cursor_glyph (w);
9811 if (cursor_glyph == NULL)
9812 return;
9814 /* Compute the width of the rectangle to draw. If on a stretch
9815 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9816 rectangle as wide as the glyph, but use a canonical character
9817 width instead. */
9818 wd = cursor_glyph->pixel_width - 1;
9819 if (cursor_glyph->type == STRETCH_GLYPH
9820 && !x_stretch_cursor_p)
9821 wd = min (CANON_X_UNIT (f), wd);
9823 /* The foreground of cursor_gc is typically the same as the normal
9824 background color, which can cause the cursor box to be invisible. */
9825 xgcv.foreground = f->output_data.x->cursor_pixel;
9826 if (dpyinfo->scratch_cursor_gc)
9827 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9828 else
9829 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
9830 GCForeground, &xgcv);
9831 gc = dpyinfo->scratch_cursor_gc;
9833 /* Set clipping, draw the rectangle, and reset clipping again. */
9834 x_clip_to_row (w, row, gc, 0);
9835 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
9836 XSetClipMask (dpy, gc, None);
9840 /* Draw a bar cursor on window W in glyph row ROW.
9842 Implementation note: One would like to draw a bar cursor with an
9843 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9844 Unfortunately, I didn't find a font yet that has this property set.
9845 --gerd. */
9847 static void
9848 x_draw_bar_cursor (w, row)
9849 struct window *w;
9850 struct glyph_row *row;
9852 /* If cursor hpos is out of bounds, don't draw garbage. This can
9853 happen in mini-buffer windows when switching between echo area
9854 glyphs and mini-buffer. */
9855 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9857 struct frame *f = XFRAME (w->frame);
9858 struct glyph *cursor_glyph;
9859 GC gc;
9860 int x;
9861 unsigned long mask;
9862 XGCValues xgcv;
9863 Display *dpy;
9864 Window window;
9866 cursor_glyph = get_phys_cursor_glyph (w);
9867 if (cursor_glyph == NULL)
9868 return;
9870 xgcv.background = f->output_data.x->cursor_pixel;
9871 xgcv.foreground = f->output_data.x->cursor_pixel;
9872 xgcv.graphics_exposures = 0;
9873 mask = GCForeground | GCBackground | GCGraphicsExposures;
9874 dpy = FRAME_X_DISPLAY (f);
9875 window = FRAME_X_WINDOW (f);
9876 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9878 if (gc)
9879 XChangeGC (dpy, gc, mask, &xgcv);
9880 else
9882 gc = XCreateGC (dpy, window, mask, &xgcv);
9883 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9886 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9887 x_clip_to_row (w, row, gc, 0);
9888 XFillRectangle (dpy, window, gc,
9890 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9891 min (cursor_glyph->pixel_width,
9892 f->output_data.x->cursor_width),
9893 row->height);
9894 XSetClipMask (dpy, gc, None);
9899 /* Clear the cursor of window W to background color, and mark the
9900 cursor as not shown. This is used when the text where the cursor
9901 is is about to be rewritten. */
9903 static void
9904 x_clear_cursor (w)
9905 struct window *w;
9907 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9908 x_update_window_cursor (w, 0);
9912 /* Draw the cursor glyph of window W in glyph row ROW. See the
9913 comment of x_draw_glyphs for the meaning of HL. */
9915 static void
9916 x_draw_phys_cursor_glyph (w, row, hl)
9917 struct window *w;
9918 struct glyph_row *row;
9919 enum draw_glyphs_face hl;
9921 /* If cursor hpos is out of bounds, don't draw garbage. This can
9922 happen in mini-buffer windows when switching between echo area
9923 glyphs and mini-buffer. */
9924 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9926 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9927 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9928 hl, 0, 0, 0);
9930 /* When we erase the cursor, and ROW is overlapped by other
9931 rows, make sure that these overlapping parts of other rows
9932 are redrawn. */
9933 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9935 if (row > w->current_matrix->rows
9936 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9937 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9939 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9940 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9941 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9947 /* Erase the image of a cursor of window W from the screen. */
9949 static void
9950 x_erase_phys_cursor (w)
9951 struct window *w;
9953 struct frame *f = XFRAME (w->frame);
9954 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9955 int hpos = w->phys_cursor.hpos;
9956 int vpos = w->phys_cursor.vpos;
9957 int mouse_face_here_p = 0;
9958 struct glyph_matrix *active_glyphs = w->current_matrix;
9959 struct glyph_row *cursor_row;
9960 struct glyph *cursor_glyph;
9961 enum draw_glyphs_face hl;
9963 /* No cursor displayed or row invalidated => nothing to do on the
9964 screen. */
9965 if (w->phys_cursor_type == NO_CURSOR)
9966 goto mark_cursor_off;
9968 /* VPOS >= active_glyphs->nrows means that window has been resized.
9969 Don't bother to erase the cursor. */
9970 if (vpos >= active_glyphs->nrows)
9971 goto mark_cursor_off;
9973 /* If row containing cursor is marked invalid, there is nothing we
9974 can do. */
9975 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9976 if (!cursor_row->enabled_p)
9977 goto mark_cursor_off;
9979 /* This can happen when the new row is shorter than the old one.
9980 In this case, either x_draw_glyphs or clear_end_of_line
9981 should have cleared the cursor. Note that we wouldn't be
9982 able to erase the cursor in this case because we don't have a
9983 cursor glyph at hand. */
9984 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9985 goto mark_cursor_off;
9987 /* If the cursor is in the mouse face area, redisplay that when
9988 we clear the cursor. */
9989 if (w == XWINDOW (dpyinfo->mouse_face_window)
9990 && (vpos > dpyinfo->mouse_face_beg_row
9991 || (vpos == dpyinfo->mouse_face_beg_row
9992 && hpos >= dpyinfo->mouse_face_beg_col))
9993 && (vpos < dpyinfo->mouse_face_end_row
9994 || (vpos == dpyinfo->mouse_face_end_row
9995 && hpos < dpyinfo->mouse_face_end_col))
9996 /* Don't redraw the cursor's spot in mouse face if it is at the
9997 end of a line (on a newline). The cursor appears there, but
9998 mouse highlighting does not. */
9999 && cursor_row->used[TEXT_AREA] > hpos)
10000 mouse_face_here_p = 1;
10002 /* Maybe clear the display under the cursor. */
10003 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10005 int x;
10006 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10008 cursor_glyph = get_phys_cursor_glyph (w);
10009 if (cursor_glyph == NULL)
10010 goto mark_cursor_off;
10012 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10014 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10016 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10017 cursor_row->y)),
10018 cursor_glyph->pixel_width,
10019 cursor_row->visible_height,
10020 False);
10023 /* Erase the cursor by redrawing the character underneath it. */
10024 if (mouse_face_here_p)
10025 hl = DRAW_MOUSE_FACE;
10026 else if (cursor_row->inverse_p)
10027 hl = DRAW_INVERSE_VIDEO;
10028 else
10029 hl = DRAW_NORMAL_TEXT;
10030 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10032 mark_cursor_off:
10033 w->phys_cursor_on_p = 0;
10034 w->phys_cursor_type = NO_CURSOR;
10038 /* Display or clear cursor of window W. If ON is zero, clear the
10039 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10040 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10042 void
10043 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10044 struct window *w;
10045 int on, hpos, vpos, x, y;
10047 struct frame *f = XFRAME (w->frame);
10048 int new_cursor_type;
10049 struct glyph_matrix *current_glyphs;
10050 struct glyph_row *glyph_row;
10051 struct glyph *glyph;
10053 /* This is pointless on invisible frames, and dangerous on garbaged
10054 windows and frames; in the latter case, the frame or window may
10055 be in the midst of changing its size, and x and y may be off the
10056 window. */
10057 if (! FRAME_VISIBLE_P (f)
10058 || FRAME_GARBAGED_P (f)
10059 || vpos >= w->current_matrix->nrows
10060 || hpos >= w->current_matrix->matrix_w)
10061 return;
10063 /* If cursor is off and we want it off, return quickly. */
10064 if (!on && !w->phys_cursor_on_p)
10065 return;
10067 current_glyphs = w->current_matrix;
10068 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10069 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10071 /* If cursor row is not enabled, we don't really know where to
10072 display the cursor. */
10073 if (!glyph_row->enabled_p)
10075 w->phys_cursor_on_p = 0;
10076 return;
10079 xassert (interrupt_input_blocked);
10081 /* Set new_cursor_type to the cursor we want to be displayed. In a
10082 mini-buffer window, we want the cursor only to appear if we are
10083 reading input from this window. For the selected window, we want
10084 the cursor type given by the frame parameter. If explicitly
10085 marked off, draw no cursor. In all other cases, we want a hollow
10086 box cursor. */
10087 if (cursor_in_echo_area
10088 && FRAME_HAS_MINIBUF_P (f)
10089 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10091 if (w == XWINDOW (echo_area_window))
10092 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10093 else
10094 new_cursor_type = HOLLOW_BOX_CURSOR;
10096 else
10098 if (w != XWINDOW (selected_window)
10099 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10101 if (MINI_WINDOW_P (w))
10102 new_cursor_type = NO_CURSOR;
10103 else
10104 new_cursor_type = HOLLOW_BOX_CURSOR;
10106 else if (w->cursor_off_p)
10107 new_cursor_type = NO_CURSOR;
10108 else
10109 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10112 /* If cursor is currently being shown and we don't want it to be or
10113 it is in the wrong place, or the cursor type is not what we want,
10114 erase it. */
10115 if (w->phys_cursor_on_p
10116 && (!on
10117 || w->phys_cursor.x != x
10118 || w->phys_cursor.y != y
10119 || new_cursor_type != w->phys_cursor_type))
10120 x_erase_phys_cursor (w);
10122 /* If the cursor is now invisible and we want it to be visible,
10123 display it. */
10124 if (on && !w->phys_cursor_on_p)
10126 w->phys_cursor_ascent = glyph_row->ascent;
10127 w->phys_cursor_height = glyph_row->height;
10129 /* Set phys_cursor_.* before x_draw_.* is called because some
10130 of them may need the information. */
10131 w->phys_cursor.x = x;
10132 w->phys_cursor.y = glyph_row->y;
10133 w->phys_cursor.hpos = hpos;
10134 w->phys_cursor.vpos = vpos;
10135 w->phys_cursor_type = new_cursor_type;
10136 w->phys_cursor_on_p = 1;
10138 switch (new_cursor_type)
10140 case HOLLOW_BOX_CURSOR:
10141 x_draw_hollow_cursor (w, glyph_row);
10142 break;
10144 case FILLED_BOX_CURSOR:
10145 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10146 break;
10148 case BAR_CURSOR:
10149 x_draw_bar_cursor (w, glyph_row);
10150 break;
10152 case NO_CURSOR:
10153 break;
10155 default:
10156 abort ();
10160 #ifndef XFlush
10161 if (updating_frame != f)
10162 XFlush (FRAME_X_DISPLAY (f));
10163 #endif
10167 /* Display the cursor on window W, or clear it. X and Y are window
10168 relative pixel coordinates. HPOS and VPOS are glyph matrix
10169 positions. If W is not the selected window, display a hollow
10170 cursor. ON non-zero means display the cursor at X, Y which
10171 correspond to HPOS, VPOS, otherwise it is cleared. */
10173 void
10174 x_display_cursor (w, on, hpos, vpos, x, y)
10175 struct window *w;
10176 int on, hpos, vpos, x, y;
10178 BLOCK_INPUT;
10179 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10180 UNBLOCK_INPUT;
10184 /* Display the cursor on window W, or clear it, according to ON_P.
10185 Don't change the cursor's position. */
10187 void
10188 x_update_cursor (f, on_p)
10189 struct frame *f;
10191 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10195 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10196 in the window tree rooted at W. */
10198 static void
10199 x_update_cursor_in_window_tree (w, on_p)
10200 struct window *w;
10201 int on_p;
10203 while (w)
10205 if (!NILP (w->hchild))
10206 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10207 else if (!NILP (w->vchild))
10208 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10209 else
10210 x_update_window_cursor (w, on_p);
10212 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10217 /* Switch the display of W's cursor on or off, according to the value
10218 of ON. */
10220 static void
10221 x_update_window_cursor (w, on)
10222 struct window *w;
10223 int on;
10225 BLOCK_INPUT;
10226 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10227 w->phys_cursor.x, w->phys_cursor.y);
10228 UNBLOCK_INPUT;
10234 /* Icons. */
10236 /* Refresh bitmap kitchen sink icon for frame F
10237 when we get an expose event for it. */
10239 void
10240 refreshicon (f)
10241 struct frame *f;
10243 /* Normally, the window manager handles this function. */
10246 /* Make the x-window of frame F use the gnu icon bitmap. */
10249 x_bitmap_icon (f, file)
10250 struct frame *f;
10251 Lisp_Object file;
10253 int bitmap_id;
10255 if (FRAME_X_WINDOW (f) == 0)
10256 return 1;
10258 /* Free up our existing icon bitmap if any. */
10259 if (f->output_data.x->icon_bitmap > 0)
10260 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10261 f->output_data.x->icon_bitmap = 0;
10263 if (STRINGP (file))
10264 bitmap_id = x_create_bitmap_from_file (f, file);
10265 else
10267 /* Create the GNU bitmap if necessary. */
10268 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10269 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10270 = x_create_bitmap_from_data (f, gnu_bits,
10271 gnu_width, gnu_height);
10273 /* The first time we create the GNU bitmap,
10274 this increments the ref-count one extra time.
10275 As a result, the GNU bitmap is never freed.
10276 That way, we don't have to worry about allocating it again. */
10277 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10279 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10282 x_wm_set_icon_pixmap (f, bitmap_id);
10283 f->output_data.x->icon_bitmap = bitmap_id;
10285 return 0;
10289 /* Make the x-window of frame F use a rectangle with text.
10290 Use ICON_NAME as the text. */
10293 x_text_icon (f, icon_name)
10294 struct frame *f;
10295 char *icon_name;
10297 if (FRAME_X_WINDOW (f) == 0)
10298 return 1;
10300 #ifdef HAVE_X11R4
10302 XTextProperty text;
10303 text.value = (unsigned char *) icon_name;
10304 text.encoding = XA_STRING;
10305 text.format = 8;
10306 text.nitems = strlen (icon_name);
10307 #ifdef USE_X_TOOLKIT
10308 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10309 &text);
10310 #else /* not USE_X_TOOLKIT */
10311 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10312 #endif /* not USE_X_TOOLKIT */
10314 #else /* not HAVE_X11R4 */
10315 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10316 #endif /* not HAVE_X11R4 */
10318 if (f->output_data.x->icon_bitmap > 0)
10319 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10320 f->output_data.x->icon_bitmap = 0;
10321 x_wm_set_icon_pixmap (f, 0);
10323 return 0;
10326 #define X_ERROR_MESSAGE_SIZE 200
10328 /* If non-nil, this should be a string.
10329 It means catch X errors and store the error message in this string. */
10331 static Lisp_Object x_error_message_string;
10333 /* An X error handler which stores the error message in
10334 x_error_message_string. This is called from x_error_handler if
10335 x_catch_errors is in effect. */
10337 static void
10338 x_error_catcher (display, error)
10339 Display *display;
10340 XErrorEvent *error;
10342 XGetErrorText (display, error->error_code,
10343 XSTRING (x_error_message_string)->data,
10344 X_ERROR_MESSAGE_SIZE);
10347 /* Begin trapping X errors for display DPY. Actually we trap X errors
10348 for all displays, but DPY should be the display you are actually
10349 operating on.
10351 After calling this function, X protocol errors no longer cause
10352 Emacs to exit; instead, they are recorded in the string
10353 stored in x_error_message_string.
10355 Calling x_check_errors signals an Emacs error if an X error has
10356 occurred since the last call to x_catch_errors or x_check_errors.
10358 Calling x_uncatch_errors resumes the normal error handling. */
10360 void x_check_errors ();
10361 static Lisp_Object x_catch_errors_unwind ();
10364 x_catch_errors (dpy)
10365 Display *dpy;
10367 int count = specpdl_ptr - specpdl;
10369 /* Make sure any errors from previous requests have been dealt with. */
10370 XSync (dpy, False);
10372 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10374 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10375 XSTRING (x_error_message_string)->data[0] = 0;
10377 return count;
10380 /* Unbind the binding that we made to check for X errors. */
10382 static Lisp_Object
10383 x_catch_errors_unwind (old_val)
10384 Lisp_Object old_val;
10386 x_error_message_string = old_val;
10387 return Qnil;
10390 /* If any X protocol errors have arrived since the last call to
10391 x_catch_errors or x_check_errors, signal an Emacs error using
10392 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10394 void
10395 x_check_errors (dpy, format)
10396 Display *dpy;
10397 char *format;
10399 /* Make sure to catch any errors incurred so far. */
10400 XSync (dpy, False);
10402 if (XSTRING (x_error_message_string)->data[0])
10403 error (format, XSTRING (x_error_message_string)->data);
10406 /* Nonzero if we had any X protocol errors
10407 since we did x_catch_errors on DPY. */
10410 x_had_errors_p (dpy)
10411 Display *dpy;
10413 /* Make sure to catch any errors incurred so far. */
10414 XSync (dpy, False);
10416 return XSTRING (x_error_message_string)->data[0] != 0;
10419 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10421 void
10422 x_clear_errors (dpy)
10423 Display *dpy;
10425 XSTRING (x_error_message_string)->data[0] = 0;
10428 /* Stop catching X protocol errors and let them make Emacs die.
10429 DPY should be the display that was passed to x_catch_errors.
10430 COUNT should be the value that was returned by
10431 the corresponding call to x_catch_errors. */
10433 void
10434 x_uncatch_errors (dpy, count)
10435 Display *dpy;
10436 int count;
10438 unbind_to (count, Qnil);
10441 #if 0
10442 static unsigned int x_wire_count;
10443 x_trace_wire ()
10445 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10447 #endif /* ! 0 */
10450 /* Handle SIGPIPE, which can happen when the connection to a server
10451 simply goes away. SIGPIPE is handled by x_connection_signal.
10452 Don't need to do anything, because the write which caused the
10453 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10454 which will do the appropriate cleanup for us. */
10456 static SIGTYPE
10457 x_connection_signal (signalnum) /* If we don't have an argument, */
10458 int signalnum; /* some compilers complain in signal calls. */
10460 #ifdef USG
10461 /* USG systems forget handlers when they are used;
10462 must reestablish each time */
10463 signal (signalnum, x_connection_signal);
10464 #endif /* USG */
10467 /* Handling X errors. */
10469 /* Handle the loss of connection to display DISPLAY. */
10471 static SIGTYPE
10472 x_connection_closed (display, error_message)
10473 Display *display;
10474 char *error_message;
10476 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10477 Lisp_Object frame, tail;
10479 /* Indicate that this display is dead. */
10481 #ifdef USE_X_TOOLKIT
10482 XtCloseDisplay (display);
10483 #endif
10485 dpyinfo->display = 0;
10487 /* First delete frames whose mini-buffers are on frames
10488 that are on the dead display. */
10489 FOR_EACH_FRAME (tail, frame)
10491 Lisp_Object minibuf_frame;
10492 minibuf_frame
10493 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10494 if (FRAME_X_P (XFRAME (frame))
10495 && FRAME_X_P (XFRAME (minibuf_frame))
10496 && ! EQ (frame, minibuf_frame)
10497 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10498 Fdelete_frame (frame, Qt);
10501 /* Now delete all remaining frames on the dead display.
10502 We are now sure none of these is used as the mini-buffer
10503 for another frame that we need to delete. */
10504 FOR_EACH_FRAME (tail, frame)
10505 if (FRAME_X_P (XFRAME (frame))
10506 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10508 /* Set this to t so that Fdelete_frame won't get confused
10509 trying to find a replacement. */
10510 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10511 Fdelete_frame (frame, Qt);
10514 if (dpyinfo)
10515 x_delete_display (dpyinfo);
10517 if (x_display_list == 0)
10519 fprintf (stderr, "%s\n", error_message);
10520 shut_down_emacs (0, 0, Qnil);
10521 exit (70);
10524 /* Ordinary stack unwind doesn't deal with these. */
10525 #ifdef SIGIO
10526 sigunblock (sigmask (SIGIO));
10527 #endif
10528 sigunblock (sigmask (SIGALRM));
10529 TOTALLY_UNBLOCK_INPUT;
10531 clear_waiting_for_input ();
10532 error ("%s", error_message);
10535 /* This is the usual handler for X protocol errors.
10536 It kills all frames on the display that we got the error for.
10537 If that was the only one, it prints an error message and kills Emacs. */
10539 static void
10540 x_error_quitter (display, error)
10541 Display *display;
10542 XErrorEvent *error;
10544 char buf[256], buf1[356];
10546 /* Note that there is no real way portable across R3/R4 to get the
10547 original error handler. */
10549 XGetErrorText (display, error->error_code, buf, sizeof (buf));
10550 sprintf (buf1, "X protocol error: %s on protocol request %d",
10551 buf, error->request_code);
10552 x_connection_closed (display, buf1);
10555 /* This is the first-level handler for X protocol errors.
10556 It calls x_error_quitter or x_error_catcher. */
10558 static int
10559 x_error_handler (display, error)
10560 Display *display;
10561 XErrorEvent *error;
10563 if (! NILP (x_error_message_string))
10564 x_error_catcher (display, error);
10565 else
10566 x_error_quitter (display, error);
10567 return 0;
10570 /* This is the handler for X IO errors, always.
10571 It kills all frames on the display that we lost touch with.
10572 If that was the only one, it prints an error message and kills Emacs. */
10574 static int
10575 x_io_error_quitter (display)
10576 Display *display;
10578 char buf[256];
10580 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10581 x_connection_closed (display, buf);
10582 return 0;
10585 /* Changing the font of the frame. */
10587 /* Give frame F the font named FONTNAME as its default font, and
10588 return the full name of that font. FONTNAME may be a wildcard
10589 pattern; in that case, we choose some font that fits the pattern.
10590 The return value shows which font we chose. */
10592 Lisp_Object
10593 x_new_font (f, fontname)
10594 struct frame *f;
10595 register char *fontname;
10597 struct font_info *fontp
10598 = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
10600 if (!fontp)
10601 return Qnil;
10603 f->output_data.x->font = (XFontStruct *) (fontp->font);
10604 f->output_data.x->font_baseline
10605 = (f->output_data.x->font->ascent + fontp->baseline_offset);
10606 f->output_data.x->fontset = -1;
10608 /* Compute the scroll bar width in character columns. */
10609 if (f->scroll_bar_pixel_width > 0)
10611 int wid = FONT_WIDTH (f->output_data.x->font);
10612 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10614 else
10616 int wid = FONT_WIDTH (f->output_data.x->font);
10617 f->scroll_bar_cols = (14 + wid - 1) / wid;
10620 /* Now make the frame display the given font. */
10621 if (FRAME_X_WINDOW (f) != 0)
10623 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10624 f->output_data.x->font->fid);
10625 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10626 f->output_data.x->font->fid);
10627 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10628 f->output_data.x->font->fid);
10630 frame_update_line_height (f);
10631 x_set_window_size (f, 0, f->width, f->height);
10633 else
10634 /* If we are setting a new frame's font for the first time,
10635 there are no faces yet, so this font's height is the line height. */
10636 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
10638 return build_string (fontp->full_name);
10641 /* Give frame F the fontset named FONTSETNAME as its default font, and
10642 return the full name of that fontset. FONTSETNAME may be a wildcard
10643 pattern; in that case, we choose some fontset that fits the pattern.
10644 The return value shows which fontset we chose. */
10646 Lisp_Object
10647 x_new_fontset (f, fontsetname)
10648 struct frame *f;
10649 char *fontsetname;
10651 int fontset = fs_query_fontset (f, fontsetname);
10652 struct fontset_info *fontsetp;
10653 Lisp_Object result;
10655 if (fontset < 0)
10656 return Qnil;
10658 if (f->output_data.x->fontset == fontset)
10659 /* This fontset is already set in frame F. There's nothing more
10660 to do. */
10661 return build_string (fontsetname);
10663 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
10665 if (!fontsetp->fontname[CHARSET_ASCII])
10666 /* This fontset doesn't contain ASCII font. */
10667 return Qnil;
10669 result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
10671 if (!STRINGP (result))
10672 /* Can't load ASCII font. */
10673 return Qnil;
10675 /* Since x_new_font doesn't update any fontset information, do it now. */
10676 f->output_data.x->fontset = fontset;
10677 FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
10678 CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
10680 return build_string (fontsetname);
10683 /* Calculate the absolute position in frame F
10684 from its current recorded position values and gravity. */
10686 void
10687 x_calc_absolute_position (f)
10688 struct frame *f;
10690 Window child;
10691 int win_x = 0, win_y = 0;
10692 int flags = f->output_data.x->size_hint_flags;
10693 int this_window;
10695 /* We have nothing to do if the current position
10696 is already for the top-left corner. */
10697 if (! ((flags & XNegative) || (flags & YNegative)))
10698 return;
10700 #ifdef USE_X_TOOLKIT
10701 this_window = XtWindow (f->output_data.x->widget);
10702 #else
10703 this_window = FRAME_X_WINDOW (f);
10704 #endif
10706 /* Find the position of the outside upper-left corner of
10707 the inner window, with respect to the outer window.
10708 But do this only if we will need the results. */
10709 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10711 int count;
10713 BLOCK_INPUT;
10714 count = x_catch_errors (FRAME_X_DISPLAY (f));
10715 while (1)
10717 x_clear_errors (FRAME_X_DISPLAY (f));
10718 XTranslateCoordinates (FRAME_X_DISPLAY (f),
10720 /* From-window, to-window. */
10721 this_window,
10722 f->output_data.x->parent_desc,
10724 /* From-position, to-position. */
10725 0, 0, &win_x, &win_y,
10727 /* Child of win. */
10728 &child);
10729 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
10731 Window newroot, newparent = 0xdeadbeef;
10732 Window *newchildren;
10733 int nchildren;
10735 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
10736 &newparent, &newchildren, &nchildren))
10737 break;
10739 XFree ((char *) newchildren);
10741 f->output_data.x->parent_desc = newparent;
10743 else
10744 break;
10747 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
10748 UNBLOCK_INPUT;
10751 /* Treat negative positions as relative to the leftmost bottommost
10752 position that fits on the screen. */
10753 if (flags & XNegative)
10754 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
10755 - 2 * f->output_data.x->border_width - win_x
10756 - PIXEL_WIDTH (f)
10757 + f->output_data.x->left_pos);
10759 if (flags & YNegative)
10761 int menubar_height = 0;
10763 #ifdef USE_X_TOOLKIT
10764 if (f->output_data.x->menubar_widget)
10765 menubar_height
10766 = (f->output_data.x->menubar_widget->core.height
10767 + f->output_data.x->menubar_widget->core.border_width);
10768 #endif
10770 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
10771 - 2 * f->output_data.x->border_width
10772 - win_y
10773 - PIXEL_HEIGHT (f)
10774 - menubar_height
10775 + f->output_data.x->top_pos);
10778 /* The left_pos and top_pos
10779 are now relative to the top and left screen edges,
10780 so the flags should correspond. */
10781 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
10784 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10785 to really change the position, and 0 when calling from
10786 x_make_frame_visible (in that case, XOFF and YOFF are the current
10787 position values). It is -1 when calling from x_set_frame_parameters,
10788 which means, do adjust for borders but don't change the gravity. */
10790 void
10791 x_set_offset (f, xoff, yoff, change_gravity)
10792 struct frame *f;
10793 register int xoff, yoff;
10794 int change_gravity;
10796 int modified_top, modified_left;
10798 if (change_gravity > 0)
10800 f->output_data.x->top_pos = yoff;
10801 f->output_data.x->left_pos = xoff;
10802 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
10803 if (xoff < 0)
10804 f->output_data.x->size_hint_flags |= XNegative;
10805 if (yoff < 0)
10806 f->output_data.x->size_hint_flags |= YNegative;
10807 f->output_data.x->win_gravity = NorthWestGravity;
10809 x_calc_absolute_position (f);
10811 BLOCK_INPUT;
10812 x_wm_set_size_hint (f, (long) 0, 0);
10814 modified_left = f->output_data.x->left_pos;
10815 modified_top = f->output_data.x->top_pos;
10816 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
10817 this seems to be unnecessary and incorrect. rms, 4/17/97. */
10818 /* It is a mystery why we need to add the border_width here
10819 when the frame is already visible, but experiment says we do. */
10820 if (change_gravity != 0)
10822 modified_left += f->output_data.x->border_width;
10823 modified_top += f->output_data.x->border_width;
10825 #endif
10827 #ifdef USE_X_TOOLKIT
10828 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10829 modified_left, modified_top);
10830 #else /* not USE_X_TOOLKIT */
10831 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10832 modified_left, modified_top);
10833 #endif /* not USE_X_TOOLKIT */
10834 UNBLOCK_INPUT;
10837 /* Call this to change the size of frame F's x-window.
10838 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10839 for this size change and subsequent size changes.
10840 Otherwise we leave the window gravity unchanged. */
10842 void
10843 x_set_window_size (f, change_gravity, cols, rows)
10844 struct frame *f;
10845 int change_gravity;
10846 int cols, rows;
10848 #ifndef USE_X_TOOLKIT
10849 int pixelwidth, pixelheight;
10850 #endif
10852 BLOCK_INPUT;
10854 #ifdef USE_X_TOOLKIT
10856 /* The x and y position of the widget is clobbered by the
10857 call to XtSetValues within EmacsFrameSetCharSize.
10858 This is a real kludge, but I don't understand Xt so I can't
10859 figure out a correct fix. Can anyone else tell me? -- rms. */
10860 int xpos = f->output_data.x->widget->core.x;
10861 int ypos = f->output_data.x->widget->core.y;
10862 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
10863 f->output_data.x->widget->core.x = xpos;
10864 f->output_data.x->widget->core.y = ypos;
10867 #else /* not USE_X_TOOLKIT */
10869 check_frame_size (f, &rows, &cols);
10870 f->output_data.x->vertical_scroll_bar_extra
10871 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10873 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
10874 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
10875 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
10876 f->output_data.x->flags_areas_extra
10877 = FRAME_FLAGS_AREA_WIDTH (f);
10878 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10879 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
10881 f->output_data.x->win_gravity = NorthWestGravity;
10882 x_wm_set_size_hint (f, (long) 0, 0);
10884 XSync (FRAME_X_DISPLAY (f), False);
10885 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10886 pixelwidth, pixelheight);
10888 /* Now, strictly speaking, we can't be sure that this is accurate,
10889 but the window manager will get around to dealing with the size
10890 change request eventually, and we'll hear how it went when the
10891 ConfigureNotify event gets here.
10893 We could just not bother storing any of this information here,
10894 and let the ConfigureNotify event set everything up, but that
10895 might be kind of confusing to the Lisp code, since size changes
10896 wouldn't be reported in the frame parameters until some random
10897 point in the future when the ConfigureNotify event arrives.
10899 We pass 1 for DELAY since we can't run Lisp code inside of
10900 a BLOCK_INPUT. */
10901 change_frame_size (f, rows, cols, 0, 1, 0);
10902 PIXEL_WIDTH (f) = pixelwidth;
10903 PIXEL_HEIGHT (f) = pixelheight;
10905 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10906 receive in the ConfigureNotify event; if we get what we asked
10907 for, then the event won't cause the screen to become garbaged, so
10908 we have to make sure to do it here. */
10909 SET_FRAME_GARBAGED (f);
10911 XFlush (FRAME_X_DISPLAY (f));
10913 #endif /* not USE_X_TOOLKIT */
10915 /* If cursor was outside the new size, mark it as off. */
10916 mark_window_cursors_off (XWINDOW (f->root_window));
10918 /* Clear out any recollection of where the mouse highlighting was,
10919 since it might be in a place that's outside the new frame size.
10920 Actually checking whether it is outside is a pain in the neck,
10921 so don't try--just let the highlighting be done afresh with new size. */
10922 cancel_mouse_face (f);
10924 UNBLOCK_INPUT;
10927 /* Mouse warping. */
10929 void
10930 x_set_mouse_position (f, x, y)
10931 struct frame *f;
10932 int x, y;
10934 int pix_x, pix_y;
10936 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
10937 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
10939 if (pix_x < 0) pix_x = 0;
10940 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10942 if (pix_y < 0) pix_y = 0;
10943 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
10945 BLOCK_INPUT;
10947 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10948 0, 0, 0, 0, pix_x, pix_y);
10949 UNBLOCK_INPUT;
10952 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10954 void
10955 x_set_mouse_pixel_position (f, pix_x, pix_y)
10956 struct frame *f;
10957 int pix_x, pix_y;
10959 BLOCK_INPUT;
10961 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10962 0, 0, 0, 0, pix_x, pix_y);
10963 UNBLOCK_INPUT;
10966 /* focus shifting, raising and lowering. */
10968 void
10969 x_focus_on_frame (f)
10970 struct frame *f;
10972 #if 0 /* This proves to be unpleasant. */
10973 x_raise_frame (f);
10974 #endif
10975 #if 0
10976 /* I don't think that the ICCCM allows programs to do things like this
10977 without the interaction of the window manager. Whatever you end up
10978 doing with this code, do it to x_unfocus_frame too. */
10979 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10980 RevertToPointerRoot, CurrentTime);
10981 #endif /* ! 0 */
10984 void
10985 x_unfocus_frame (f)
10986 struct frame *f;
10988 #if 0
10989 /* Look at the remarks in x_focus_on_frame. */
10990 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
10991 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
10992 RevertToPointerRoot, CurrentTime);
10993 #endif /* ! 0 */
10996 /* Raise frame F. */
10998 void
10999 x_raise_frame (f)
11000 struct frame *f;
11002 if (f->async_visible)
11004 BLOCK_INPUT;
11005 #ifdef USE_X_TOOLKIT
11006 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11007 #else /* not USE_X_TOOLKIT */
11008 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11009 #endif /* not USE_X_TOOLKIT */
11010 XFlush (FRAME_X_DISPLAY (f));
11011 UNBLOCK_INPUT;
11015 /* Lower frame F. */
11017 void
11018 x_lower_frame (f)
11019 struct frame *f;
11021 if (f->async_visible)
11023 BLOCK_INPUT;
11024 #ifdef USE_X_TOOLKIT
11025 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11026 #else /* not USE_X_TOOLKIT */
11027 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11028 #endif /* not USE_X_TOOLKIT */
11029 XFlush (FRAME_X_DISPLAY (f));
11030 UNBLOCK_INPUT;
11034 static void
11035 XTframe_raise_lower (f, raise_flag)
11036 FRAME_PTR f;
11037 int raise_flag;
11039 if (raise_flag)
11040 x_raise_frame (f);
11041 else
11042 x_lower_frame (f);
11045 /* Change of visibility. */
11047 /* This tries to wait until the frame is really visible.
11048 However, if the window manager asks the user where to position
11049 the frame, this will return before the user finishes doing that.
11050 The frame will not actually be visible at that time,
11051 but it will become visible later when the window manager
11052 finishes with it. */
11054 void
11055 x_make_frame_visible (f)
11056 struct frame *f;
11058 Lisp_Object type;
11059 int original_top, original_left;
11061 BLOCK_INPUT;
11063 type = x_icon_type (f);
11064 if (!NILP (type))
11065 x_bitmap_icon (f, type);
11067 if (! FRAME_VISIBLE_P (f))
11069 /* We test FRAME_GARBAGED_P here to make sure we don't
11070 call x_set_offset a second time
11071 if we get to x_make_frame_visible a second time
11072 before the window gets really visible. */
11073 if (! FRAME_ICONIFIED_P (f)
11074 && ! f->output_data.x->asked_for_visible)
11075 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11077 f->output_data.x->asked_for_visible = 1;
11079 if (! EQ (Vx_no_window_manager, Qt))
11080 x_wm_set_window_state (f, NormalState);
11081 #ifdef USE_X_TOOLKIT
11082 /* This was XtPopup, but that did nothing for an iconified frame. */
11083 XtMapWidget (f->output_data.x->widget);
11084 #else /* not USE_X_TOOLKIT */
11085 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11086 #endif /* not USE_X_TOOLKIT */
11087 #if 0 /* This seems to bring back scroll bars in the wrong places
11088 if the window configuration has changed. They seem
11089 to come back ok without this. */
11090 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11091 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11092 #endif
11095 XFlush (FRAME_X_DISPLAY (f));
11097 /* Synchronize to ensure Emacs knows the frame is visible
11098 before we do anything else. We do this loop with input not blocked
11099 so that incoming events are handled. */
11101 Lisp_Object frame;
11102 int count = input_signal_count;
11103 /* This must be before UNBLOCK_INPUT
11104 since events that arrive in response to the actions above
11105 will set it when they are handled. */
11106 int previously_visible = f->output_data.x->has_been_visible;
11108 original_left = f->output_data.x->left_pos;
11109 original_top = f->output_data.x->top_pos;
11111 /* This must come after we set COUNT. */
11112 UNBLOCK_INPUT;
11114 /* We unblock here so that arriving X events are processed. */
11116 /* Now move the window back to where it was "supposed to be".
11117 But don't do it if the gravity is negative.
11118 When the gravity is negative, this uses a position
11119 that is 3 pixels too low. Perhaps that's really the border width.
11121 Don't do this if the window has never been visible before,
11122 because the window manager may choose the position
11123 and we don't want to override it. */
11125 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11126 && f->output_data.x->win_gravity == NorthWestGravity
11127 && previously_visible)
11129 Drawable rootw;
11130 int x, y;
11131 unsigned int width, height, border, depth;
11133 BLOCK_INPUT;
11135 /* On some window managers (such as FVWM) moving an existing
11136 window, even to the same place, causes the window manager
11137 to introduce an offset. This can cause the window to move
11138 to an unexpected location. Check the geometry (a little
11139 slow here) and then verify that the window is in the right
11140 place. If the window is not in the right place, move it
11141 there, and take the potential window manager hit. */
11142 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11143 &rootw, &x, &y, &width, &height, &border, &depth);
11145 if (original_left != x || original_top != y)
11146 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11147 original_left, original_top);
11149 UNBLOCK_INPUT;
11152 XSETFRAME (frame, f);
11154 while (1)
11156 x_sync (f);
11157 /* Once we have handled input events,
11158 we should have received the MapNotify if one is coming.
11159 So if we have not got it yet, stop looping.
11160 Some window managers make their own decisions
11161 about visibility. */
11162 if (input_signal_count != count)
11163 break;
11164 /* Machines that do polling rather than SIGIO have been observed
11165 to go into a busy-wait here. So we'll fake an alarm signal
11166 to let the handler know that there's something to be read.
11167 We used to raise a real alarm, but it seems that the handler
11168 isn't always enabled here. This is probably a bug. */
11169 if (input_polling_used ())
11171 /* It could be confusing if a real alarm arrives while processing
11172 the fake one. Turn it off and let the handler reset it. */
11173 alarm (0);
11174 input_poll_signal (0);
11176 /* Once we have handled input events,
11177 we should have received the MapNotify if one is coming.
11178 So if we have not got it yet, stop looping.
11179 Some window managers make their own decisions
11180 about visibility. */
11181 if (input_signal_count != count)
11182 break;
11184 FRAME_SAMPLE_VISIBILITY (f);
11188 /* Change from mapped state to withdrawn state. */
11190 /* Make the frame visible (mapped and not iconified). */
11192 void
11193 x_make_frame_invisible (f)
11194 struct frame *f;
11196 Window window;
11198 #ifdef USE_X_TOOLKIT
11199 /* Use the frame's outermost window, not the one we normally draw on. */
11200 window = XtWindow (f->output_data.x->widget);
11201 #else /* not USE_X_TOOLKIT */
11202 window = FRAME_X_WINDOW (f);
11203 #endif /* not USE_X_TOOLKIT */
11205 /* Don't keep the highlight on an invisible frame. */
11206 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11207 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11209 #if 0/* This might add unreliability; I don't trust it -- rms. */
11210 if (! f->async_visible && ! f->async_iconified)
11211 return;
11212 #endif
11214 BLOCK_INPUT;
11216 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11217 that the current position of the window is user-specified, rather than
11218 program-specified, so that when the window is mapped again, it will be
11219 placed at the same location, without forcing the user to position it
11220 by hand again (they have already done that once for this window.) */
11221 x_wm_set_size_hint (f, (long) 0, 1);
11223 #ifdef HAVE_X11R4
11225 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11226 DefaultScreen (FRAME_X_DISPLAY (f))))
11228 UNBLOCK_INPUT_RESIGNAL;
11229 error ("Can't notify window manager of window withdrawal");
11231 #else /* ! defined (HAVE_X11R4) */
11233 /* Tell the window manager what we're going to do. */
11234 if (! EQ (Vx_no_window_manager, Qt))
11236 XEvent unmap;
11238 unmap.xunmap.type = UnmapNotify;
11239 unmap.xunmap.window = window;
11240 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
11241 unmap.xunmap.from_configure = False;
11242 if (! XSendEvent (FRAME_X_DISPLAY (f),
11243 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11244 False,
11245 SubstructureRedirectMaskSubstructureNotifyMask,
11246 &unmap))
11248 UNBLOCK_INPUT_RESIGNAL;
11249 error ("Can't notify window manager of withdrawal");
11253 /* Unmap the window ourselves. Cheeky! */
11254 XUnmapWindow (FRAME_X_DISPLAY (f), window);
11255 #endif /* ! defined (HAVE_X11R4) */
11257 /* We can't distinguish this from iconification
11258 just by the event that we get from the server.
11259 So we can't win using the usual strategy of letting
11260 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11261 and synchronize with the server to make sure we agree. */
11262 f->visible = 0;
11263 FRAME_ICONIFIED_P (f) = 0;
11264 f->async_visible = 0;
11265 f->async_iconified = 0;
11267 x_sync (f);
11269 UNBLOCK_INPUT;
11272 /* Change window state from mapped to iconified. */
11274 void
11275 x_iconify_frame (f)
11276 struct frame *f;
11278 int result;
11279 Lisp_Object type;
11281 /* Don't keep the highlight on an invisible frame. */
11282 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11283 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11285 if (f->async_iconified)
11286 return;
11288 BLOCK_INPUT;
11290 FRAME_SAMPLE_VISIBILITY (f);
11292 type = x_icon_type (f);
11293 if (!NILP (type))
11294 x_bitmap_icon (f, type);
11296 #ifdef USE_X_TOOLKIT
11298 if (! FRAME_VISIBLE_P (f))
11300 if (! EQ (Vx_no_window_manager, Qt))
11301 x_wm_set_window_state (f, IconicState);
11302 /* This was XtPopup, but that did nothing for an iconified frame. */
11303 XtMapWidget (f->output_data.x->widget);
11304 /* The server won't give us any event to indicate
11305 that an invisible frame was changed to an icon,
11306 so we have to record it here. */
11307 f->iconified = 1;
11308 f->visible = 1;
11309 f->async_iconified = 1;
11310 f->async_visible = 0;
11311 UNBLOCK_INPUT;
11312 return;
11315 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11316 XtWindow (f->output_data.x->widget),
11317 DefaultScreen (FRAME_X_DISPLAY (f)));
11318 UNBLOCK_INPUT;
11320 if (!result)
11321 error ("Can't notify window manager of iconification");
11323 f->async_iconified = 1;
11324 f->async_visible = 0;
11327 BLOCK_INPUT;
11328 XFlush (FRAME_X_DISPLAY (f));
11329 UNBLOCK_INPUT;
11330 #else /* not USE_X_TOOLKIT */
11332 /* Make sure the X server knows where the window should be positioned,
11333 in case the user deiconifies with the window manager. */
11334 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
11335 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11337 /* Since we don't know which revision of X we're running, we'll use both
11338 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11340 /* X11R4: send a ClientMessage to the window manager using the
11341 WM_CHANGE_STATE type. */
11343 XEvent message;
11345 message.xclient.window = FRAME_X_WINDOW (f);
11346 message.xclient.type = ClientMessage;
11347 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
11348 message.xclient.format = 32;
11349 message.xclient.data.l[0] = IconicState;
11351 if (! XSendEvent (FRAME_X_DISPLAY (f),
11352 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11353 False,
11354 SubstructureRedirectMask | SubstructureNotifyMask,
11355 &message))
11357 UNBLOCK_INPUT_RESIGNAL;
11358 error ("Can't notify window manager of iconification");
11362 /* X11R3: set the initial_state field of the window manager hints to
11363 IconicState. */
11364 x_wm_set_window_state (f, IconicState);
11366 if (!FRAME_VISIBLE_P (f))
11368 /* If the frame was withdrawn, before, we must map it. */
11369 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11372 f->async_iconified = 1;
11373 f->async_visible = 0;
11375 XFlush (FRAME_X_DISPLAY (f));
11376 UNBLOCK_INPUT;
11377 #endif /* not USE_X_TOOLKIT */
11380 /* Destroy the X window of frame F. */
11382 void
11383 x_destroy_window (f)
11384 struct frame *f;
11386 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11388 BLOCK_INPUT;
11390 /* If a display connection is dead, don't try sending more
11391 commands to the X server. */
11392 if (dpyinfo->display != 0)
11394 if (f->output_data.x->icon_desc != 0)
11395 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
11396 #ifdef HAVE_X_I18N
11397 if (FRAME_XIM (f))
11399 XDestroyIC (FRAME_XIC (f));
11400 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11401 /* This line causes crashes on Solaris with Openwin,
11402 due to an apparent bug in XCloseIM.
11403 X11R6 seems not to have the bug. */
11404 XCloseIM (FRAME_XIM (f));
11405 #endif
11407 #endif
11408 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
11409 #ifdef USE_X_TOOLKIT
11410 if (f->output_data.x->widget)
11411 XtDestroyWidget (f->output_data.x->widget);
11412 free_frame_menubar (f);
11413 #endif /* USE_X_TOOLKIT */
11415 free_frame_faces (f);
11416 XFlush (FRAME_X_DISPLAY (f));
11419 if (f->output_data.x->saved_menu_event)
11420 xfree (f->output_data.x->saved_menu_event);
11422 xfree (f->output_data.x);
11423 f->output_data.x = 0;
11424 if (f == dpyinfo->x_focus_frame)
11425 dpyinfo->x_focus_frame = 0;
11426 if (f == dpyinfo->x_focus_event_frame)
11427 dpyinfo->x_focus_event_frame = 0;
11428 if (f == dpyinfo->x_highlight_frame)
11429 dpyinfo->x_highlight_frame = 0;
11431 dpyinfo->reference_count--;
11433 if (f == dpyinfo->mouse_face_mouse_frame)
11435 dpyinfo->mouse_face_beg_row
11436 = dpyinfo->mouse_face_beg_col = -1;
11437 dpyinfo->mouse_face_end_row
11438 = dpyinfo->mouse_face_end_col = -1;
11439 dpyinfo->mouse_face_window = Qnil;
11440 dpyinfo->mouse_face_deferred_gc = 0;
11441 dpyinfo->mouse_face_mouse_frame = 0;
11444 UNBLOCK_INPUT;
11447 /* Setting window manager hints. */
11449 /* Set the normal size hints for the window manager, for frame F.
11450 FLAGS is the flags word to use--or 0 meaning preserve the flags
11451 that the window now has.
11452 If USER_POSITION is nonzero, we set the USPosition
11453 flag (this is useful when FLAGS is 0). */
11455 void
11456 x_wm_set_size_hint (f, flags, user_position)
11457 struct frame *f;
11458 long flags;
11459 int user_position;
11461 XSizeHints size_hints;
11463 #ifdef USE_X_TOOLKIT
11464 Arg al[2];
11465 int ac = 0;
11466 Dimension widget_width, widget_height;
11467 Window window = XtWindow (f->output_data.x->widget);
11468 #else /* not USE_X_TOOLKIT */
11469 Window window = FRAME_X_WINDOW (f);
11470 #endif /* not USE_X_TOOLKIT */
11472 /* Setting PMaxSize caused various problems. */
11473 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
11475 size_hints.x = f->output_data.x->left_pos;
11476 size_hints.y = f->output_data.x->top_pos;
11478 #ifdef USE_X_TOOLKIT
11479 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11480 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
11481 XtGetValues (f->output_data.x->widget, al, ac);
11482 size_hints.height = widget_height;
11483 size_hints.width = widget_width;
11484 #else /* not USE_X_TOOLKIT */
11485 size_hints.height = PIXEL_HEIGHT (f);
11486 size_hints.width = PIXEL_WIDTH (f);
11487 #endif /* not USE_X_TOOLKIT */
11489 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11490 size_hints.height_inc = f->output_data.x->line_height;
11491 size_hints.max_width
11492 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11493 size_hints.max_height
11494 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
11496 /* Calculate the base and minimum sizes.
11498 (When we use the X toolkit, we don't do it here.
11499 Instead we copy the values that the widgets are using, below.) */
11500 #ifndef USE_X_TOOLKIT
11502 int base_width, base_height;
11503 int min_rows = 0, min_cols = 0;
11505 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11506 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
11508 check_frame_size (f, &min_rows, &min_cols);
11510 /* The window manager uses the base width hints to calculate the
11511 current number of rows and columns in the frame while
11512 resizing; min_width and min_height aren't useful for this
11513 purpose, since they might not give the dimensions for a
11514 zero-row, zero-column frame.
11516 We use the base_width and base_height members if we have
11517 them; otherwise, we set the min_width and min_height members
11518 to the size for a zero x zero frame. */
11520 #ifdef HAVE_X11R4
11521 size_hints.flags |= PBaseSize;
11522 size_hints.base_width = base_width;
11523 size_hints.base_height = base_height;
11524 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
11525 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
11526 #else
11527 size_hints.min_width = base_width;
11528 size_hints.min_height = base_height;
11529 #endif
11532 /* If we don't need the old flags, we don't need the old hint at all. */
11533 if (flags)
11535 size_hints.flags |= flags;
11536 goto no_read;
11538 #endif /* not USE_X_TOOLKIT */
11541 XSizeHints hints; /* Sometimes I hate X Windows... */
11542 long supplied_return;
11543 int value;
11545 #ifdef HAVE_X11R4
11546 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
11547 &supplied_return);
11548 #else
11549 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
11550 #endif
11552 #ifdef USE_X_TOOLKIT
11553 size_hints.base_height = hints.base_height;
11554 size_hints.base_width = hints.base_width;
11555 size_hints.min_height = hints.min_height;
11556 size_hints.min_width = hints.min_width;
11557 #endif
11559 if (flags)
11560 size_hints.flags |= flags;
11561 else
11563 if (value == 0)
11564 hints.flags = 0;
11565 if (hints.flags & PSize)
11566 size_hints.flags |= PSize;
11567 if (hints.flags & PPosition)
11568 size_hints.flags |= PPosition;
11569 if (hints.flags & USPosition)
11570 size_hints.flags |= USPosition;
11571 if (hints.flags & USSize)
11572 size_hints.flags |= USSize;
11576 #ifndef USE_X_TOOLKIT
11577 no_read:
11578 #endif
11580 #ifdef PWinGravity
11581 size_hints.win_gravity = f->output_data.x->win_gravity;
11582 size_hints.flags |= PWinGravity;
11584 if (user_position)
11586 size_hints.flags &= ~ PPosition;
11587 size_hints.flags |= USPosition;
11589 #endif /* PWinGravity */
11591 #ifdef HAVE_X11R4
11592 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
11593 #else
11594 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
11595 #endif
11598 /* Used for IconicState or NormalState */
11600 void
11601 x_wm_set_window_state (f, state)
11602 struct frame *f;
11603 int state;
11605 #ifdef USE_X_TOOLKIT
11606 Arg al[1];
11608 XtSetArg (al[0], XtNinitialState, state);
11609 XtSetValues (f->output_data.x->widget, al, 1);
11610 #else /* not USE_X_TOOLKIT */
11611 Window window = FRAME_X_WINDOW (f);
11613 f->output_data.x->wm_hints.flags |= StateHint;
11614 f->output_data.x->wm_hints.initial_state = state;
11616 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11617 #endif /* not USE_X_TOOLKIT */
11620 void
11621 x_wm_set_icon_pixmap (f, pixmap_id)
11622 struct frame *f;
11623 int pixmap_id;
11625 Pixmap icon_pixmap;
11627 #ifndef USE_X_TOOLKIT
11628 Window window = FRAME_X_WINDOW (f);
11629 #endif
11631 if (pixmap_id > 0)
11633 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
11634 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
11636 else
11638 /* It seems there is no way to turn off use of an icon pixmap.
11639 The following line does it, only if no icon has yet been created,
11640 for some window managers. But with mwm it crashes.
11641 Some people say it should clear the IconPixmapHint bit in this case,
11642 but that doesn't work, and the X consortium said it isn't the
11643 right thing at all. Since there is no way to win,
11644 best to explicitly give up. */
11645 #if 0
11646 f->output_data.x->wm_hints.icon_pixmap = None;
11647 #else
11648 return;
11649 #endif
11652 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11655 Arg al[1];
11656 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
11657 XtSetValues (f->output_data.x->widget, al, 1);
11660 #else /* not USE_X_TOOLKIT */
11662 f->output_data.x->wm_hints.flags |= IconPixmapHint;
11663 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11665 #endif /* not USE_X_TOOLKIT */
11668 void
11669 x_wm_set_icon_position (f, icon_x, icon_y)
11670 struct frame *f;
11671 int icon_x, icon_y;
11673 #ifdef USE_X_TOOLKIT
11674 Window window = XtWindow (f->output_data.x->widget);
11675 #else
11676 Window window = FRAME_X_WINDOW (f);
11677 #endif
11679 f->output_data.x->wm_hints.flags |= IconPositionHint;
11680 f->output_data.x->wm_hints.icon_x = icon_x;
11681 f->output_data.x->wm_hints.icon_y = icon_y;
11683 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11687 /***********************************************************************
11688 Fonts
11689 ***********************************************************************/
11691 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11693 struct font_info *
11694 x_get_font_info (f, font_idx)
11695 FRAME_PTR f;
11696 int font_idx;
11698 return (FRAME_X_FONT_TABLE (f) + font_idx);
11702 /* Return a list of names of available fonts matching PATTERN on frame
11703 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11704 to be listed. Frame F NULL means we have not yet created any
11705 frame on X, and consult the first display in x_display_list.
11706 MAXNAMES sets a limit on how many fonts to match. */
11708 Lisp_Object
11709 x_list_fonts (f, pattern, size, maxnames)
11710 FRAME_PTR f;
11711 Lisp_Object pattern;
11712 int size;
11713 int maxnames;
11715 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
11716 Lisp_Object tem, second_best;
11717 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
11718 int try_XLoadQueryFont = 0;
11719 int count;
11721 patterns = Fassoc (pattern, Valternate_fontname_alist);
11722 if (NILP (patterns))
11723 patterns = Fcons (pattern, Qnil);
11725 if (maxnames == 1 && !size)
11726 /* We can return any single font matching PATTERN. */
11727 try_XLoadQueryFont = 1;
11729 for (; CONSP (patterns); patterns = XCDR (patterns))
11731 int num_fonts;
11732 char **names;
11734 pattern = XCAR (patterns);
11735 /* See if we cached the result for this particular query.
11736 The cache is an alist of the form:
11737 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11739 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
11740 key = Fcons (pattern, make_number (maxnames)),
11741 !NILP (list = Fassoc (key, tem))))
11743 list = Fcdr_safe (list);
11744 /* We have a cashed list. Don't have to get the list again. */
11745 goto label_cached;
11748 /* At first, put PATTERN in the cache. */
11750 BLOCK_INPUT;
11751 count = x_catch_errors (dpy);
11753 if (try_XLoadQueryFont)
11755 XFontStruct *font;
11756 unsigned long value;
11758 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
11759 if (x_had_errors_p (dpy))
11761 /* This error is perhaps due to insufficient memory on X
11762 server. Let's just ignore it. */
11763 font = NULL;
11764 x_clear_errors (dpy);
11767 if (font
11768 && XGetFontProperty (font, XA_FONT, &value))
11770 char *name = (char *) XGetAtomName (dpy, (Atom) value);
11771 int len = strlen (name);
11772 char *tmp;
11774 /* If DXPC (a Differential X Protocol Compressor)
11775 Ver.3.7 is running, XGetAtomName will return null
11776 string. We must avoid such a name. */
11777 if (len == 0)
11778 try_XLoadQueryFont = 0;
11779 else
11781 num_fonts = 1;
11782 names = (char **) alloca (sizeof (char *));
11783 /* Some systems only allow alloca assigned to a
11784 simple var. */
11785 tmp = (char *) alloca (len + 1); names[0] = tmp;
11786 bcopy (name, names[0], len + 1);
11787 XFree (name);
11790 else
11791 try_XLoadQueryFont = 0;
11793 if (font)
11794 XFreeFont (dpy, font);
11797 if (!try_XLoadQueryFont)
11799 /* We try at least 10 fonts because XListFonts will return
11800 auto-scaled fonts at the head. */
11801 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
11802 &num_fonts);
11803 if (x_had_errors_p (dpy))
11805 /* This error is perhaps due to insufficient memory on X
11806 server. Let's just ignore it. */
11807 names = NULL;
11808 x_clear_errors (dpy);
11812 x_uncatch_errors (dpy, count);
11813 UNBLOCK_INPUT;
11815 if (names)
11817 int i;
11819 /* Make a list of all the fonts we got back.
11820 Store that in the font cache for the display. */
11821 for (i = 0; i < num_fonts; i++)
11823 int width = 0;
11824 char *p = names[i];
11825 int average_width = -1, dashes = 0;
11827 /* Count the number of dashes in NAMES[I]. If there are
11828 14 dashes, and the field value following 12th dash
11829 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
11830 is usually too ugly to be used for editing. Let's
11831 ignore it. */
11832 while (*p)
11833 if (*p++ == '-')
11835 dashes++;
11836 if (dashes == 7) /* PIXEL_SIZE field */
11837 width = atoi (p);
11838 else if (dashes == 12) /* AVERAGE_WIDTH field */
11839 average_width = atoi (p);
11841 if (dashes < 14 || average_width != 0)
11843 tem = build_string (names[i]);
11844 if (NILP (Fassoc (tem, list)))
11846 if (STRINGP (Vx_pixel_size_width_font_regexp)
11847 && ((fast_c_string_match_ignore_case
11848 (Vx_pixel_size_width_font_regexp, names[i]))
11849 >= 0))
11850 /* We can set the value of PIXEL_SIZE to the
11851 width of this font. */
11852 list = Fcons (Fcons (tem, make_number (width)), list);
11853 else
11854 /* For the moment, width is not known. */
11855 list = Fcons (Fcons (tem, Qnil), list);
11859 if (!try_XLoadQueryFont)
11860 XFreeFontNames (names);
11863 /* Now store the result in the cache. */
11864 if (f != NULL)
11865 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
11866 = Fcons (Fcons (key, list),
11867 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
11869 label_cached:
11870 if (NILP (list)) continue; /* Try the remaining alternatives. */
11872 newlist = second_best = Qnil;
11873 /* Make a list of the fonts that have the right width. */
11874 for (; CONSP (list); list = XCDR (list))
11876 int found_size;
11878 tem = XCAR (list);
11880 if (!CONSP (tem) || NILP (XCAR (tem)))
11881 continue;
11882 if (!size)
11884 newlist = Fcons (XCAR (tem), newlist);
11885 continue;
11888 if (!INTEGERP (XCDR (tem)))
11890 /* Since we have not yet known the size of this font, we
11891 must try slow function call XLoadQueryFont. */
11892 XFontStruct *thisinfo;
11894 BLOCK_INPUT;
11895 count = x_catch_errors (dpy);
11896 thisinfo = XLoadQueryFont (dpy,
11897 XSTRING (XCAR (tem))->data);
11898 if (x_had_errors_p (dpy))
11900 /* This error is perhaps due to insufficient memory on X
11901 server. Let's just ignore it. */
11902 thisinfo = NULL;
11903 x_clear_errors (dpy);
11905 x_uncatch_errors (dpy, count);
11906 UNBLOCK_INPUT;
11908 if (thisinfo)
11910 XCDR (tem)
11911 = (thisinfo->min_bounds.width == 0
11912 ? make_number (0)
11913 : make_number (thisinfo->max_bounds.width));
11914 XFreeFont (dpy, thisinfo);
11916 else
11917 /* For unknown reason, the previous call of XListFont had
11918 returned a font which can't be opened. Record the size
11919 as 0 not to try to open it again. */
11920 XCDR (tem) = make_number (0);
11923 found_size = XINT (XCDR (tem));
11924 if (found_size == size)
11925 newlist = Fcons (XCAR (tem), newlist);
11926 else if (found_size > 0)
11928 if (NILP (second_best))
11929 second_best = tem;
11930 else if (found_size < size)
11932 if (XINT (XCDR (second_best)) > size
11933 || XINT (XCDR (second_best)) < found_size)
11934 second_best = tem;
11936 else
11938 if (XINT (XCDR (second_best)) > size
11939 && XINT (XCDR (second_best)) > found_size)
11940 second_best = tem;
11944 if (!NILP (newlist))
11945 break;
11946 else if (!NILP (second_best))
11948 newlist = Fcons (XCAR (second_best), Qnil);
11949 break;
11953 return newlist;
11957 #if GLYPH_DEBUG
11959 /* Check that FONT is valid on frame F. It is if it can be found in F's
11960 font table. */
11962 static void
11963 x_check_font (f, font)
11964 struct frame *f;
11965 XFontStruct *font;
11967 int i;
11968 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11970 xassert (font != NULL);
11972 for (i = 0; i < dpyinfo->n_fonts; i++)
11973 if (dpyinfo->font_table[i].name
11974 && font == dpyinfo->font_table[i].font)
11975 break;
11977 xassert (i < dpyinfo->n_fonts);
11980 #endif /* GLYPH_DEBUG != 0 */
11982 /* Set *W to the minimum width, *H to the minimum font height of FONT.
11983 Note: There are (broken) X fonts out there with invalid XFontStruct
11984 min_bounds contents. For example, handa@etl.go.jp reports that
11985 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
11986 have font->min_bounds.width == 0. */
11988 static INLINE void
11989 x_font_min_bounds (font, w, h)
11990 XFontStruct *font;
11991 int *w, *h;
11993 *h = FONT_HEIGHT (font);
11994 *w = font->min_bounds.width;
11996 /* Try to handle the case where FONT->min_bounds has invalid
11997 contents. Since the only font known to have invalid min_bounds
11998 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
11999 if (*w <= 0)
12000 *w = font->max_bounds.width;
12004 /* Compute the smallest character width and smallest font height over
12005 all fonts available on frame F. Set the members smallest_char_width
12006 and smallest_font_height in F's x_display_info structure to
12007 the values computed. Value is non-zero if smallest_font_height or
12008 smallest_char_width become smaller than they were before. */
12010 static int
12011 x_compute_min_glyph_bounds (f)
12012 struct frame *f;
12014 int i;
12015 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12016 XFontStruct *font;
12017 int old_width = dpyinfo->smallest_char_width;
12018 int old_height = dpyinfo->smallest_font_height;
12020 dpyinfo->smallest_font_height = 100000;
12021 dpyinfo->smallest_char_width = 100000;
12023 for (i = 0; i < dpyinfo->n_fonts; ++i)
12024 if (dpyinfo->font_table[i].name)
12026 struct font_info *fontp = dpyinfo->font_table + i;
12027 int w, h;
12029 font = (XFontStruct *) fontp->font;
12030 xassert (font != (XFontStruct *) ~0);
12031 x_font_min_bounds (font, &w, &h);
12033 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12034 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12037 xassert (dpyinfo->smallest_char_width > 0
12038 && dpyinfo->smallest_font_height > 0);
12040 return (dpyinfo->n_fonts == 1
12041 || dpyinfo->smallest_char_width < old_width
12042 || dpyinfo->smallest_font_height < old_height);
12046 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12047 pointer to the structure font_info while allocating it dynamically.
12048 If SIZE is 0, load any size of font.
12049 If loading is failed, return NULL. */
12051 struct font_info *
12052 x_load_font (f, fontname, size)
12053 struct frame *f;
12054 register char *fontname;
12055 int size;
12057 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12058 Lisp_Object font_names;
12059 int count;
12061 /* Get a list of all the fonts that match this name. Once we
12062 have a list of matching fonts, we compare them against the fonts
12063 we already have by comparing names. */
12064 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12066 if (!NILP (font_names))
12068 Lisp_Object tail;
12069 int i;
12071 for (i = 0; i < dpyinfo->n_fonts; i++)
12072 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12073 if (dpyinfo->font_table[i].name
12074 && (!strcmp (dpyinfo->font_table[i].name,
12075 XSTRING (XCAR (tail))->data)
12076 || !strcmp (dpyinfo->font_table[i].full_name,
12077 XSTRING (XCAR (tail))->data)))
12078 return (dpyinfo->font_table + i);
12081 /* Load the font and add it to the table. */
12083 char *full_name;
12084 XFontStruct *font;
12085 struct font_info *fontp;
12086 unsigned long value;
12087 int i;
12089 /* If we have found fonts by x_list_font, load one of them. If
12090 not, we still try to load a font by the name given as FONTNAME
12091 because XListFonts (called in x_list_font) of some X server has
12092 a bug of not finding a font even if the font surely exists and
12093 is loadable by XLoadQueryFont. */
12094 if (size > 0 && !NILP (font_names))
12095 fontname = (char *) XSTRING (XCAR (font_names))->data;
12097 BLOCK_INPUT;
12098 count = x_catch_errors (FRAME_X_DISPLAY (f));
12099 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12100 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12102 /* This error is perhaps due to insufficient memory on X
12103 server. Let's just ignore it. */
12104 font = NULL;
12105 x_clear_errors (FRAME_X_DISPLAY (f));
12107 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12108 UNBLOCK_INPUT;
12109 if (!font)
12110 return NULL;
12112 /* Find a free slot in the font table. */
12113 for (i = 0; i < dpyinfo->n_fonts; ++i)
12114 if (dpyinfo->font_table[i].name == NULL)
12115 break;
12117 /* If no free slot found, maybe enlarge the font table. */
12118 if (i == dpyinfo->n_fonts
12119 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12121 int sz;
12122 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12123 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12124 dpyinfo->font_table
12125 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12128 fontp = dpyinfo->font_table + i;
12129 if (i == dpyinfo->n_fonts)
12130 ++dpyinfo->n_fonts;
12132 /* Now fill in the slots of *FONTP. */
12133 BLOCK_INPUT;
12134 fontp->font = font;
12135 fontp->font_idx = i;
12136 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12137 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12139 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12140 full_name = 0;
12141 if (XGetFontProperty (font, XA_FONT, &value))
12143 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12144 char *p = name;
12145 int dashes = 0;
12147 /* Count the number of dashes in the "full name".
12148 If it is too few, this isn't really the font's full name,
12149 so don't use it.
12150 In X11R4, the fonts did not come with their canonical names
12151 stored in them. */
12152 while (*p)
12154 if (*p == '-')
12155 dashes++;
12156 p++;
12159 if (dashes >= 13)
12161 full_name = (char *) xmalloc (p - name + 1);
12162 bcopy (name, full_name, p - name + 1);
12165 XFree (name);
12168 if (full_name != 0)
12169 fontp->full_name = full_name;
12170 else
12171 fontp->full_name = fontp->name;
12173 fontp->size = font->max_bounds.width;
12174 fontp->height = FONT_HEIGHT (font);
12176 /* For some font, ascent and descent in max_bounds field is
12177 larger than the above value. */
12178 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12179 if (max_height > fontp->height)
12180 fontp->height = max_height;
12183 if (NILP (font_names))
12185 /* We come here because of a bug of XListFonts mentioned at
12186 the head of this block. Let's store this information in
12187 the cache for x_list_fonts. */
12188 Lisp_Object lispy_name = build_string (fontname);
12189 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12191 XCDR (dpyinfo->name_list_element)
12192 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12193 Fcons (Fcons (lispy_full_name,
12194 make_number (fontp->size)),
12195 Qnil)),
12196 XCDR (dpyinfo->name_list_element));
12197 if (full_name)
12198 XCDR (dpyinfo->name_list_element)
12199 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12200 Fcons (Fcons (lispy_full_name,
12201 make_number (fontp->size)),
12202 Qnil)),
12203 XCDR (dpyinfo->name_list_element));
12206 /* The slot `encoding' specifies how to map a character
12207 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12208 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12209 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12210 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12211 2:0xA020..0xFF7F). For the moment, we don't know which charset
12212 uses this font. So, we set information in fontp->encoding[1]
12213 which is never used by any charset. If mapping can't be
12214 decided, set FONT_ENCODING_NOT_DECIDED. */
12215 fontp->encoding[1]
12216 = (font->max_byte1 == 0
12217 /* 1-byte font */
12218 ? (font->min_char_or_byte2 < 0x80
12219 ? (font->max_char_or_byte2 < 0x80
12220 ? 0 /* 0x20..0x7F */
12221 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
12222 : 1) /* 0xA0..0xFF */
12223 /* 2-byte font */
12224 : (font->min_byte1 < 0x80
12225 ? (font->max_byte1 < 0x80
12226 ? (font->min_char_or_byte2 < 0x80
12227 ? (font->max_char_or_byte2 < 0x80
12228 ? 0 /* 0x2020..0x7F7F */
12229 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
12230 : 3) /* 0x20A0..0x7FFF */
12231 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
12232 : (font->min_char_or_byte2 < 0x80
12233 ? (font->max_char_or_byte2 < 0x80
12234 ? 2 /* 0xA020..0xFF7F */
12235 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
12236 : 1))); /* 0xA0A0..0xFFFF */
12238 fontp->baseline_offset
12239 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12240 ? (long) value : 0);
12241 fontp->relative_compose
12242 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12243 ? (long) value : 0);
12244 fontp->default_ascent
12245 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12246 ? (long) value : 0);
12248 /* Set global flag fonts_changed_p to non-zero if the font loaded
12249 has a character with a smaller width than any other character
12250 before, or if the font loaded has a smalle>r height than any
12251 other font loaded before. If this happens, it will make a
12252 glyph matrix reallocation necessary. */
12253 fonts_changed_p = x_compute_min_glyph_bounds (f);
12254 UNBLOCK_INPUT;
12255 return fontp;
12260 /* Return a pointer to struct font_info of a font named FONTNAME for
12261 frame F. If no such font is loaded, return NULL. */
12263 struct font_info *
12264 x_query_font (f, fontname)
12265 struct frame *f;
12266 register char *fontname;
12268 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12269 int i;
12271 for (i = 0; i < dpyinfo->n_fonts; i++)
12272 if (dpyinfo->font_table[i].name
12273 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12274 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
12275 return (dpyinfo->font_table + i);
12276 return NULL;
12280 /* Find a CCL program for a font specified by FONTP, and set the member
12281 `encoder' of the structure. */
12283 void
12284 x_find_ccl_program (fontp)
12285 struct font_info *fontp;
12287 Lisp_Object list, elt;
12289 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
12291 elt = XCAR (list);
12292 if (CONSP (elt)
12293 && STRINGP (XCAR (elt))
12294 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
12295 >= 0))
12296 break;
12298 if (! NILP (list))
12300 struct ccl_program *ccl
12301 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
12303 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
12304 xfree (ccl);
12305 else
12306 fontp->font_encoder = ccl;
12312 /***********************************************************************
12313 Initialization
12314 ***********************************************************************/
12316 #ifdef USE_X_TOOLKIT
12317 static XrmOptionDescRec emacs_options[] = {
12318 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12319 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12321 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12322 XrmoptionSepArg, NULL},
12323 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12325 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12326 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12327 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12328 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12329 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12330 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12331 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12333 #endif /* USE_X_TOOLKIT */
12335 static int x_initialized;
12337 #ifdef MULTI_KBOARD
12338 /* Test whether two display-name strings agree up to the dot that separates
12339 the screen number from the server number. */
12340 static int
12341 same_x_server (name1, name2)
12342 char *name1, *name2;
12344 int seen_colon = 0;
12345 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12346 int system_name_length = strlen (system_name);
12347 int length_until_period = 0;
12349 while (system_name[length_until_period] != 0
12350 && system_name[length_until_period] != '.')
12351 length_until_period++;
12353 /* Treat `unix' like an empty host name. */
12354 if (! strncmp (name1, "unix:", 5))
12355 name1 += 4;
12356 if (! strncmp (name2, "unix:", 5))
12357 name2 += 4;
12358 /* Treat this host's name like an empty host name. */
12359 if (! strncmp (name1, system_name, system_name_length)
12360 && name1[system_name_length] == ':')
12361 name1 += system_name_length;
12362 if (! strncmp (name2, system_name, system_name_length)
12363 && name2[system_name_length] == ':')
12364 name2 += system_name_length;
12365 /* Treat this host's domainless name like an empty host name. */
12366 if (! strncmp (name1, system_name, length_until_period)
12367 && name1[length_until_period] == ':')
12368 name1 += length_until_period;
12369 if (! strncmp (name2, system_name, length_until_period)
12370 && name2[length_until_period] == ':')
12371 name2 += length_until_period;
12373 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12375 if (*name1 == ':')
12376 seen_colon++;
12377 if (seen_colon && *name1 == '.')
12378 return 1;
12380 return (seen_colon
12381 && (*name1 == '.' || *name1 == '\0')
12382 && (*name2 == '.' || *name2 == '\0'));
12384 #endif
12386 struct x_display_info *
12387 x_term_init (display_name, xrm_option, resource_name)
12388 Lisp_Object display_name;
12389 char *xrm_option;
12390 char *resource_name;
12392 int connection;
12393 Display *dpy;
12394 struct x_display_info *dpyinfo;
12395 XrmDatabase xrdb;
12397 BLOCK_INPUT;
12399 if (!x_initialized)
12401 x_initialize ();
12402 x_initialized = 1;
12405 #ifdef USE_X_TOOLKIT
12406 /* weiner@footloose.sps.mot.com reports that this causes
12407 errors with X11R5:
12408 X protocol error: BadAtom (invalid Atom parameter)
12409 on protocol request 18skiloaf.
12410 So let's not use it until R6. */
12411 #ifdef HAVE_X11XTR6
12412 XtSetLanguageProc (NULL, NULL, NULL);
12413 #endif
12416 int argc = 0;
12417 char *argv[3];
12419 argv[0] = "";
12420 argc = 1;
12421 if (xrm_option)
12423 argv[argc++] = "-xrm";
12424 argv[argc++] = xrm_option;
12426 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12427 resource_name, EMACS_CLASS,
12428 emacs_options, XtNumber (emacs_options),
12429 &argc, argv);
12431 #ifdef HAVE_X11XTR6
12432 /* I think this is to compensate for XtSetLanguageProc. */
12433 fixup_locale ();
12434 #endif
12437 #else /* not USE_X_TOOLKIT */
12438 #ifdef HAVE_X11R5
12439 XSetLocaleModifiers ("");
12440 #endif
12441 dpy = XOpenDisplay (XSTRING (display_name)->data);
12442 #endif /* not USE_X_TOOLKIT */
12444 /* Detect failure. */
12445 if (dpy == 0)
12447 UNBLOCK_INPUT;
12448 return 0;
12451 /* We have definitely succeeded. Record the new connection. */
12453 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12455 #ifdef MULTI_KBOARD
12457 struct x_display_info *share;
12458 Lisp_Object tail;
12460 for (share = x_display_list, tail = x_display_name_list; share;
12461 share = share->next, tail = XCDR (tail))
12462 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
12463 XSTRING (display_name)->data))
12464 break;
12465 if (share)
12466 dpyinfo->kboard = share->kboard;
12467 else
12469 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12470 init_kboard (dpyinfo->kboard);
12471 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12473 char *vendor = ServerVendor (dpy);
12474 dpyinfo->kboard->Vsystem_key_alist
12475 = call1 (Qvendor_specific_keysyms,
12476 build_string (vendor ? vendor : ""));
12479 dpyinfo->kboard->next_kboard = all_kboards;
12480 all_kboards = dpyinfo->kboard;
12481 /* Don't let the initial kboard remain current longer than necessary.
12482 That would cause problems if a file loaded on startup tries to
12483 prompt in the mini-buffer. */
12484 if (current_kboard == initial_kboard)
12485 current_kboard = dpyinfo->kboard;
12487 dpyinfo->kboard->reference_count++;
12489 #endif
12491 /* Put this display on the chain. */
12492 dpyinfo->next = x_display_list;
12493 x_display_list = dpyinfo;
12495 /* Put it on x_display_name_list as well, to keep them parallel. */
12496 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12497 x_display_name_list);
12498 dpyinfo->name_list_element = XCAR (x_display_name_list);
12500 dpyinfo->display = dpy;
12502 #if 0
12503 XSetAfterFunction (x_current_display, x_trace_wire);
12504 #endif /* ! 0 */
12506 dpyinfo->x_id_name
12507 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12508 + STRING_BYTES (XSTRING (Vsystem_name))
12509 + 2);
12510 sprintf (dpyinfo->x_id_name, "%s@%s",
12511 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12513 /* Figure out which modifier bits mean what. */
12514 x_find_modifier_meanings (dpyinfo);
12516 /* Get the scroll bar cursor. */
12517 dpyinfo->vertical_scroll_bar_cursor
12518 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12520 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12521 resource_name, EMACS_CLASS);
12522 #ifdef HAVE_XRMSETDATABASE
12523 XrmSetDatabase (dpyinfo->display, xrdb);
12524 #else
12525 dpyinfo->display->db = xrdb;
12526 #endif
12527 /* Put the rdb where we can find it in a way that works on
12528 all versions. */
12529 dpyinfo->xrdb = xrdb;
12531 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12532 DefaultScreen (dpyinfo->display));
12533 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
12534 &dpyinfo->n_planes);
12535 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
12536 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
12537 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12538 dpyinfo->grabbed = 0;
12539 dpyinfo->reference_count = 0;
12540 dpyinfo->icon_bitmap_id = -1;
12541 dpyinfo->font_table = NULL;
12542 dpyinfo->n_fonts = 0;
12543 dpyinfo->font_table_size = 0;
12544 dpyinfo->bitmaps = 0;
12545 dpyinfo->bitmaps_size = 0;
12546 dpyinfo->bitmaps_last = 0;
12547 dpyinfo->scratch_cursor_gc = 0;
12548 dpyinfo->mouse_face_mouse_frame = 0;
12549 dpyinfo->mouse_face_deferred_gc = 0;
12550 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12551 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12552 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12553 dpyinfo->mouse_face_window = Qnil;
12554 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
12555 dpyinfo->mouse_face_defer = 0;
12556 dpyinfo->x_focus_frame = 0;
12557 dpyinfo->x_focus_event_frame = 0;
12558 dpyinfo->x_highlight_frame = 0;
12559 dpyinfo->image_cache = make_image_cache ();
12562 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
12563 double pixels = DisplayHeight (dpyinfo->display, screen_number);
12564 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
12565 dpyinfo->resy = pixels * 25.4 / mm;
12566 pixels = DisplayWidth (dpyinfo->display, screen_number);
12567 mm = DisplayWidthMM (dpyinfo->display, screen_number);
12568 dpyinfo->resx = pixels * 25.4 / mm;
12571 dpyinfo->Xatom_wm_protocols
12572 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
12573 dpyinfo->Xatom_wm_take_focus
12574 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
12575 dpyinfo->Xatom_wm_save_yourself
12576 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
12577 dpyinfo->Xatom_wm_delete_window
12578 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
12579 dpyinfo->Xatom_wm_change_state
12580 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
12581 dpyinfo->Xatom_wm_configure_denied
12582 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
12583 dpyinfo->Xatom_wm_window_moved
12584 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
12585 dpyinfo->Xatom_editres
12586 = XInternAtom (dpyinfo->display, "Editres", False);
12587 dpyinfo->Xatom_CLIPBOARD
12588 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
12589 dpyinfo->Xatom_TIMESTAMP
12590 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
12591 dpyinfo->Xatom_TEXT
12592 = XInternAtom (dpyinfo->display, "TEXT", False);
12593 dpyinfo->Xatom_COMPOUND_TEXT
12594 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
12595 dpyinfo->Xatom_DELETE
12596 = XInternAtom (dpyinfo->display, "DELETE", False);
12597 dpyinfo->Xatom_MULTIPLE
12598 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
12599 dpyinfo->Xatom_INCR
12600 = XInternAtom (dpyinfo->display, "INCR", False);
12601 dpyinfo->Xatom_EMACS_TMP
12602 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
12603 dpyinfo->Xatom_TARGETS
12604 = XInternAtom (dpyinfo->display, "TARGETS", False);
12605 dpyinfo->Xatom_NULL
12606 = XInternAtom (dpyinfo->display, "NULL", False);
12607 dpyinfo->Xatom_ATOM_PAIR
12608 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
12609 /* For properties of font. */
12610 dpyinfo->Xatom_PIXEL_SIZE
12611 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
12612 dpyinfo->Xatom_MULE_BASELINE_OFFSET
12613 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
12614 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
12615 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
12616 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
12617 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
12619 /* Ghostscript support. */
12620 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
12621 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
12623 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
12624 False);
12626 dpyinfo->cut_buffers_initialized = 0;
12628 connection = ConnectionNumber (dpyinfo->display);
12629 dpyinfo->connection = connection;
12632 char null_bits[1];
12634 null_bits[0] = 0x00;
12636 dpyinfo->null_pixel
12637 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12638 null_bits, 1, 1, (long) 0, (long) 0,
12643 extern int gray_bitmap_width, gray_bitmap_height;
12644 extern unsigned char *gray_bitmap_bits;
12645 dpyinfo->gray
12646 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12647 gray_bitmap_bits,
12648 gray_bitmap_width, gray_bitmap_height,
12649 (unsigned long) 1, (unsigned long) 0, 1);
12652 #ifdef subprocesses
12653 /* This is only needed for distinguishing keyboard and process input. */
12654 if (connection != 0)
12655 add_keyboard_wait_descriptor (connection);
12656 #endif
12658 #ifndef F_SETOWN_BUG
12659 #ifdef F_SETOWN
12660 #ifdef F_SETOWN_SOCK_NEG
12661 /* stdin is a socket here */
12662 fcntl (connection, F_SETOWN, -getpid ());
12663 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12664 fcntl (connection, F_SETOWN, getpid ());
12665 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12666 #endif /* ! defined (F_SETOWN) */
12667 #endif /* F_SETOWN_BUG */
12669 #ifdef SIGIO
12670 if (interrupt_input)
12671 init_sigio (connection);
12672 #endif /* ! defined (SIGIO) */
12674 #ifdef USE_LUCID
12675 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12676 /* Make sure that we have a valid font for dialog boxes
12677 so that Xt does not crash. */
12679 Display *dpy = dpyinfo->display;
12680 XrmValue d, fr, to;
12681 Font font;
12682 int count;
12684 d.addr = (XPointer)&dpy;
12685 d.size = sizeof (Display *);
12686 fr.addr = XtDefaultFont;
12687 fr.size = sizeof (XtDefaultFont);
12688 to.size = sizeof (Font *);
12689 to.addr = (XPointer)&font;
12690 count = x_catch_errors (dpy);
12691 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
12692 abort ();
12693 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
12694 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
12695 x_uncatch_errors (dpy, count);
12697 #endif
12698 #endif
12700 UNBLOCK_INPUT;
12702 return dpyinfo;
12705 /* Get rid of display DPYINFO, assuming all frames are already gone,
12706 and without sending any more commands to the X server. */
12708 void
12709 x_delete_display (dpyinfo)
12710 struct x_display_info *dpyinfo;
12712 delete_keyboard_wait_descriptor (dpyinfo->connection);
12714 /* Discard this display from x_display_name_list and x_display_list.
12715 We can't use Fdelq because that can quit. */
12716 if (! NILP (x_display_name_list)
12717 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
12718 x_display_name_list = XCDR (x_display_name_list);
12719 else
12721 Lisp_Object tail;
12723 tail = x_display_name_list;
12724 while (CONSP (tail) && CONSP (XCDR (tail)))
12726 if (EQ (XCAR (XCDR (tail)),
12727 dpyinfo->name_list_element))
12729 XCDR (tail) = XCDR (XCDR (tail));
12730 break;
12732 tail = XCDR (tail);
12736 if (x_display_list == dpyinfo)
12737 x_display_list = dpyinfo->next;
12738 else
12740 struct x_display_info *tail;
12742 for (tail = x_display_list; tail; tail = tail->next)
12743 if (tail->next == dpyinfo)
12744 tail->next = tail->next->next;
12747 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12748 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12749 XrmDestroyDatabase (dpyinfo->xrdb);
12750 #endif
12751 #endif
12752 #ifdef MULTI_KBOARD
12753 if (--dpyinfo->kboard->reference_count == 0)
12754 delete_kboard (dpyinfo->kboard);
12755 #endif
12756 xfree (dpyinfo->font_table);
12757 xfree (dpyinfo->x_id_name);
12758 xfree (dpyinfo);
12761 /* Set up use of X before we make the first connection. */
12763 static struct redisplay_interface x_redisplay_interface =
12765 x_produce_glyphs,
12766 x_write_glyphs,
12767 x_insert_glyphs,
12768 x_clear_end_of_line,
12769 x_scroll_run,
12770 x_after_update_window_line,
12771 x_update_window_begin,
12772 x_update_window_end,
12773 XTcursor_to,
12774 x_flush,
12775 x_get_glyph_overhangs,
12776 x_fix_overlapping_area
12779 void
12780 x_initialize ()
12782 rif = &x_redisplay_interface;
12784 clear_frame_hook = x_clear_frame;
12785 ins_del_lines_hook = x_ins_del_lines;
12786 change_line_highlight_hook = x_change_line_highlight;
12787 delete_glyphs_hook = x_delete_glyphs;
12788 ring_bell_hook = XTring_bell;
12789 reset_terminal_modes_hook = XTreset_terminal_modes;
12790 set_terminal_modes_hook = XTset_terminal_modes;
12791 update_begin_hook = x_update_begin;
12792 update_end_hook = x_update_end;
12793 set_terminal_window_hook = XTset_terminal_window;
12794 read_socket_hook = XTread_socket;
12795 frame_up_to_date_hook = XTframe_up_to_date;
12796 reassert_line_highlight_hook = XTreassert_line_highlight;
12797 mouse_position_hook = XTmouse_position;
12798 frame_rehighlight_hook = XTframe_rehighlight;
12799 frame_raise_lower_hook = XTframe_raise_lower;
12800 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12801 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12802 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12803 judge_scroll_bars_hook = XTjudge_scroll_bars;
12804 estimate_mode_line_height_hook = x_estimate_mode_line_height;
12806 scroll_region_ok = 1; /* we'll scroll partial frames */
12807 char_ins_del_ok = 0; /* just as fast to write the line */
12808 line_ins_del_ok = 1; /* we'll just blt 'em */
12809 fast_clear_end_of_line = 1; /* X does this well */
12810 memory_below_frame = 0; /* we don't remember what scrolls
12811 off the bottom */
12812 baud_rate = 19200;
12814 x_noop_count = 0;
12815 last_tool_bar_item = -1;
12816 any_help_event_p = 0;
12818 /* Try to use interrupt input; if we can't, then start polling. */
12819 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12821 #ifdef USE_X_TOOLKIT
12822 XtToolkitInitialize ();
12823 Xt_app_con = XtCreateApplicationContext ();
12824 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
12825 #endif
12827 /* Note that there is no real way portable across R3/R4 to get the
12828 original error handler. */
12829 XSetErrorHandler (x_error_handler);
12830 XSetIOErrorHandler (x_io_error_quitter);
12832 /* Disable Window Change signals; they are handled by X events. */
12833 #ifdef SIGWINCH
12834 signal (SIGWINCH, SIG_DFL);
12835 #endif /* ! defined (SIGWINCH) */
12837 signal (SIGPIPE, x_connection_signal);
12841 void
12842 syms_of_xterm ()
12844 staticpro (&x_error_message_string);
12845 x_error_message_string = Qnil;
12847 staticpro (&x_display_name_list);
12848 x_display_name_list = Qnil;
12850 staticpro (&last_mouse_scroll_bar);
12851 last_mouse_scroll_bar = Qnil;
12853 staticpro (&Qvendor_specific_keysyms);
12854 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
12856 staticpro (&last_mouse_press_frame);
12857 last_mouse_press_frame = Qnil;
12859 staticpro (&help_echo);
12860 help_echo = Qnil;
12861 staticpro (&previous_help_echo);
12862 previous_help_echo = Qnil;
12864 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
12865 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12866 For example, if a block cursor is over a tab, it will be drawn as\n\
12867 wide as that tab on the display.");
12868 x_stretch_cursor_p = 0;
12870 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
12871 "If not nil, Emacs uses toolkit scroll bars.");
12872 #if USE_TOOLKIT_SCROLL_BARS
12873 x_toolkit_scroll_bars_p = 1;
12874 #else
12875 x_toolkit_scroll_bars_p = 0;
12876 #endif
12878 defsubr (&Sxt_process_timeouts);
12879 staticpro (&last_mouse_motion_frame);
12880 last_mouse_motion_frame = Qnil;
12883 #endif /* not HAVE_X_WINDOWS */