(x_use_underline_position_properties): New variable.
[emacs.git] / src / xterm.c
blobf4cce32b5fafd6f4c4f1fd3aca49e0412996fb69
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
25 #include <config.h>
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
31 #include <stdio.h>
33 #ifdef HAVE_X_WINDOWS
35 #include "lisp.h"
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
57 #include "systty.h"
58 #include "systime.h"
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "disptab.h"
85 #include "buffer.h"
86 #include "window.h"
87 #include "keyboard.h"
88 #include "intervals.h"
89 #include "process.h"
90 #include "atimer.h"
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
96 #ifdef HAVE_SYS_TIME_H
97 #include <sys/time.h>
98 #endif
99 #ifdef HAVE_UNISTD_H
100 #include <unistd.h>
101 #endif
103 #ifdef USE_X_TOOLKIT
105 extern void free_frame_menubar P_ ((struct frame *));
106 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110 #define HACK_EDITRES
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
114 /* Include toolkit specific headers for the scroll bar widget. */
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #else /* !USE_MOTIF i.e. use Xaw */
122 #ifdef HAVE_XAW3D
123 #include <X11/Xaw3d/Simple.h>
124 #include <X11/Xaw3d/Scrollbar.h>
125 #define ARROW_SCROLLBAR
126 #include <X11/Xaw3d/ScrollbarP.h>
127 #else /* !HAVE_XAW3D */
128 #include <X11/Xaw/Simple.h>
129 #include <X11/Xaw/Scrollbar.h>
130 #endif /* !HAVE_XAW3D */
131 #ifndef XtNpickTop
132 #define XtNpickTop "pickTop"
133 #endif /* !XtNpickTop */
134 #endif /* !USE_MOTIF */
135 #endif /* USE_TOOLKIT_SCROLL_BARS */
137 #endif /* USE_X_TOOLKIT */
139 #ifndef USE_X_TOOLKIT
140 #define x_any_window_to_frame x_window_to_frame
141 #define x_top_window_to_frame x_window_to_frame
142 #endif
144 #ifdef USE_X_TOOLKIT
145 #include "widget.h"
146 #ifndef XtNinitialState
147 #define XtNinitialState "initialState"
148 #endif
149 #endif
151 #ifndef min
152 #define min(a,b) ((a) < (b) ? (a) : (b))
153 #endif
154 #ifndef max
155 #define max(a,b) ((a) > (b) ? (a) : (b))
156 #endif
158 #define abs(x) ((x) < 0 ? -(x) : (x))
160 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
163 /* Bitmaps for truncated lines. */
165 enum bitmap_type
167 NO_BITMAP,
168 LEFT_TRUNCATION_BITMAP,
169 RIGHT_TRUNCATION_BITMAP,
170 OVERLAY_ARROW_BITMAP,
171 CONTINUED_LINE_BITMAP,
172 CONTINUATION_LINE_BITMAP,
173 ZV_LINE_BITMAP
176 /* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
179 #define zv_width 8
180 #define zv_height 8
181 static unsigned char zv_bits[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184 /* An arrow like this: `<-'. */
186 #define left_width 8
187 #define left_height 8
188 static unsigned char left_bits[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191 /* Right truncation arrow bitmap `->'. */
193 #define right_width 8
194 #define right_height 8
195 static unsigned char right_bits[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198 /* Marker for continued lines. */
200 #define continued_width 8
201 #define continued_height 8
202 static unsigned char continued_bits[] = {
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205 /* Marker for continuation lines. */
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits[] = {
210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
212 /* Overlay arrow bitmap. */
214 #if 0
215 /* A bomb. */
216 #define ov_width 8
217 #define ov_height 8
218 static unsigned char ov_bits[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
220 #else
221 /* A triangular arrow. */
222 #define ov_width 8
223 #define ov_height 8
224 static unsigned char ov_bits[] = {
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
227 #endif
229 extern Lisp_Object Qhelp_echo;
232 /* Non-nil means Emacs uses toolkit scroll bars. */
234 Lisp_Object Vx_toolkit_scroll_bars;
236 /* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
239 static Lisp_Object help_echo;
240 static Lisp_Object help_echo_window;
241 static Lisp_Object help_echo_object;
242 static int help_echo_pos;
244 /* Temporary variable for XTread_socket. */
246 static Lisp_Object previous_help_echo;
248 /* Non-zero means that a HELP_EVENT has been generated since Emacs
249 start. */
251 static int any_help_event_p;
253 /* Non-zero means draw block and hollow cursor as wide as the glyph
254 under it. For example, if a block cursor is over a tab, it will be
255 drawn as wide as that tab on the display. */
257 int x_stretch_cursor_p;
259 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
261 int x_use_underline_position_properties;
263 /* This is a chain of structures for all the X displays currently in
264 use. */
266 struct x_display_info *x_display_list;
268 /* This is a list of cons cells, each of the form (NAME
269 . FONT-LIST-CACHE), one for each element of x_display_list and in
270 the same order. NAME is the name of the frame. FONT-LIST-CACHE
271 records previous values returned by x-list-fonts. */
273 Lisp_Object x_display_name_list;
275 /* Frame being updated by update_frame. This is declared in term.c.
276 This is set by update_begin and looked at by all the XT functions.
277 It is zero while not inside an update. In that case, the XT
278 functions assume that `selected_frame' is the frame to apply to. */
280 extern struct frame *updating_frame;
282 extern int waiting_for_input;
284 /* This is a frame waiting to be auto-raised, within XTread_socket. */
286 struct frame *pending_autoraise_frame;
288 #ifdef USE_X_TOOLKIT
289 /* The application context for Xt use. */
290 XtAppContext Xt_app_con;
291 static String Xt_default_resources[] = {0};
292 #endif /* USE_X_TOOLKIT */
294 /* Nominal cursor position -- where to draw output.
295 HPOS and VPOS are window relative glyph matrix coordinates.
296 X and Y are window relative pixel coordinates. */
298 struct cursor_pos output_cursor;
300 /* Non-zero means user is interacting with a toolkit scroll bar. */
302 static int toolkit_scroll_bar_interaction;
304 /* Mouse movement.
306 Formerly, we used PointerMotionHintMask (in standard_event_mask)
307 so that we would have to call XQueryPointer after each MotionNotify
308 event to ask for another such event. However, this made mouse tracking
309 slow, and there was a bug that made it eventually stop.
311 Simply asking for MotionNotify all the time seems to work better.
313 In order to avoid asking for motion events and then throwing most
314 of them away or busy-polling the server for mouse positions, we ask
315 the server for pointer motion hints. This means that we get only
316 one event per group of mouse movements. "Groups" are delimited by
317 other kinds of events (focus changes and button clicks, for
318 example), or by XQueryPointer calls; when one of these happens, we
319 get another MotionNotify event the next time the mouse moves. This
320 is at least as efficient as getting motion events when mouse
321 tracking is on, and I suspect only negligibly worse when tracking
322 is off. */
324 /* Where the mouse was last time we reported a mouse event. */
326 FRAME_PTR last_mouse_frame;
327 static XRectangle last_mouse_glyph;
328 static Lisp_Object last_mouse_press_frame;
330 /* The scroll bar in which the last X motion event occurred.
332 If the last X motion event occurred in a scroll bar, we set this so
333 XTmouse_position can know whether to report a scroll bar motion or
334 an ordinary motion.
336 If the last X motion event didn't occur in a scroll bar, we set
337 this to Qnil, to tell XTmouse_position to return an ordinary motion
338 event. */
340 static Lisp_Object last_mouse_scroll_bar;
342 /* This is a hack. We would really prefer that XTmouse_position would
343 return the time associated with the position it returns, but there
344 doesn't seem to be any way to wrest the time-stamp from the server
345 along with the position query. So, we just keep track of the time
346 of the last movement we received, and return that in hopes that
347 it's somewhat accurate. */
349 static Time last_mouse_movement_time;
351 /* Incremented by XTread_socket whenever it really tries to read
352 events. */
354 #ifdef __STDC__
355 static int volatile input_signal_count;
356 #else
357 static int input_signal_count;
358 #endif
360 /* Used locally within XTread_socket. */
362 static int x_noop_count;
364 /* Initial values of argv and argc. */
366 extern char **initial_argv;
367 extern int initial_argc;
369 extern Lisp_Object Vcommand_line_args, Vsystem_name;
371 /* Tells if a window manager is present or not. */
373 extern Lisp_Object Vx_no_window_manager;
375 extern Lisp_Object Qface, Qmouse_face;
377 extern int errno;
379 /* A mask of extra modifier bits to put into every keyboard char. */
381 extern int extra_keyboard_modifiers;
383 static Lisp_Object Qvendor_specific_keysyms;
385 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
386 extern Lisp_Object x_icon_type P_ ((struct frame *));
389 /* Enumeration for overriding/changing the face to use for drawing
390 glyphs in x_draw_glyphs. */
392 enum draw_glyphs_face
394 DRAW_NORMAL_TEXT,
395 DRAW_INVERSE_VIDEO,
396 DRAW_CURSOR,
397 DRAW_MOUSE_FACE,
398 DRAW_IMAGE_RAISED,
399 DRAW_IMAGE_SUNKEN
402 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
403 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
404 static const XColor *x_color_cells P_ ((Display *, int *));
405 static void x_update_window_end P_ ((struct window *, int, int));
406 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
407 void x_delete_display P_ ((struct x_display_info *));
408 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
409 unsigned));
410 static int fast_find_position P_ ((struct window *, int, int *, int *,
411 int *, int *));
412 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
413 int *, int *, int *, int *, int));
414 static void set_output_cursor P_ ((struct cursor_pos *));
415 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
416 int *, int *, int *, int));
417 static void note_mode_line_highlight P_ ((struct window *, int, int));
418 static void note_mouse_highlight P_ ((struct frame *, int, int));
419 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
420 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
421 static void show_mouse_face P_ ((struct x_display_info *,
422 enum draw_glyphs_face));
423 static int x_io_error_quitter P_ ((Display *));
424 int x_catch_errors P_ ((Display *));
425 void x_uncatch_errors P_ ((Display *, int));
426 void x_lower_frame P_ ((struct frame *));
427 void x_scroll_bar_clear P_ ((struct frame *));
428 int x_had_errors_p P_ ((Display *));
429 void x_wm_set_size_hint P_ ((struct frame *, long, int));
430 void x_raise_frame P_ ((struct frame *));
431 void x_set_window_size P_ ((struct frame *, int, int, int));
432 void x_wm_set_window_state P_ ((struct frame *, int));
433 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
434 void x_initialize P_ ((void));
435 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
436 static int x_compute_min_glyph_bounds P_ ((struct frame *));
437 static void x_draw_phys_cursor_glyph P_ ((struct window *,
438 struct glyph_row *,
439 enum draw_glyphs_face));
440 static void x_update_end P_ ((struct frame *));
441 static void XTframe_up_to_date P_ ((struct frame *));
442 static void XTreassert_line_highlight P_ ((int, int));
443 static void x_change_line_highlight P_ ((int, int, int, int));
444 static void XTset_terminal_modes P_ ((void));
445 static void XTreset_terminal_modes P_ ((void));
446 static void XTcursor_to P_ ((int, int, int, int));
447 static void x_write_glyphs P_ ((struct glyph *, int));
448 static void x_clear_end_of_line P_ ((int));
449 static void x_clear_frame P_ ((void));
450 static void x_clear_cursor P_ ((struct window *));
451 static void frame_highlight P_ ((struct frame *));
452 static void frame_unhighlight P_ ((struct frame *));
453 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
454 static void XTframe_rehighlight P_ ((struct frame *));
455 static void x_frame_rehighlight P_ ((struct x_display_info *));
456 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
457 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
458 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
459 XRectangle *));
460 static void expose_frame P_ ((struct frame *, int, int, int, int));
461 static void expose_window_tree P_ ((struct window *, XRectangle *));
462 static void expose_window P_ ((struct window *, XRectangle *));
463 static void expose_area P_ ((struct window *, struct glyph_row *,
464 XRectangle *, enum glyph_row_area));
465 static void expose_line P_ ((struct window *, struct glyph_row *,
466 XRectangle *));
467 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
468 static void x_update_window_cursor P_ ((struct window *, int));
469 static void x_erase_phys_cursor P_ ((struct window *));
470 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
471 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
472 enum bitmap_type));
474 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
475 GC, int));
476 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
477 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
478 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
479 static void x_flush P_ ((struct frame *f));
480 static void x_update_begin P_ ((struct frame *));
481 static void x_update_window_begin P_ ((struct window *));
482 static void x_draw_vertical_border P_ ((struct window *));
483 static void x_after_update_window_line P_ ((struct glyph_row *));
484 static INLINE void take_vertical_position_into_account P_ ((struct it *));
485 static void x_produce_stretch_glyph P_ ((struct it *));
486 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
487 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
488 enum scroll_bar_part *,
489 Lisp_Object *, Lisp_Object *,
490 unsigned long *));
492 /* Flush display of frame F, or of all frames if F is null. */
494 static void
495 x_flush (f)
496 struct frame *f;
498 BLOCK_INPUT;
499 if (f == NULL)
501 Lisp_Object rest, frame;
502 FOR_EACH_FRAME (rest, frame)
503 x_flush (XFRAME (frame));
505 else if (FRAME_X_P (f))
506 XFlush (FRAME_X_DISPLAY (f));
507 UNBLOCK_INPUT;
511 /* Remove calls to XFlush by defining XFlush to an empty replacement.
512 Calls to XFlush should be unnecessary because the X output buffer
513 is flushed automatically as needed by calls to XPending,
514 XNextEvent, or XWindowEvent according to the XFlush man page.
515 XTread_socket calls XPending. Removing XFlush improves
516 performance. */
518 #define XFlush(DISPLAY) (void) 0
521 /***********************************************************************
522 Debugging
523 ***********************************************************************/
525 #if 0
527 /* This is a function useful for recording debugging information about
528 the sequence of occurrences in this file. */
530 struct record
532 char *locus;
533 int type;
536 struct record event_record[100];
538 int event_record_index;
540 record_event (locus, type)
541 char *locus;
542 int type;
544 if (event_record_index == sizeof (event_record) / sizeof (struct record))
545 event_record_index = 0;
547 event_record[event_record_index].locus = locus;
548 event_record[event_record_index].type = type;
549 event_record_index++;
552 #endif /* 0 */
556 /* Return the struct x_display_info corresponding to DPY. */
558 struct x_display_info *
559 x_display_info_for_display (dpy)
560 Display *dpy;
562 struct x_display_info *dpyinfo;
564 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
565 if (dpyinfo->display == dpy)
566 return dpyinfo;
568 return 0;
573 /***********************************************************************
574 Starting and ending an update
575 ***********************************************************************/
577 /* Start an update of frame F. This function is installed as a hook
578 for update_begin, i.e. it is called when update_begin is called.
579 This function is called prior to calls to x_update_window_begin for
580 each window being updated. Currently, there is nothing to do here
581 because all interesting stuff is done on a window basis. */
583 static void
584 x_update_begin (f)
585 struct frame *f;
587 /* Nothing to do. */
591 /* Start update of window W. Set the global variable updated_window
592 to the window being updated and set output_cursor to the cursor
593 position of W. */
595 static void
596 x_update_window_begin (w)
597 struct window *w;
599 struct frame *f = XFRAME (WINDOW_FRAME (w));
600 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
602 updated_window = w;
603 set_output_cursor (&w->cursor);
605 BLOCK_INPUT;
607 if (f == display_info->mouse_face_mouse_frame)
609 /* Don't do highlighting for mouse motion during the update. */
610 display_info->mouse_face_defer = 1;
612 /* If F needs to be redrawn, simply forget about any prior mouse
613 highlighting. */
614 if (FRAME_GARBAGED_P (f))
615 display_info->mouse_face_window = Qnil;
617 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
618 their mouse_face_p flag set, which means that they are always
619 unequal to rows in a desired matrix which never have that
620 flag set. So, rows containing mouse-face glyphs are never
621 scrolled, and we don't have to switch the mouse highlight off
622 here to prevent it from being scrolled. */
624 /* Can we tell that this update does not affect the window
625 where the mouse highlight is? If so, no need to turn off.
626 Likewise, don't do anything if the frame is garbaged;
627 in that case, the frame's current matrix that we would use
628 is all wrong, and we will redisplay that line anyway. */
629 if (!NILP (display_info->mouse_face_window)
630 && w == XWINDOW (display_info->mouse_face_window))
632 int i;
634 for (i = 0; i < w->desired_matrix->nrows; ++i)
635 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
636 break;
638 if (i < w->desired_matrix->nrows)
639 clear_mouse_face (display_info);
641 #endif /* 0 */
644 UNBLOCK_INPUT;
648 /* Draw a vertical window border to the right of window W if W doesn't
649 have vertical scroll bars. */
651 static void
652 x_draw_vertical_border (w)
653 struct window *w;
655 struct frame *f = XFRAME (WINDOW_FRAME (w));
657 /* Redraw borders between horizontally adjacent windows. Don't
658 do it for frames with vertical scroll bars because either the
659 right scroll bar of a window, or the left scroll bar of its
660 neighbor will suffice as a border. */
661 if (!WINDOW_RIGHTMOST_P (w)
662 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
664 int x0, x1, y0, y1;
666 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
667 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
668 y1 -= 1;
670 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
671 f->output_data.x->normal_gc, x1, y0, x1, y1);
676 /* End update of window W (which is equal to updated_window).
678 Draw vertical borders between horizontally adjacent windows, and
679 display W's cursor if CURSOR_ON_P is non-zero.
681 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
682 glyphs in mouse-face were overwritten. In that case we have to
683 make sure that the mouse-highlight is properly redrawn.
685 W may be a menu bar pseudo-window in case we don't have X toolkit
686 support. Such windows don't have a cursor, so don't display it
687 here. */
689 static void
690 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
691 struct window *w;
692 int cursor_on_p, mouse_face_overwritten_p;
694 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
696 if (!w->pseudo_window_p)
698 BLOCK_INPUT;
700 if (cursor_on_p)
701 x_display_and_set_cursor (w, 1, output_cursor.hpos,
702 output_cursor.vpos,
703 output_cursor.x, output_cursor.y);
705 x_draw_vertical_border (w);
706 UNBLOCK_INPUT;
709 /* If a row with mouse-face was overwritten, arrange for
710 XTframe_up_to_date to redisplay the mouse highlight. */
711 if (mouse_face_overwritten_p)
713 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
714 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
715 dpyinfo->mouse_face_window = Qnil;
718 updated_window = NULL;
722 /* End update of frame F. This function is installed as a hook in
723 update_end. */
725 static void
726 x_update_end (f)
727 struct frame *f;
729 /* Mouse highlight may be displayed again. */
730 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
732 BLOCK_INPUT;
733 XFlush (FRAME_X_DISPLAY (f));
734 UNBLOCK_INPUT;
738 /* This function is called from various places in xdisp.c whenever a
739 complete update has been performed. The global variable
740 updated_window is not available here. */
742 static void
743 XTframe_up_to_date (f)
744 struct frame *f;
746 if (FRAME_X_P (f))
748 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
750 if (dpyinfo->mouse_face_deferred_gc
751 || f == dpyinfo->mouse_face_mouse_frame)
753 BLOCK_INPUT;
754 if (dpyinfo->mouse_face_mouse_frame)
755 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
756 dpyinfo->mouse_face_mouse_x,
757 dpyinfo->mouse_face_mouse_y);
758 dpyinfo->mouse_face_deferred_gc = 0;
759 UNBLOCK_INPUT;
765 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
766 arrow bitmaps, or clear the areas where they would be displayed
767 before DESIRED_ROW is made current. The window being updated is
768 found in updated_window. This function It is called from
769 update_window_line only if it is known that there are differences
770 between bitmaps to be drawn between current row and DESIRED_ROW. */
772 static void
773 x_after_update_window_line (desired_row)
774 struct glyph_row *desired_row;
776 struct window *w = updated_window;
778 xassert (w);
780 if (!desired_row->mode_line_p && !w->pseudo_window_p)
782 struct frame *f;
783 int width;
785 BLOCK_INPUT;
786 x_draw_row_bitmaps (w, desired_row);
788 /* When a window has disappeared, make sure that no rest of
789 full-width rows stays visible in the internal border. */
790 if (windows_or_buffers_changed
791 && (f = XFRAME (w->frame),
792 width = FRAME_INTERNAL_BORDER_WIDTH (f),
793 width != 0))
795 int height = desired_row->visible_height;
796 int x = (window_box_right (w, -1)
797 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
798 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
800 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
801 x, y, width, height, False);
804 UNBLOCK_INPUT;
809 /* Draw the bitmap WHICH in one of the areas to the left or right of
810 window W. ROW is the glyph row for which to display the bitmap; it
811 determines the vertical position at which the bitmap has to be
812 drawn. */
814 static void
815 x_draw_bitmap (w, row, which)
816 struct window *w;
817 struct glyph_row *row;
818 enum bitmap_type which;
820 struct frame *f = XFRAME (WINDOW_FRAME (w));
821 Display *display = FRAME_X_DISPLAY (f);
822 Window window = FRAME_X_WINDOW (f);
823 int x, y, wd, h, dy;
824 unsigned char *bits;
825 Pixmap pixmap;
826 GC gc = f->output_data.x->normal_gc;
827 struct face *face;
828 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
830 /* Must clip because of partially visible lines. */
831 x_clip_to_row (w, row, gc, 1);
833 switch (which)
835 case LEFT_TRUNCATION_BITMAP:
836 wd = left_width;
837 h = left_height;
838 bits = left_bits;
839 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
840 - wd
841 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
842 break;
844 case OVERLAY_ARROW_BITMAP:
845 wd = left_width;
846 h = left_height;
847 bits = ov_bits;
848 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
849 - wd
850 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
851 break;
853 case RIGHT_TRUNCATION_BITMAP:
854 wd = right_width;
855 h = right_height;
856 bits = right_bits;
857 x = window_box_right (w, -1);
858 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
859 break;
861 case CONTINUED_LINE_BITMAP:
862 wd = right_width;
863 h = right_height;
864 bits = continued_bits;
865 x = window_box_right (w, -1);
866 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
867 break;
869 case CONTINUATION_LINE_BITMAP:
870 wd = continuation_width;
871 h = continuation_height;
872 bits = continuation_bits;
873 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
874 - wd
875 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
876 break;
878 case ZV_LINE_BITMAP:
879 wd = zv_width;
880 h = zv_height;
881 bits = zv_bits;
882 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
883 - wd
884 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
885 break;
887 default:
888 abort ();
891 /* Convert to frame coordinates. Set dy to the offset in the row to
892 start drawing the bitmap. */
893 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
894 dy = (row->height - h) / 2;
896 /* Draw the bitmap. I believe these small pixmaps can be cached
897 by the server. */
898 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
899 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
900 face->foreground,
901 face->background, depth);
902 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
903 XFreePixmap (display, pixmap);
904 XSetClipMask (display, gc, None);
908 /* Draw flags bitmaps for glyph row ROW on window W. Call this
909 function with input blocked. */
911 static void
912 x_draw_row_bitmaps (w, row)
913 struct window *w;
914 struct glyph_row *row;
916 struct frame *f = XFRAME (w->frame);
917 enum bitmap_type bitmap;
918 struct face *face;
919 int header_line_height = -1;
921 xassert (interrupt_input_blocked);
923 /* If row is completely invisible, because of vscrolling, we
924 don't have to draw anything. */
925 if (row->visible_height <= 0)
926 return;
928 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
929 PREPARE_FACE_FOR_DISPLAY (f, face);
931 /* Decide which bitmap to draw at the left side. */
932 if (row->overlay_arrow_p)
933 bitmap = OVERLAY_ARROW_BITMAP;
934 else if (row->truncated_on_left_p)
935 bitmap = LEFT_TRUNCATION_BITMAP;
936 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
937 bitmap = CONTINUATION_LINE_BITMAP;
938 else if (row->indicate_empty_line_p)
939 bitmap = ZV_LINE_BITMAP;
940 else
941 bitmap = NO_BITMAP;
943 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
944 the flags area. */
945 if (bitmap == NO_BITMAP
946 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
947 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
949 /* If W has a vertical border to its left, don't draw over it. */
950 int border = ((XFASTINT (w->left) > 0
951 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
952 ? 1 : 0);
953 int left = window_box_left (w, -1);
955 if (header_line_height < 0)
956 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
958 /* In case the same realized face is used for bitmap areas and
959 for something displayed in the text (e.g. face `region' on
960 mono-displays, the fill style may have been changed to
961 FillSolid in x_draw_glyph_string_background. */
962 if (face->stipple)
963 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
964 else
965 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
967 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
968 face->gc,
969 (left
970 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
971 + border),
972 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
973 row->y)),
974 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
975 row->visible_height);
976 if (!face->stipple)
977 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
980 /* Draw the left bitmap. */
981 if (bitmap != NO_BITMAP)
982 x_draw_bitmap (w, row, bitmap);
984 /* Decide which bitmap to draw at the right side. */
985 if (row->truncated_on_right_p)
986 bitmap = RIGHT_TRUNCATION_BITMAP;
987 else if (row->continued_p)
988 bitmap = CONTINUED_LINE_BITMAP;
989 else
990 bitmap = NO_BITMAP;
992 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
993 the flags area. */
994 if (bitmap == NO_BITMAP
995 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
996 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
998 int right = window_box_right (w, -1);
1000 if (header_line_height < 0)
1001 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1003 /* In case the same realized face is used for bitmap areas and
1004 for something displayed in the text (e.g. face `region' on
1005 mono-displays, the fill style may have been changed to
1006 FillSolid in x_draw_glyph_string_background. */
1007 if (face->stipple)
1008 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1009 else
1010 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1011 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1012 face->gc,
1013 right,
1014 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1015 row->y)),
1016 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1017 row->visible_height);
1018 if (!face->stipple)
1019 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1022 /* Draw the right bitmap. */
1023 if (bitmap != NO_BITMAP)
1024 x_draw_bitmap (w, row, bitmap);
1028 /***********************************************************************
1029 Line Highlighting
1030 ***********************************************************************/
1032 /* External interface to control of standout mode. Not used for X
1033 frames. Aborts when called. */
1035 static void
1036 XTreassert_line_highlight (new, vpos)
1037 int new, vpos;
1039 abort ();
1043 /* Call this when about to modify line at position VPOS and change
1044 whether it is highlighted. Not used for X frames. Aborts when
1045 called. */
1047 static void
1048 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1049 int new_highlight, vpos, y, first_unused_hpos;
1051 abort ();
1055 /* This is called when starting Emacs and when restarting after
1056 suspend. When starting Emacs, no X window is mapped. And nothing
1057 must be done to Emacs's own window if it is suspended (though that
1058 rarely happens). */
1060 static void
1061 XTset_terminal_modes ()
1065 /* This is called when exiting or suspending Emacs. Exiting will make
1066 the X-windows go away, and suspending requires no action. */
1068 static void
1069 XTreset_terminal_modes ()
1075 /***********************************************************************
1076 Output Cursor
1077 ***********************************************************************/
1079 /* Set the global variable output_cursor to CURSOR. All cursor
1080 positions are relative to updated_window. */
1082 static void
1083 set_output_cursor (cursor)
1084 struct cursor_pos *cursor;
1086 output_cursor.hpos = cursor->hpos;
1087 output_cursor.vpos = cursor->vpos;
1088 output_cursor.x = cursor->x;
1089 output_cursor.y = cursor->y;
1093 /* Set a nominal cursor position.
1095 HPOS and VPOS are column/row positions in a window glyph matrix. X
1096 and Y are window text area relative pixel positions.
1098 If this is done during an update, updated_window will contain the
1099 window that is being updated and the position is the future output
1100 cursor position for that window. If updated_window is null, use
1101 selected_window and display the cursor at the given position. */
1103 static void
1104 XTcursor_to (vpos, hpos, y, x)
1105 int vpos, hpos, y, x;
1107 struct window *w;
1109 /* If updated_window is not set, work on selected_window. */
1110 if (updated_window)
1111 w = updated_window;
1112 else
1113 w = XWINDOW (selected_window);
1115 /* Set the output cursor. */
1116 output_cursor.hpos = hpos;
1117 output_cursor.vpos = vpos;
1118 output_cursor.x = x;
1119 output_cursor.y = y;
1121 /* If not called as part of an update, really display the cursor.
1122 This will also set the cursor position of W. */
1123 if (updated_window == NULL)
1125 BLOCK_INPUT;
1126 x_display_cursor (w, 1, hpos, vpos, x, y);
1127 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1128 UNBLOCK_INPUT;
1134 /***********************************************************************
1135 Display Iterator
1136 ***********************************************************************/
1138 /* Function prototypes of this page. */
1140 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1141 struct glyph *,
1142 XChar2b *,
1143 int *));
1144 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1145 int, XChar2b *, int));
1146 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1147 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1148 static void x_append_glyph P_ ((struct it *));
1149 static void x_append_composite_glyph P_ ((struct it *));
1150 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1151 int, int, double));
1152 static void x_produce_glyphs P_ ((struct it *));
1153 static void x_produce_image_glyph P_ ((struct it *it));
1156 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1157 is not contained in the font. */
1159 static INLINE XCharStruct *
1160 x_per_char_metric (font, char2b)
1161 XFontStruct *font;
1162 XChar2b *char2b;
1164 /* The result metric information. */
1165 XCharStruct *pcm = NULL;
1167 xassert (font && char2b);
1169 if (font->per_char != NULL)
1171 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1173 /* min_char_or_byte2 specifies the linear character index
1174 corresponding to the first element of the per_char array,
1175 max_char_or_byte2 is the index of the last character. A
1176 character with non-zero CHAR2B->byte1 is not in the font.
1177 A character with byte2 less than min_char_or_byte2 or
1178 greater max_char_or_byte2 is not in the font. */
1179 if (char2b->byte1 == 0
1180 && char2b->byte2 >= font->min_char_or_byte2
1181 && char2b->byte2 <= font->max_char_or_byte2)
1182 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1184 else
1186 /* If either min_byte1 or max_byte1 are nonzero, both
1187 min_char_or_byte2 and max_char_or_byte2 are less than
1188 256, and the 2-byte character index values corresponding
1189 to the per_char array element N (counting from 0) are:
1191 byte1 = N/D + min_byte1
1192 byte2 = N\D + min_char_or_byte2
1194 where:
1196 D = max_char_or_byte2 - min_char_or_byte2 + 1
1197 / = integer division
1198 \ = integer modulus */
1199 if (char2b->byte1 >= font->min_byte1
1200 && char2b->byte1 <= font->max_byte1
1201 && char2b->byte2 >= font->min_char_or_byte2
1202 && char2b->byte2 <= font->max_char_or_byte2)
1204 pcm = (font->per_char
1205 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1206 * (char2b->byte1 - font->min_byte1))
1207 + (char2b->byte2 - font->min_char_or_byte2));
1211 else
1213 /* If the per_char pointer is null, all glyphs between the first
1214 and last character indexes inclusive have the same
1215 information, as given by both min_bounds and max_bounds. */
1216 if (char2b->byte2 >= font->min_char_or_byte2
1217 && char2b->byte2 <= font->max_char_or_byte2)
1218 pcm = &font->max_bounds;
1221 return ((pcm == NULL
1222 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1223 ? NULL : pcm);
1227 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1228 the two-byte form of C. Encoding is returned in *CHAR2B. */
1230 static INLINE void
1231 x_encode_char (c, char2b, font_info)
1232 int c;
1233 XChar2b *char2b;
1234 struct font_info *font_info;
1236 int charset = CHAR_CHARSET (c);
1237 XFontStruct *font = font_info->font;
1239 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1240 This may be either a program in a special encoder language or a
1241 fixed encoding. */
1242 if (font_info->font_encoder)
1244 /* It's a program. */
1245 struct ccl_program *ccl = font_info->font_encoder;
1247 if (CHARSET_DIMENSION (charset) == 1)
1249 ccl->reg[0] = charset;
1250 ccl->reg[1] = char2b->byte2;
1252 else
1254 ccl->reg[0] = charset;
1255 ccl->reg[1] = char2b->byte1;
1256 ccl->reg[2] = char2b->byte2;
1259 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1261 /* We assume that MSBs are appropriately set/reset by CCL
1262 program. */
1263 if (font->max_byte1 == 0) /* 1-byte font */
1264 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1265 else
1266 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1268 else if (font_info->encoding[charset])
1270 /* Fixed encoding scheme. See fontset.h for the meaning of the
1271 encoding numbers. */
1272 int enc = font_info->encoding[charset];
1274 if ((enc == 1 || enc == 2)
1275 && CHARSET_DIMENSION (charset) == 2)
1276 char2b->byte1 |= 0x80;
1278 if (enc == 1 || enc == 3)
1279 char2b->byte2 |= 0x80;
1284 /* Get face and two-byte form of character C in face FACE_ID on frame
1285 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1286 means we want to display multibyte text. Value is a pointer to a
1287 realized face that is ready for display. */
1289 static INLINE struct face *
1290 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1291 struct frame *f;
1292 int c, face_id;
1293 XChar2b *char2b;
1294 int multibyte_p;
1296 struct face *face = FACE_FROM_ID (f, face_id);
1298 if (!multibyte_p)
1300 /* Unibyte case. We don't have to encode, but we have to make
1301 sure to use a face suitable for unibyte. */
1302 char2b->byte1 = 0;
1303 char2b->byte2 = c;
1304 face_id = FACE_FOR_CHAR (f, face, c);
1305 face = FACE_FROM_ID (f, face_id);
1307 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1309 /* Case of ASCII in a face known to fit ASCII. */
1310 char2b->byte1 = 0;
1311 char2b->byte2 = c;
1313 else
1315 int c1, c2, charset;
1317 /* Split characters into bytes. If c2 is -1 afterwards, C is
1318 really a one-byte character so that byte1 is zero. */
1319 SPLIT_CHAR (c, charset, c1, c2);
1320 if (c2 > 0)
1321 char2b->byte1 = c1, char2b->byte2 = c2;
1322 else
1323 char2b->byte1 = 0, char2b->byte2 = c1;
1325 /* Maybe encode the character in *CHAR2B. */
1326 if (face->font != NULL)
1328 struct font_info *font_info
1329 = FONT_INFO_FROM_ID (f, face->font_info_id);
1330 if (font_info)
1331 x_encode_char (c, char2b, font_info);
1335 /* Make sure X resources of the face are allocated. */
1336 xassert (face != NULL);
1337 PREPARE_FACE_FOR_DISPLAY (f, face);
1339 return face;
1343 /* Get face and two-byte form of character glyph GLYPH on frame F.
1344 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1345 a pointer to a realized face that is ready for display. */
1347 static INLINE struct face *
1348 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1349 struct frame *f;
1350 struct glyph *glyph;
1351 XChar2b *char2b;
1352 int *two_byte_p;
1354 struct face *face;
1356 xassert (glyph->type == CHAR_GLYPH);
1357 face = FACE_FROM_ID (f, glyph->face_id);
1359 if (two_byte_p)
1360 *two_byte_p = 0;
1362 if (!glyph->multibyte_p)
1364 /* Unibyte case. We don't have to encode, but we have to make
1365 sure to use a face suitable for unibyte. */
1366 char2b->byte1 = 0;
1367 char2b->byte2 = glyph->u.ch;
1369 else if (glyph->u.ch < 128
1370 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1372 /* Case of ASCII in a face known to fit ASCII. */
1373 char2b->byte1 = 0;
1374 char2b->byte2 = glyph->u.ch;
1376 else
1378 int c1, c2, charset;
1380 /* Split characters into bytes. If c2 is -1 afterwards, C is
1381 really a one-byte character so that byte1 is zero. */
1382 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1383 if (c2 > 0)
1384 char2b->byte1 = c1, char2b->byte2 = c2;
1385 else
1386 char2b->byte1 = 0, char2b->byte2 = c1;
1388 /* Maybe encode the character in *CHAR2B. */
1389 if (charset != CHARSET_ASCII)
1391 struct font_info *font_info
1392 = FONT_INFO_FROM_ID (f, face->font_info_id);
1393 if (font_info)
1395 x_encode_char (glyph->u.ch, char2b, font_info);
1396 if (two_byte_p)
1397 *two_byte_p
1398 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1403 /* Make sure X resources of the face are allocated. */
1404 xassert (face != NULL);
1405 PREPARE_FACE_FOR_DISPLAY (f, face);
1406 return face;
1410 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1411 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1413 static INLINE void
1414 x_append_glyph (it)
1415 struct it *it;
1417 struct glyph *glyph;
1418 enum glyph_row_area area = it->area;
1420 xassert (it->glyph_row);
1421 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1423 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1424 if (glyph < it->glyph_row->glyphs[area + 1])
1426 glyph->charpos = CHARPOS (it->position);
1427 glyph->object = it->object;
1428 glyph->pixel_width = it->pixel_width;
1429 glyph->voffset = it->voffset;
1430 glyph->type = CHAR_GLYPH;
1431 glyph->multibyte_p = it->multibyte_p;
1432 glyph->left_box_line_p = it->start_of_box_run_p;
1433 glyph->right_box_line_p = it->end_of_box_run_p;
1434 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1435 || it->phys_descent > it->descent);
1436 glyph->padding_p = 0;
1437 glyph->glyph_not_available_p = it->glyph_not_available_p;
1438 glyph->face_id = it->face_id;
1439 glyph->u.ch = it->char_to_display;
1440 ++it->glyph_row->used[area];
1444 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1445 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1447 static INLINE void
1448 x_append_composite_glyph (it)
1449 struct it *it;
1451 struct glyph *glyph;
1452 enum glyph_row_area area = it->area;
1454 xassert (it->glyph_row);
1456 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1457 if (glyph < it->glyph_row->glyphs[area + 1])
1459 glyph->charpos = CHARPOS (it->position);
1460 glyph->object = it->object;
1461 glyph->pixel_width = it->pixel_width;
1462 glyph->voffset = it->voffset;
1463 glyph->type = COMPOSITE_GLYPH;
1464 glyph->multibyte_p = it->multibyte_p;
1465 glyph->left_box_line_p = it->start_of_box_run_p;
1466 glyph->right_box_line_p = it->end_of_box_run_p;
1467 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1468 || it->phys_descent > it->descent);
1469 glyph->padding_p = 0;
1470 glyph->glyph_not_available_p = 0;
1471 glyph->face_id = it->face_id;
1472 glyph->u.cmp_id = it->cmp_id;
1473 ++it->glyph_row->used[area];
1478 /* Change IT->ascent and IT->height according to the setting of
1479 IT->voffset. */
1481 static INLINE void
1482 take_vertical_position_into_account (it)
1483 struct it *it;
1485 if (it->voffset)
1487 if (it->voffset < 0)
1488 /* Increase the ascent so that we can display the text higher
1489 in the line. */
1490 it->ascent += abs (it->voffset);
1491 else
1492 /* Increase the descent so that we can display the text lower
1493 in the line. */
1494 it->descent += it->voffset;
1499 /* Produce glyphs/get display metrics for the image IT is loaded with.
1500 See the description of struct display_iterator in dispextern.h for
1501 an overview of struct display_iterator. */
1503 static void
1504 x_produce_image_glyph (it)
1505 struct it *it;
1507 struct image *img;
1508 struct face *face;
1510 xassert (it->what == IT_IMAGE);
1512 face = FACE_FROM_ID (it->f, it->face_id);
1513 img = IMAGE_FROM_ID (it->f, it->image_id);
1514 xassert (img);
1516 /* Make sure X resources of the face and image are loaded. */
1517 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1518 prepare_image_for_display (it->f, img);
1520 it->ascent = it->phys_ascent = image_ascent (img, face);
1521 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1522 it->pixel_width = img->width + 2 * img->hmargin;
1524 it->nglyphs = 1;
1526 if (face->box != FACE_NO_BOX)
1528 if (face->box_line_width > 0)
1530 it->ascent += face->box_line_width;
1531 it->descent += face->box_line_width;
1534 if (it->start_of_box_run_p)
1535 it->pixel_width += abs (face->box_line_width);
1536 if (it->end_of_box_run_p)
1537 it->pixel_width += abs (face->box_line_width);
1540 take_vertical_position_into_account (it);
1542 if (it->glyph_row)
1544 struct glyph *glyph;
1545 enum glyph_row_area area = it->area;
1547 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1548 if (glyph < it->glyph_row->glyphs[area + 1])
1550 glyph->charpos = CHARPOS (it->position);
1551 glyph->object = it->object;
1552 glyph->pixel_width = it->pixel_width;
1553 glyph->voffset = it->voffset;
1554 glyph->type = IMAGE_GLYPH;
1555 glyph->multibyte_p = it->multibyte_p;
1556 glyph->left_box_line_p = it->start_of_box_run_p;
1557 glyph->right_box_line_p = it->end_of_box_run_p;
1558 glyph->overlaps_vertically_p = 0;
1559 glyph->padding_p = 0;
1560 glyph->glyph_not_available_p = 0;
1561 glyph->face_id = it->face_id;
1562 glyph->u.img_id = img->id;
1563 ++it->glyph_row->used[area];
1569 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1570 of the glyph, WIDTH and HEIGHT are the width and height of the
1571 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1572 ascent of the glyph (0 <= ASCENT <= 1). */
1574 static void
1575 x_append_stretch_glyph (it, object, width, height, ascent)
1576 struct it *it;
1577 Lisp_Object object;
1578 int width, height;
1579 double ascent;
1581 struct glyph *glyph;
1582 enum glyph_row_area area = it->area;
1584 xassert (ascent >= 0 && ascent <= 1);
1586 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1587 if (glyph < it->glyph_row->glyphs[area + 1])
1589 glyph->charpos = CHARPOS (it->position);
1590 glyph->object = object;
1591 glyph->pixel_width = width;
1592 glyph->voffset = it->voffset;
1593 glyph->type = STRETCH_GLYPH;
1594 glyph->multibyte_p = it->multibyte_p;
1595 glyph->left_box_line_p = it->start_of_box_run_p;
1596 glyph->right_box_line_p = it->end_of_box_run_p;
1597 glyph->overlaps_vertically_p = 0;
1598 glyph->padding_p = 0;
1599 glyph->glyph_not_available_p = 0;
1600 glyph->face_id = it->face_id;
1601 glyph->u.stretch.ascent = height * ascent;
1602 glyph->u.stretch.height = height;
1603 ++it->glyph_row->used[area];
1608 /* Produce a stretch glyph for iterator IT. IT->object is the value
1609 of the glyph property displayed. The value must be a list
1610 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1611 being recognized:
1613 1. `:width WIDTH' specifies that the space should be WIDTH *
1614 canonical char width wide. WIDTH may be an integer or floating
1615 point number.
1617 2. `:relative-width FACTOR' specifies that the width of the stretch
1618 should be computed from the width of the first character having the
1619 `glyph' property, and should be FACTOR times that width.
1621 3. `:align-to HPOS' specifies that the space should be wide enough
1622 to reach HPOS, a value in canonical character units.
1624 Exactly one of the above pairs must be present.
1626 4. `:height HEIGHT' specifies that the height of the stretch produced
1627 should be HEIGHT, measured in canonical character units.
1629 5. `:relative-height FACTOR' specifies that the height of the the
1630 stretch should be FACTOR times the height of the characters having
1631 the glyph property.
1633 Either none or exactly one of 4 or 5 must be present.
1635 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1636 of the stretch should be used for the ascent of the stretch.
1637 ASCENT must be in the range 0 <= ASCENT <= 100. */
1639 #define NUMVAL(X) \
1640 ((INTEGERP (X) || FLOATP (X)) \
1641 ? XFLOATINT (X) \
1642 : - 1)
1645 static void
1646 x_produce_stretch_glyph (it)
1647 struct it *it;
1649 /* (space :width WIDTH :height HEIGHT. */
1650 #if GLYPH_DEBUG
1651 extern Lisp_Object Qspace;
1652 #endif
1653 extern Lisp_Object QCwidth, QCheight, QCascent;
1654 extern Lisp_Object QCrelative_width, QCrelative_height;
1655 extern Lisp_Object QCalign_to;
1656 Lisp_Object prop, plist;
1657 double width = 0, height = 0, ascent = 0;
1658 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1659 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1661 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1663 /* List should start with `space'. */
1664 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1665 plist = XCDR (it->object);
1667 /* Compute the width of the stretch. */
1668 if (prop = Fplist_get (plist, QCwidth),
1669 NUMVAL (prop) > 0)
1670 /* Absolute width `:width WIDTH' specified and valid. */
1671 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1672 else if (prop = Fplist_get (plist, QCrelative_width),
1673 NUMVAL (prop) > 0)
1675 /* Relative width `:relative-width FACTOR' specified and valid.
1676 Compute the width of the characters having the `glyph'
1677 property. */
1678 struct it it2;
1679 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1681 it2 = *it;
1682 if (it->multibyte_p)
1684 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1685 - IT_BYTEPOS (*it));
1686 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1688 else
1689 it2.c = *p, it2.len = 1;
1691 it2.glyph_row = NULL;
1692 it2.what = IT_CHARACTER;
1693 x_produce_glyphs (&it2);
1694 width = NUMVAL (prop) * it2.pixel_width;
1696 else if (prop = Fplist_get (plist, QCalign_to),
1697 NUMVAL (prop) > 0)
1698 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1699 else
1700 /* Nothing specified -> width defaults to canonical char width. */
1701 width = CANON_X_UNIT (it->f);
1703 /* Compute height. */
1704 if (prop = Fplist_get (plist, QCheight),
1705 NUMVAL (prop) > 0)
1706 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1707 else if (prop = Fplist_get (plist, QCrelative_height),
1708 NUMVAL (prop) > 0)
1709 height = FONT_HEIGHT (font) * NUMVAL (prop);
1710 else
1711 height = FONT_HEIGHT (font);
1713 /* Compute percentage of height used for ascent. If
1714 `:ascent ASCENT' is present and valid, use that. Otherwise,
1715 derive the ascent from the font in use. */
1716 if (prop = Fplist_get (plist, QCascent),
1717 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1718 ascent = NUMVAL (prop) / 100.0;
1719 else
1720 ascent = (double) font->ascent / FONT_HEIGHT (font);
1722 if (width <= 0)
1723 width = 1;
1724 if (height <= 0)
1725 height = 1;
1727 if (it->glyph_row)
1729 Lisp_Object object = it->stack[it->sp - 1].string;
1730 if (!STRINGP (object))
1731 object = it->w->buffer;
1732 x_append_stretch_glyph (it, object, width, height, ascent);
1735 it->pixel_width = width;
1736 it->ascent = it->phys_ascent = height * ascent;
1737 it->descent = it->phys_descent = height - it->ascent;
1738 it->nglyphs = 1;
1740 if (face->box != FACE_NO_BOX)
1742 if (face->box_line_width > 0)
1744 it->ascent += face->box_line_width;
1745 it->descent += face->box_line_width;
1748 if (it->start_of_box_run_p)
1749 it->pixel_width += abs (face->box_line_width);
1750 if (it->end_of_box_run_p)
1751 it->pixel_width += abs (face->box_line_width);
1754 take_vertical_position_into_account (it);
1757 /* Return proper value to be used as baseline offset of font that has
1758 ASCENT and DESCENT to draw characters by the font at the vertical
1759 center of the line of frame F.
1761 Here, out task is to find the value of BOFF in the following figure;
1763 -------------------------+-----------+-
1764 -+-+---------+-+ | |
1765 | | | | | |
1766 | | | | F_ASCENT F_HEIGHT
1767 | | | ASCENT | |
1768 HEIGHT | | | | |
1769 | | |-|-+------+-----------|------- baseline
1770 | | | | BOFF | |
1771 | |---------|-+-+ | |
1772 | | | DESCENT | |
1773 -+-+---------+-+ F_DESCENT |
1774 -------------------------+-----------+-
1776 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1777 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1778 DESCENT = FONT->descent
1779 HEIGHT = FONT_HEIGHT (FONT)
1780 F_DESCENT = (F->output_data.x->font->descent
1781 - F->output_data.x->baseline_offset)
1782 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1785 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1786 ((FONT)->descent \
1787 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1788 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1789 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1791 /* Produce glyphs/get display metrics for the display element IT is
1792 loaded with. See the description of struct display_iterator in
1793 dispextern.h for an overview of struct display_iterator. */
1795 static void
1796 x_produce_glyphs (it)
1797 struct it *it;
1799 it->glyph_not_available_p = 0;
1801 if (it->what == IT_CHARACTER)
1803 XChar2b char2b;
1804 XFontStruct *font;
1805 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1806 XCharStruct *pcm;
1807 int font_not_found_p;
1808 struct font_info *font_info;
1809 int boff; /* baseline offset */
1810 /* We may change it->multibyte_p upon unibyte<->multibyte
1811 conversion. So, save the current value now and restore it
1812 later.
1814 Note: It seems that we don't have to record multibyte_p in
1815 struct glyph because the character code itself tells if or
1816 not the character is multibyte. Thus, in the future, we must
1817 consider eliminating the field `multibyte_p' in the struct
1818 glyph.
1820 int saved_multibyte_p = it->multibyte_p;
1822 /* Maybe translate single-byte characters to multibyte, or the
1823 other way. */
1824 it->char_to_display = it->c;
1825 if (!ASCII_BYTE_P (it->c))
1827 if (unibyte_display_via_language_environment
1828 && SINGLE_BYTE_CHAR_P (it->c)
1829 && (it->c >= 0240
1830 || !NILP (Vnonascii_translation_table)))
1832 it->char_to_display = unibyte_char_to_multibyte (it->c);
1833 it->multibyte_p = 1;
1834 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1835 face = FACE_FROM_ID (it->f, it->face_id);
1837 else if (!SINGLE_BYTE_CHAR_P (it->c)
1838 && !it->multibyte_p)
1840 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1841 it->multibyte_p = 0;
1842 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1843 face = FACE_FROM_ID (it->f, it->face_id);
1847 /* Get font to use. Encode IT->char_to_display. */
1848 x_get_char_face_and_encoding (it->f, it->char_to_display,
1849 it->face_id, &char2b,
1850 it->multibyte_p);
1851 font = face->font;
1853 /* When no suitable font found, use the default font. */
1854 font_not_found_p = font == NULL;
1855 if (font_not_found_p)
1857 font = FRAME_FONT (it->f);
1858 boff = it->f->output_data.x->baseline_offset;
1859 font_info = NULL;
1861 else
1863 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1864 boff = font_info->baseline_offset;
1865 if (font_info->vertical_centering)
1866 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1869 if (it->char_to_display >= ' '
1870 && (!it->multibyte_p || it->char_to_display < 128))
1872 /* Either unibyte or ASCII. */
1873 int stretched_p;
1875 it->nglyphs = 1;
1877 pcm = x_per_char_metric (font, &char2b);
1878 it->ascent = font->ascent + boff;
1879 it->descent = font->descent - boff;
1881 if (pcm)
1883 it->phys_ascent = pcm->ascent + boff;
1884 it->phys_descent = pcm->descent - boff;
1885 it->pixel_width = pcm->width;
1887 else
1889 it->glyph_not_available_p = 1;
1890 it->phys_ascent = font->ascent + boff;
1891 it->phys_descent = font->descent - boff;
1892 it->pixel_width = FONT_WIDTH (font);
1895 /* If this is a space inside a region of text with
1896 `space-width' property, change its width. */
1897 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1898 if (stretched_p)
1899 it->pixel_width *= XFLOATINT (it->space_width);
1901 /* If face has a box, add the box thickness to the character
1902 height. If character has a box line to the left and/or
1903 right, add the box line width to the character's width. */
1904 if (face->box != FACE_NO_BOX)
1906 int thick = face->box_line_width;
1908 if (thick > 0)
1910 it->ascent += thick;
1911 it->descent += thick;
1913 else
1914 thick = -thick;
1916 if (it->start_of_box_run_p)
1917 it->pixel_width += thick;
1918 if (it->end_of_box_run_p)
1919 it->pixel_width += thick;
1922 /* If face has an overline, add the height of the overline
1923 (1 pixel) and a 1 pixel margin to the character height. */
1924 if (face->overline_p)
1925 it->ascent += 2;
1927 take_vertical_position_into_account (it);
1929 /* If we have to actually produce glyphs, do it. */
1930 if (it->glyph_row)
1932 if (stretched_p)
1934 /* Translate a space with a `space-width' property
1935 into a stretch glyph. */
1936 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1937 x_append_stretch_glyph (it, it->object, it->pixel_width,
1938 it->ascent + it->descent, ascent);
1940 else
1941 x_append_glyph (it);
1943 /* If characters with lbearing or rbearing are displayed
1944 in this line, record that fact in a flag of the
1945 glyph row. This is used to optimize X output code. */
1946 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1947 it->glyph_row->contains_overlapping_glyphs_p = 1;
1950 else if (it->char_to_display == '\n')
1952 /* A newline has no width but we need the height of the line. */
1953 it->pixel_width = 0;
1954 it->nglyphs = 0;
1955 it->ascent = it->phys_ascent = font->ascent + boff;
1956 it->descent = it->phys_descent = font->descent - boff;
1958 if (face->box != FACE_NO_BOX
1959 && face->box_line_width > 0)
1961 it->ascent += face->box_line_width;
1962 it->descent += face->box_line_width;
1965 else if (it->char_to_display == '\t')
1967 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1968 int x = it->current_x + it->continuation_lines_width;
1969 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1971 /* If the distance from the current position to the next tab
1972 stop is less than a canonical character width, use the
1973 tab stop after that. */
1974 if (next_tab_x - x < CANON_X_UNIT (it->f))
1975 next_tab_x += tab_width;
1977 it->pixel_width = next_tab_x - x;
1978 it->nglyphs = 1;
1979 it->ascent = it->phys_ascent = font->ascent + boff;
1980 it->descent = it->phys_descent = font->descent - boff;
1982 if (it->glyph_row)
1984 double ascent = (double) it->ascent / (it->ascent + it->descent);
1985 x_append_stretch_glyph (it, it->object, it->pixel_width,
1986 it->ascent + it->descent, ascent);
1989 else
1991 /* A multi-byte character. Assume that the display width of the
1992 character is the width of the character multiplied by the
1993 width of the font. */
1995 /* If we found a font, this font should give us the right
1996 metrics. If we didn't find a font, use the frame's
1997 default font and calculate the width of the character
1998 from the charset width; this is what old redisplay code
1999 did. */
2000 pcm = x_per_char_metric (font, &char2b);
2001 if (font_not_found_p || !pcm)
2003 int charset = CHAR_CHARSET (it->char_to_display);
2005 it->glyph_not_available_p = 1;
2006 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2007 * CHARSET_WIDTH (charset));
2008 it->phys_ascent = font->ascent + boff;
2009 it->phys_descent = font->descent - boff;
2011 else
2013 it->pixel_width = pcm->width;
2014 it->phys_ascent = pcm->ascent + boff;
2015 it->phys_descent = pcm->descent - boff;
2016 if (it->glyph_row
2017 && (pcm->lbearing < 0
2018 || pcm->rbearing > pcm->width))
2019 it->glyph_row->contains_overlapping_glyphs_p = 1;
2021 it->nglyphs = 1;
2022 it->ascent = font->ascent + boff;
2023 it->descent = font->descent - boff;
2024 if (face->box != FACE_NO_BOX)
2026 int thick = face->box_line_width;
2028 if (thick > 0)
2030 it->ascent += thick;
2031 it->descent += thick;
2033 else
2034 thick = - thick;
2036 if (it->start_of_box_run_p)
2037 it->pixel_width += thick;
2038 if (it->end_of_box_run_p)
2039 it->pixel_width += thick;
2042 /* If face has an overline, add the height of the overline
2043 (1 pixel) and a 1 pixel margin to the character height. */
2044 if (face->overline_p)
2045 it->ascent += 2;
2047 take_vertical_position_into_account (it);
2049 if (it->glyph_row)
2050 x_append_glyph (it);
2052 it->multibyte_p = saved_multibyte_p;
2054 else if (it->what == IT_COMPOSITION)
2056 /* Note: A composition is represented as one glyph in the
2057 glyph matrix. There are no padding glyphs. */
2058 XChar2b char2b;
2059 XFontStruct *font;
2060 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2061 XCharStruct *pcm;
2062 int font_not_found_p;
2063 struct font_info *font_info;
2064 int boff; /* baseline offset */
2065 struct composition *cmp = composition_table[it->cmp_id];
2067 /* Maybe translate single-byte characters to multibyte. */
2068 it->char_to_display = it->c;
2069 if (unibyte_display_via_language_environment
2070 && SINGLE_BYTE_CHAR_P (it->c)
2071 && (it->c >= 0240
2072 || (it->c >= 0200
2073 && !NILP (Vnonascii_translation_table))))
2075 it->char_to_display = unibyte_char_to_multibyte (it->c);
2078 /* Get face and font to use. Encode IT->char_to_display. */
2079 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2080 face = FACE_FROM_ID (it->f, it->face_id);
2081 x_get_char_face_and_encoding (it->f, it->char_to_display,
2082 it->face_id, &char2b, it->multibyte_p);
2083 font = face->font;
2085 /* When no suitable font found, use the default font. */
2086 font_not_found_p = font == NULL;
2087 if (font_not_found_p)
2089 font = FRAME_FONT (it->f);
2090 boff = it->f->output_data.x->baseline_offset;
2091 font_info = NULL;
2093 else
2095 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2096 boff = font_info->baseline_offset;
2097 if (font_info->vertical_centering)
2098 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2101 /* There are no padding glyphs, so there is only one glyph to
2102 produce for the composition. Important is that pixel_width,
2103 ascent and descent are the values of what is drawn by
2104 draw_glyphs (i.e. the values of the overall glyphs composed). */
2105 it->nglyphs = 1;
2107 /* If we have not yet calculated pixel size data of glyphs of
2108 the composition for the current face font, calculate them
2109 now. Theoretically, we have to check all fonts for the
2110 glyphs, but that requires much time and memory space. So,
2111 here we check only the font of the first glyph. This leads
2112 to incorrect display very rarely, and C-l (recenter) can
2113 correct the display anyway. */
2114 if (cmp->font != (void *) font)
2116 /* Ascent and descent of the font of the first character of
2117 this composition (adjusted by baseline offset). Ascent
2118 and descent of overall glyphs should not be less than
2119 them respectively. */
2120 int font_ascent = font->ascent + boff;
2121 int font_descent = font->descent - boff;
2122 /* Bounding box of the overall glyphs. */
2123 int leftmost, rightmost, lowest, highest;
2124 int i, width, ascent, descent;
2126 cmp->font = (void *) font;
2128 /* Initialize the bounding box. */
2129 if (font_info
2130 && (pcm = x_per_char_metric (font, &char2b)))
2132 width = pcm->width;
2133 ascent = pcm->ascent;
2134 descent = pcm->descent;
2136 else
2138 width = FONT_WIDTH (font);
2139 ascent = font->ascent;
2140 descent = font->descent;
2143 rightmost = width;
2144 lowest = - descent + boff;
2145 highest = ascent + boff;
2146 leftmost = 0;
2148 if (font_info
2149 && font_info->default_ascent
2150 && CHAR_TABLE_P (Vuse_default_ascent)
2151 && !NILP (Faref (Vuse_default_ascent,
2152 make_number (it->char_to_display))))
2153 highest = font_info->default_ascent + boff;
2155 /* Draw the first glyph at the normal position. It may be
2156 shifted to right later if some other glyphs are drawn at
2157 the left. */
2158 cmp->offsets[0] = 0;
2159 cmp->offsets[1] = boff;
2161 /* Set cmp->offsets for the remaining glyphs. */
2162 for (i = 1; i < cmp->glyph_len; i++)
2164 int left, right, btm, top;
2165 int ch = COMPOSITION_GLYPH (cmp, i);
2166 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2168 face = FACE_FROM_ID (it->f, face_id);
2169 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2170 it->multibyte_p);
2171 font = face->font;
2172 if (font == NULL)
2174 font = FRAME_FONT (it->f);
2175 boff = it->f->output_data.x->baseline_offset;
2176 font_info = NULL;
2178 else
2180 font_info
2181 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2182 boff = font_info->baseline_offset;
2183 if (font_info->vertical_centering)
2184 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2187 if (font_info
2188 && (pcm = x_per_char_metric (font, &char2b)))
2190 width = pcm->width;
2191 ascent = pcm->ascent;
2192 descent = pcm->descent;
2194 else
2196 width = FONT_WIDTH (font);
2197 ascent = 1;
2198 descent = 0;
2201 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2203 /* Relative composition with or without
2204 alternate chars. */
2205 left = (leftmost + rightmost - width) / 2;
2206 btm = - descent + boff;
2207 if (font_info && font_info->relative_compose
2208 && (! CHAR_TABLE_P (Vignore_relative_composition)
2209 || NILP (Faref (Vignore_relative_composition,
2210 make_number (ch)))))
2213 if (- descent >= font_info->relative_compose)
2214 /* One extra pixel between two glyphs. */
2215 btm = highest + 1;
2216 else if (ascent <= 0)
2217 /* One extra pixel between two glyphs. */
2218 btm = lowest - 1 - ascent - descent;
2221 else
2223 /* A composition rule is specified by an integer
2224 value that encodes global and new reference
2225 points (GREF and NREF). GREF and NREF are
2226 specified by numbers as below:
2228 0---1---2 -- ascent
2232 9--10--11 -- center
2234 ---3---4---5--- baseline
2236 6---7---8 -- descent
2238 int rule = COMPOSITION_RULE (cmp, i);
2239 int gref, nref, grefx, grefy, nrefx, nrefy;
2241 COMPOSITION_DECODE_RULE (rule, gref, nref);
2242 grefx = gref % 3, nrefx = nref % 3;
2243 grefy = gref / 3, nrefy = nref / 3;
2245 left = (leftmost
2246 + grefx * (rightmost - leftmost) / 2
2247 - nrefx * width / 2);
2248 btm = ((grefy == 0 ? highest
2249 : grefy == 1 ? 0
2250 : grefy == 2 ? lowest
2251 : (highest + lowest) / 2)
2252 - (nrefy == 0 ? ascent + descent
2253 : nrefy == 1 ? descent - boff
2254 : nrefy == 2 ? 0
2255 : (ascent + descent) / 2));
2258 cmp->offsets[i * 2] = left;
2259 cmp->offsets[i * 2 + 1] = btm + descent;
2261 /* Update the bounding box of the overall glyphs. */
2262 right = left + width;
2263 top = btm + descent + ascent;
2264 if (left < leftmost)
2265 leftmost = left;
2266 if (right > rightmost)
2267 rightmost = right;
2268 if (top > highest)
2269 highest = top;
2270 if (btm < lowest)
2271 lowest = btm;
2274 /* If there are glyphs whose x-offsets are negative,
2275 shift all glyphs to the right and make all x-offsets
2276 non-negative. */
2277 if (leftmost < 0)
2279 for (i = 0; i < cmp->glyph_len; i++)
2280 cmp->offsets[i * 2] -= leftmost;
2281 rightmost -= leftmost;
2284 cmp->pixel_width = rightmost;
2285 cmp->ascent = highest;
2286 cmp->descent = - lowest;
2287 if (cmp->ascent < font_ascent)
2288 cmp->ascent = font_ascent;
2289 if (cmp->descent < font_descent)
2290 cmp->descent = font_descent;
2293 it->pixel_width = cmp->pixel_width;
2294 it->ascent = it->phys_ascent = cmp->ascent;
2295 it->descent = it->phys_descent = cmp->descent;
2297 if (face->box != FACE_NO_BOX)
2299 int thick = face->box_line_width;
2301 if (thick > 0)
2303 it->ascent += thick;
2304 it->descent += thick;
2306 else
2307 thick = - thick;
2309 if (it->start_of_box_run_p)
2310 it->pixel_width += thick;
2311 if (it->end_of_box_run_p)
2312 it->pixel_width += thick;
2315 /* If face has an overline, add the height of the overline
2316 (1 pixel) and a 1 pixel margin to the character height. */
2317 if (face->overline_p)
2318 it->ascent += 2;
2320 take_vertical_position_into_account (it);
2322 if (it->glyph_row)
2323 x_append_composite_glyph (it);
2325 else if (it->what == IT_IMAGE)
2326 x_produce_image_glyph (it);
2327 else if (it->what == IT_STRETCH)
2328 x_produce_stretch_glyph (it);
2330 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2331 because this isn't true for images with `:ascent 100'. */
2332 xassert (it->ascent >= 0 && it->descent >= 0);
2333 if (it->area == TEXT_AREA)
2334 it->current_x += it->pixel_width;
2336 it->descent += it->extra_line_spacing;
2338 it->max_ascent = max (it->max_ascent, it->ascent);
2339 it->max_descent = max (it->max_descent, it->descent);
2340 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2341 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2345 /* Estimate the pixel height of the mode or top line on frame F.
2346 FACE_ID specifies what line's height to estimate. */
2349 x_estimate_mode_line_height (f, face_id)
2350 struct frame *f;
2351 enum face_id face_id;
2353 int height = FONT_HEIGHT (FRAME_FONT (f));
2355 /* This function is called so early when Emacs starts that the face
2356 cache and mode line face are not yet initialized. */
2357 if (FRAME_FACE_CACHE (f))
2359 struct face *face = FACE_FROM_ID (f, face_id);
2360 if (face)
2362 if (face->font)
2363 height = FONT_HEIGHT (face->font);
2364 if (face->box_line_width > 0)
2365 height += 2 * face->box_line_width;
2369 return height;
2373 /***********************************************************************
2374 Glyph display
2375 ***********************************************************************/
2377 /* A sequence of glyphs to be drawn in the same face.
2379 This data structure is not really completely X specific, so it
2380 could possibly, at least partially, be useful for other systems. It
2381 is currently not part of the external redisplay interface because
2382 it's not clear what other systems will need. */
2384 struct glyph_string
2386 /* X-origin of the string. */
2387 int x;
2389 /* Y-origin and y-position of the base line of this string. */
2390 int y, ybase;
2392 /* The width of the string, not including a face extension. */
2393 int width;
2395 /* The width of the string, including a face extension. */
2396 int background_width;
2398 /* The height of this string. This is the height of the line this
2399 string is drawn in, and can be different from the height of the
2400 font the string is drawn in. */
2401 int height;
2403 /* Number of pixels this string overwrites in front of its x-origin.
2404 This number is zero if the string has an lbearing >= 0; it is
2405 -lbearing, if the string has an lbearing < 0. */
2406 int left_overhang;
2408 /* Number of pixels this string overwrites past its right-most
2409 nominal x-position, i.e. x + width. Zero if the string's
2410 rbearing is <= its nominal width, rbearing - width otherwise. */
2411 int right_overhang;
2413 /* The frame on which the glyph string is drawn. */
2414 struct frame *f;
2416 /* The window on which the glyph string is drawn. */
2417 struct window *w;
2419 /* X display and window for convenience. */
2420 Display *display;
2421 Window window;
2423 /* The glyph row for which this string was built. It determines the
2424 y-origin and height of the string. */
2425 struct glyph_row *row;
2427 /* The area within row. */
2428 enum glyph_row_area area;
2430 /* Characters to be drawn, and number of characters. */
2431 XChar2b *char2b;
2432 int nchars;
2434 /* A face-override for drawing cursors, mouse face and similar. */
2435 enum draw_glyphs_face hl;
2437 /* Face in which this string is to be drawn. */
2438 struct face *face;
2440 /* Font in which this string is to be drawn. */
2441 XFontStruct *font;
2443 /* Font info for this string. */
2444 struct font_info *font_info;
2446 /* Non-null means this string describes (part of) a composition.
2447 All characters from char2b are drawn composed. */
2448 struct composition *cmp;
2450 /* Index of this glyph string's first character in the glyph
2451 definition of CMP. If this is zero, this glyph string describes
2452 the first character of a composition. */
2453 int gidx;
2455 /* 1 means this glyph strings face has to be drawn to the right end
2456 of the window's drawing area. */
2457 unsigned extends_to_end_of_line_p : 1;
2459 /* 1 means the background of this string has been drawn. */
2460 unsigned background_filled_p : 1;
2462 /* 1 means glyph string must be drawn with 16-bit functions. */
2463 unsigned two_byte_p : 1;
2465 /* 1 means that the original font determined for drawing this glyph
2466 string could not be loaded. The member `font' has been set to
2467 the frame's default font in this case. */
2468 unsigned font_not_found_p : 1;
2470 /* 1 means that the face in which this glyph string is drawn has a
2471 stipple pattern. */
2472 unsigned stippled_p : 1;
2474 /* 1 means only the foreground of this glyph string must be drawn,
2475 and we should use the physical height of the line this glyph
2476 string appears in as clip rect. */
2477 unsigned for_overlaps_p : 1;
2479 /* The GC to use for drawing this glyph string. */
2480 GC gc;
2482 /* A pointer to the first glyph in the string. This glyph
2483 corresponds to char2b[0]. Needed to draw rectangles if
2484 font_not_found_p is 1. */
2485 struct glyph *first_glyph;
2487 /* Image, if any. */
2488 struct image *img;
2490 struct glyph_string *next, *prev;
2494 #if 1
2496 static void
2497 x_dump_glyph_string (s)
2498 struct glyph_string *s;
2500 fprintf (stderr, "glyph string\n");
2501 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2502 s->x, s->y, s->width, s->height);
2503 fprintf (stderr, " ybase = %d\n", s->ybase);
2504 fprintf (stderr, " hl = %d\n", s->hl);
2505 fprintf (stderr, " left overhang = %d, right = %d\n",
2506 s->left_overhang, s->right_overhang);
2507 fprintf (stderr, " nchars = %d\n", s->nchars);
2508 fprintf (stderr, " extends to end of line = %d\n",
2509 s->extends_to_end_of_line_p);
2510 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2511 fprintf (stderr, " bg width = %d\n", s->background_width);
2514 #endif /* GLYPH_DEBUG */
2518 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2519 struct glyph_string **,
2520 struct glyph_string *,
2521 struct glyph_string *));
2522 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2523 struct glyph_string **,
2524 struct glyph_string *,
2525 struct glyph_string *));
2526 static void x_append_glyph_string P_ ((struct glyph_string **,
2527 struct glyph_string **,
2528 struct glyph_string *));
2529 static int x_left_overwritten P_ ((struct glyph_string *));
2530 static int x_left_overwriting P_ ((struct glyph_string *));
2531 static int x_right_overwritten P_ ((struct glyph_string *));
2532 static int x_right_overwriting P_ ((struct glyph_string *));
2533 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2534 int));
2535 static void x_init_glyph_string P_ ((struct glyph_string *,
2536 XChar2b *, struct window *,
2537 struct glyph_row *,
2538 enum glyph_row_area, int,
2539 enum draw_glyphs_face));
2540 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2541 enum glyph_row_area, int, int,
2542 enum draw_glyphs_face, int *, int *, int));
2543 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2544 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2545 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2546 int));
2547 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2548 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2549 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2550 static void x_draw_glyph_string P_ ((struct glyph_string *));
2551 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2552 static void x_set_cursor_gc P_ ((struct glyph_string *));
2553 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2554 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2555 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2556 int *, int *));
2557 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2558 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2559 unsigned long *, double, int));
2560 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2561 double, int, unsigned long));
2562 static void x_setup_relief_colors P_ ((struct glyph_string *));
2563 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2564 static void x_draw_image_relief P_ ((struct glyph_string *));
2565 static void x_draw_image_foreground P_ ((struct glyph_string *));
2566 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2567 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2568 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2569 int, int, int));
2570 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2571 int, int, int, int, XRectangle *));
2572 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2573 int, int, int, XRectangle *));
2574 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2575 enum glyph_row_area));
2576 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2577 struct glyph_row *,
2578 enum glyph_row_area, int, int));
2580 #if GLYPH_DEBUG
2581 static void x_check_font P_ ((struct frame *, XFontStruct *));
2582 #endif
2585 /* Append the list of glyph strings with head H and tail T to the list
2586 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2588 static INLINE void
2589 x_append_glyph_string_lists (head, tail, h, t)
2590 struct glyph_string **head, **tail;
2591 struct glyph_string *h, *t;
2593 if (h)
2595 if (*head)
2596 (*tail)->next = h;
2597 else
2598 *head = h;
2599 h->prev = *tail;
2600 *tail = t;
2605 /* Prepend the list of glyph strings with head H and tail T to the
2606 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2607 result. */
2609 static INLINE void
2610 x_prepend_glyph_string_lists (head, tail, h, t)
2611 struct glyph_string **head, **tail;
2612 struct glyph_string *h, *t;
2614 if (h)
2616 if (*head)
2617 (*head)->prev = t;
2618 else
2619 *tail = t;
2620 t->next = *head;
2621 *head = h;
2626 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2627 Set *HEAD and *TAIL to the resulting list. */
2629 static INLINE void
2630 x_append_glyph_string (head, tail, s)
2631 struct glyph_string **head, **tail;
2632 struct glyph_string *s;
2634 s->next = s->prev = NULL;
2635 x_append_glyph_string_lists (head, tail, s, s);
2639 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2640 face. */
2642 static void
2643 x_set_cursor_gc (s)
2644 struct glyph_string *s;
2646 if (s->font == FRAME_FONT (s->f)
2647 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2648 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2649 && !s->cmp)
2650 s->gc = s->f->output_data.x->cursor_gc;
2651 else
2653 /* Cursor on non-default face: must merge. */
2654 XGCValues xgcv;
2655 unsigned long mask;
2657 xgcv.background = s->f->output_data.x->cursor_pixel;
2658 xgcv.foreground = s->face->background;
2660 /* If the glyph would be invisible, try a different foreground. */
2661 if (xgcv.foreground == xgcv.background)
2662 xgcv.foreground = s->face->foreground;
2663 if (xgcv.foreground == xgcv.background)
2664 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2665 if (xgcv.foreground == xgcv.background)
2666 xgcv.foreground = s->face->foreground;
2668 /* Make sure the cursor is distinct from text in this face. */
2669 if (xgcv.background == s->face->background
2670 && xgcv.foreground == s->face->foreground)
2672 xgcv.background = s->face->foreground;
2673 xgcv.foreground = s->face->background;
2676 IF_DEBUG (x_check_font (s->f, s->font));
2677 xgcv.font = s->font->fid;
2678 xgcv.graphics_exposures = False;
2679 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2681 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2682 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2683 mask, &xgcv);
2684 else
2685 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2686 = XCreateGC (s->display, s->window, mask, &xgcv);
2688 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2693 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2695 static void
2696 x_set_mouse_face_gc (s)
2697 struct glyph_string *s;
2699 int face_id;
2700 struct face *face;
2702 /* What face has to be used last for the mouse face? */
2703 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2704 face = FACE_FROM_ID (s->f, face_id);
2705 if (face == NULL)
2706 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2708 if (s->first_glyph->type == CHAR_GLYPH)
2709 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2710 else
2711 face_id = FACE_FOR_CHAR (s->f, face, 0);
2712 s->face = FACE_FROM_ID (s->f, face_id);
2713 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2715 /* If font in this face is same as S->font, use it. */
2716 if (s->font == s->face->font)
2717 s->gc = s->face->gc;
2718 else
2720 /* Otherwise construct scratch_cursor_gc with values from FACE
2721 but font FONT. */
2722 XGCValues xgcv;
2723 unsigned long mask;
2725 xgcv.background = s->face->background;
2726 xgcv.foreground = s->face->foreground;
2727 IF_DEBUG (x_check_font (s->f, s->font));
2728 xgcv.font = s->font->fid;
2729 xgcv.graphics_exposures = False;
2730 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2732 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2733 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2734 mask, &xgcv);
2735 else
2736 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2737 = XCreateGC (s->display, s->window, mask, &xgcv);
2739 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2742 xassert (s->gc != 0);
2746 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2747 Faces to use in the mode line have already been computed when the
2748 matrix was built, so there isn't much to do, here. */
2750 static INLINE void
2751 x_set_mode_line_face_gc (s)
2752 struct glyph_string *s;
2754 s->gc = s->face->gc;
2758 /* Set S->gc of glyph string S for drawing that glyph string. Set
2759 S->stippled_p to a non-zero value if the face of S has a stipple
2760 pattern. */
2762 static INLINE void
2763 x_set_glyph_string_gc (s)
2764 struct glyph_string *s;
2766 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2768 if (s->hl == DRAW_NORMAL_TEXT)
2770 s->gc = s->face->gc;
2771 s->stippled_p = s->face->stipple != 0;
2773 else if (s->hl == DRAW_INVERSE_VIDEO)
2775 x_set_mode_line_face_gc (s);
2776 s->stippled_p = s->face->stipple != 0;
2778 else if (s->hl == DRAW_CURSOR)
2780 x_set_cursor_gc (s);
2781 s->stippled_p = 0;
2783 else if (s->hl == DRAW_MOUSE_FACE)
2785 x_set_mouse_face_gc (s);
2786 s->stippled_p = s->face->stipple != 0;
2788 else if (s->hl == DRAW_IMAGE_RAISED
2789 || s->hl == DRAW_IMAGE_SUNKEN)
2791 s->gc = s->face->gc;
2792 s->stippled_p = s->face->stipple != 0;
2794 else
2796 s->gc = s->face->gc;
2797 s->stippled_p = s->face->stipple != 0;
2800 /* GC must have been set. */
2801 xassert (s->gc != 0);
2805 /* Return in *R the clipping rectangle for glyph string S. */
2807 static void
2808 x_get_glyph_string_clip_rect (s, r)
2809 struct glyph_string *s;
2810 XRectangle *r;
2812 if (s->row->full_width_p)
2814 /* Draw full-width. X coordinates are relative to S->w->left. */
2815 int canon_x = CANON_X_UNIT (s->f);
2817 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2818 r->width = XFASTINT (s->w->width) * canon_x;
2820 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2822 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2823 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2824 r->x -= width;
2827 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2829 /* Unless displaying a mode or menu bar line, which are always
2830 fully visible, clip to the visible part of the row. */
2831 if (s->w->pseudo_window_p)
2832 r->height = s->row->visible_height;
2833 else
2834 r->height = s->height;
2836 else
2838 /* This is a text line that may be partially visible. */
2839 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2840 r->width = window_box_width (s->w, s->area);
2841 r->height = s->row->visible_height;
2844 /* Don't use S->y for clipping because it doesn't take partially
2845 visible lines into account. For example, it can be negative for
2846 partially visible lines at the top of a window. */
2847 if (!s->row->full_width_p
2848 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2849 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2850 else
2851 r->y = max (0, s->row->y);
2853 /* If drawing a tool-bar window, draw it over the internal border
2854 at the top of the window. */
2855 if (s->w == XWINDOW (s->f->tool_bar_window))
2856 r->y -= s->f->output_data.x->internal_border_width;
2858 /* If S draws overlapping rows, it's sufficient to use the top and
2859 bottom of the window for clipping because this glyph string
2860 intentionally draws over other lines. */
2861 if (s->for_overlaps_p)
2863 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2864 r->height = window_text_bottom_y (s->w) - r->y;
2867 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2871 /* Set clipping for output of glyph string S. S may be part of a mode
2872 line or menu if we don't have X toolkit support. */
2874 static INLINE void
2875 x_set_glyph_string_clipping (s)
2876 struct glyph_string *s;
2878 XRectangle r;
2879 x_get_glyph_string_clip_rect (s, &r);
2880 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2884 /* Compute left and right overhang of glyph string S. If S is a glyph
2885 string for a composition, assume overhangs don't exist. */
2887 static INLINE void
2888 x_compute_glyph_string_overhangs (s)
2889 struct glyph_string *s;
2891 if (s->cmp == NULL
2892 && s->first_glyph->type == CHAR_GLYPH)
2894 XCharStruct cs;
2895 int direction, font_ascent, font_descent;
2896 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2897 &font_ascent, &font_descent, &cs);
2898 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2899 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2904 /* Compute overhangs and x-positions for glyph string S and its
2905 predecessors, or successors. X is the starting x-position for S.
2906 BACKWARD_P non-zero means process predecessors. */
2908 static void
2909 x_compute_overhangs_and_x (s, x, backward_p)
2910 struct glyph_string *s;
2911 int x;
2912 int backward_p;
2914 if (backward_p)
2916 while (s)
2918 x_compute_glyph_string_overhangs (s);
2919 x -= s->width;
2920 s->x = x;
2921 s = s->prev;
2924 else
2926 while (s)
2928 x_compute_glyph_string_overhangs (s);
2929 s->x = x;
2930 x += s->width;
2931 s = s->next;
2937 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2938 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2939 assumed to be zero. */
2941 static void
2942 x_get_glyph_overhangs (glyph, f, left, right)
2943 struct glyph *glyph;
2944 struct frame *f;
2945 int *left, *right;
2947 *left = *right = 0;
2949 if (glyph->type == CHAR_GLYPH)
2951 XFontStruct *font;
2952 struct face *face;
2953 struct font_info *font_info;
2954 XChar2b char2b;
2955 XCharStruct *pcm;
2957 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2958 font = face->font;
2959 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2960 if (font
2961 && (pcm = x_per_char_metric (font, &char2b)))
2963 if (pcm->rbearing > pcm->width)
2964 *right = pcm->rbearing - pcm->width;
2965 if (pcm->lbearing < 0)
2966 *left = -pcm->lbearing;
2972 /* Return the index of the first glyph preceding glyph string S that
2973 is overwritten by S because of S's left overhang. Value is -1
2974 if no glyphs are overwritten. */
2976 static int
2977 x_left_overwritten (s)
2978 struct glyph_string *s;
2980 int k;
2982 if (s->left_overhang)
2984 int x = 0, i;
2985 struct glyph *glyphs = s->row->glyphs[s->area];
2986 int first = s->first_glyph - glyphs;
2988 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2989 x -= glyphs[i].pixel_width;
2991 k = i + 1;
2993 else
2994 k = -1;
2996 return k;
3000 /* Return the index of the first glyph preceding glyph string S that
3001 is overwriting S because of its right overhang. Value is -1 if no
3002 glyph in front of S overwrites S. */
3004 static int
3005 x_left_overwriting (s)
3006 struct glyph_string *s;
3008 int i, k, x;
3009 struct glyph *glyphs = s->row->glyphs[s->area];
3010 int first = s->first_glyph - glyphs;
3012 k = -1;
3013 x = 0;
3014 for (i = first - 1; i >= 0; --i)
3016 int left, right;
3017 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3018 if (x + right > 0)
3019 k = i;
3020 x -= glyphs[i].pixel_width;
3023 return k;
3027 /* Return the index of the last glyph following glyph string S that is
3028 not overwritten by S because of S's right overhang. Value is -1 if
3029 no such glyph is found. */
3031 static int
3032 x_right_overwritten (s)
3033 struct glyph_string *s;
3035 int k = -1;
3037 if (s->right_overhang)
3039 int x = 0, i;
3040 struct glyph *glyphs = s->row->glyphs[s->area];
3041 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3042 int end = s->row->used[s->area];
3044 for (i = first; i < end && s->right_overhang > x; ++i)
3045 x += glyphs[i].pixel_width;
3047 k = i;
3050 return k;
3054 /* Return the index of the last glyph following glyph string S that
3055 overwrites S because of its left overhang. Value is negative
3056 if no such glyph is found. */
3058 static int
3059 x_right_overwriting (s)
3060 struct glyph_string *s;
3062 int i, k, x;
3063 int end = s->row->used[s->area];
3064 struct glyph *glyphs = s->row->glyphs[s->area];
3065 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3067 k = -1;
3068 x = 0;
3069 for (i = first; i < end; ++i)
3071 int left, right;
3072 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3073 if (x - left < 0)
3074 k = i;
3075 x += glyphs[i].pixel_width;
3078 return k;
3082 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3084 static INLINE void
3085 x_clear_glyph_string_rect (s, x, y, w, h)
3086 struct glyph_string *s;
3087 int x, y, w, h;
3089 XGCValues xgcv;
3090 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3091 XSetForeground (s->display, s->gc, xgcv.background);
3092 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3093 XSetForeground (s->display, s->gc, xgcv.foreground);
3097 /* Draw the background of glyph_string S. If S->background_filled_p
3098 is non-zero don't draw it. FORCE_P non-zero means draw the
3099 background even if it wouldn't be drawn normally. This is used
3100 when a string preceding S draws into the background of S, or S
3101 contains the first component of a composition. */
3103 static void
3104 x_draw_glyph_string_background (s, force_p)
3105 struct glyph_string *s;
3106 int force_p;
3108 /* Nothing to do if background has already been drawn or if it
3109 shouldn't be drawn in the first place. */
3110 if (!s->background_filled_p)
3112 int box_line_width = max (s->face->box_line_width, 0);
3114 if (s->stippled_p)
3116 /* Fill background with a stipple pattern. */
3117 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3118 XFillRectangle (s->display, s->window, s->gc, s->x,
3119 s->y + box_line_width,
3120 s->background_width,
3121 s->height - 2 * box_line_width);
3122 XSetFillStyle (s->display, s->gc, FillSolid);
3123 s->background_filled_p = 1;
3125 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3126 || s->font_not_found_p
3127 || s->extends_to_end_of_line_p
3128 || force_p)
3130 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3131 s->background_width,
3132 s->height - 2 * box_line_width);
3133 s->background_filled_p = 1;
3139 /* Draw the foreground of glyph string S. */
3141 static void
3142 x_draw_glyph_string_foreground (s)
3143 struct glyph_string *s;
3145 int i, x;
3147 /* If first glyph of S has a left box line, start drawing the text
3148 of S to the right of that box line. */
3149 if (s->face->box != FACE_NO_BOX
3150 && s->first_glyph->left_box_line_p)
3151 x = s->x + abs (s->face->box_line_width);
3152 else
3153 x = s->x;
3155 /* Draw characters of S as rectangles if S's font could not be
3156 loaded. */
3157 if (s->font_not_found_p)
3159 for (i = 0; i < s->nchars; ++i)
3161 struct glyph *g = s->first_glyph + i;
3162 XDrawRectangle (s->display, s->window,
3163 s->gc, x, s->y, g->pixel_width - 1,
3164 s->height - 1);
3165 x += g->pixel_width;
3168 else
3170 char *char1b = (char *) s->char2b;
3171 int boff = s->font_info->baseline_offset;
3173 if (s->font_info->vertical_centering)
3174 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3176 /* If we can use 8-bit functions, condense S->char2b. */
3177 if (!s->two_byte_p)
3178 for (i = 0; i < s->nchars; ++i)
3179 char1b[i] = s->char2b[i].byte2;
3181 /* Draw text with XDrawString if background has already been
3182 filled. Otherwise, use XDrawImageString. (Note that
3183 XDrawImageString is usually faster than XDrawString.) Always
3184 use XDrawImageString when drawing the cursor so that there is
3185 no chance that characters under a box cursor are invisible. */
3186 if (s->for_overlaps_p
3187 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3189 /* Draw characters with 16-bit or 8-bit functions. */
3190 if (s->two_byte_p)
3191 XDrawString16 (s->display, s->window, s->gc, x,
3192 s->ybase - boff, s->char2b, s->nchars);
3193 else
3194 XDrawString (s->display, s->window, s->gc, x,
3195 s->ybase - boff, char1b, s->nchars);
3197 else
3199 if (s->two_byte_p)
3200 XDrawImageString16 (s->display, s->window, s->gc, x,
3201 s->ybase - boff, s->char2b, s->nchars);
3202 else
3203 XDrawImageString (s->display, s->window, s->gc, x,
3204 s->ybase - boff, char1b, s->nchars);
3209 /* Draw the foreground of composite glyph string S. */
3211 static void
3212 x_draw_composite_glyph_string_foreground (s)
3213 struct glyph_string *s;
3215 int i, x;
3217 /* If first glyph of S has a left box line, start drawing the text
3218 of S to the right of that box line. */
3219 if (s->face->box != FACE_NO_BOX
3220 && s->first_glyph->left_box_line_p)
3221 x = s->x + abs (s->face->box_line_width);
3222 else
3223 x = s->x;
3225 /* S is a glyph string for a composition. S->gidx is the index of
3226 the first character drawn for glyphs of this composition.
3227 S->gidx == 0 means we are drawing the very first character of
3228 this composition. */
3230 /* Draw a rectangle for the composition if the font for the very
3231 first character of the composition could not be loaded. */
3232 if (s->font_not_found_p)
3234 if (s->gidx == 0)
3235 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3236 s->width - 1, s->height - 1);
3238 else
3240 for (i = 0; i < s->nchars; i++, ++s->gidx)
3241 XDrawString16 (s->display, s->window, s->gc,
3242 x + s->cmp->offsets[s->gidx * 2],
3243 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3244 s->char2b + i, 1);
3249 #ifdef USE_X_TOOLKIT
3251 static struct frame *x_frame_of_widget P_ ((Widget));
3252 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3253 XrmValue *, XrmValue *, XtPointer *));
3254 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3255 XrmValue *, Cardinal *));
3258 /* Return the frame on which widget WIDGET is used.. Abort if frame
3259 cannot be determined. */
3261 static struct frame *
3262 x_frame_of_widget (widget)
3263 Widget widget;
3265 struct x_display_info *dpyinfo;
3266 Lisp_Object tail;
3267 struct frame *f;
3269 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3271 /* Find the top-level shell of the widget. Note that this function
3272 can be called when the widget is not yet realized, so XtWindow
3273 (widget) == 0. That's the reason we can't simply use
3274 x_any_window_to_frame. */
3275 while (!XtIsTopLevelShell (widget))
3276 widget = XtParent (widget);
3278 /* Look for a frame with that top-level widget. Allocate the color
3279 on that frame to get the right gamma correction value. */
3280 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3281 if (GC_FRAMEP (XCAR (tail))
3282 && (f = XFRAME (XCAR (tail)),
3283 (f->output_data.nothing != 1
3284 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3285 && f->output_data.x->widget == widget)
3286 return f;
3288 abort ();
3292 /* Allocate the color COLOR->pixel on the screen and display of
3293 widget WIDGET in colormap CMAP. If an exact match cannot be
3294 allocated, try the nearest color available. Value is non-zero
3295 if successful. This is called from lwlib. */
3298 x_alloc_nearest_color_for_widget (widget, cmap, color)
3299 Widget widget;
3300 Colormap cmap;
3301 XColor *color;
3303 struct frame *f = x_frame_of_widget (widget);
3304 return x_alloc_nearest_color (f, cmap, color);
3308 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3309 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3310 If this produces the same color as PIXEL, try a color where all RGB
3311 values have DELTA added. Return the allocated color in *PIXEL.
3312 DISPLAY is the X display, CMAP is the colormap to operate on.
3313 Value is non-zero if successful. */
3316 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3317 Widget widget;
3318 Display *display;
3319 Colormap cmap;
3320 unsigned long *pixel;
3321 double factor;
3322 int delta;
3324 struct frame *f = x_frame_of_widget (widget);
3325 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3329 /* Structure specifying which arguments should be passed by Xt to
3330 cvt_string_to_pixel. We want the widget's screen and colormap. */
3332 static XtConvertArgRec cvt_string_to_pixel_args[] =
3334 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3335 sizeof (Screen *)},
3336 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3337 sizeof (Colormap)}
3341 /* The address of this variable is returned by
3342 cvt_string_to_pixel. */
3344 static Pixel cvt_string_to_pixel_value;
3347 /* Convert a color name to a pixel color.
3349 DPY is the display we are working on.
3351 ARGS is an array of *NARGS XrmValue structures holding additional
3352 information about the widget for which the conversion takes place.
3353 The contents of this array are determined by the specification
3354 in cvt_string_to_pixel_args.
3356 FROM is a pointer to an XrmValue which points to the color name to
3357 convert. TO is an XrmValue in which to return the pixel color.
3359 CLOSURE_RET is a pointer to user-data, in which we record if
3360 we allocated the color or not.
3362 Value is True if successful, False otherwise. */
3364 static Boolean
3365 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3366 Display *dpy;
3367 XrmValue *args;
3368 Cardinal *nargs;
3369 XrmValue *from, *to;
3370 XtPointer *closure_ret;
3372 Screen *screen;
3373 Colormap cmap;
3374 Pixel pixel;
3375 String color_name;
3376 XColor color;
3378 if (*nargs != 2)
3380 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3381 "wrongParameters", "cvt_string_to_pixel",
3382 "XtToolkitError",
3383 "Screen and colormap args required", NULL, NULL);
3384 return False;
3387 screen = *(Screen **) args[0].addr;
3388 cmap = *(Colormap *) args[1].addr;
3389 color_name = (String) from->addr;
3391 if (strcmp (color_name, XtDefaultBackground) == 0)
3393 *closure_ret = (XtPointer) False;
3394 pixel = WhitePixelOfScreen (screen);
3396 else if (strcmp (color_name, XtDefaultForeground) == 0)
3398 *closure_ret = (XtPointer) False;
3399 pixel = BlackPixelOfScreen (screen);
3401 else if (XParseColor (dpy, cmap, color_name, &color)
3402 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3404 pixel = color.pixel;
3405 *closure_ret = (XtPointer) True;
3407 else
3409 String params[1];
3410 Cardinal nparams = 1;
3412 params[0] = color_name;
3413 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3414 "badValue", "cvt_string_to_pixel",
3415 "XtToolkitError", "Invalid color `%s'",
3416 params, &nparams);
3417 return False;
3420 if (to->addr != NULL)
3422 if (to->size < sizeof (Pixel))
3424 to->size = sizeof (Pixel);
3425 return False;
3428 *(Pixel *) to->addr = pixel;
3430 else
3432 cvt_string_to_pixel_value = pixel;
3433 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3436 to->size = sizeof (Pixel);
3437 return True;
3441 /* Free a pixel color which was previously allocated via
3442 cvt_string_to_pixel. This is registered as the destructor
3443 for this type of resource via XtSetTypeConverter.
3445 APP is the application context in which we work.
3447 TO is a pointer to an XrmValue holding the color to free.
3448 CLOSURE is the value we stored in CLOSURE_RET for this color
3449 in cvt_string_to_pixel.
3451 ARGS and NARGS are like for cvt_string_to_pixel. */
3453 static void
3454 cvt_pixel_dtor (app, to, closure, args, nargs)
3455 XtAppContext app;
3456 XrmValuePtr to;
3457 XtPointer closure;
3458 XrmValuePtr args;
3459 Cardinal *nargs;
3461 if (*nargs != 2)
3463 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3464 "XtToolkitError",
3465 "Screen and colormap arguments required",
3466 NULL, NULL);
3468 else if (closure != NULL)
3470 /* We did allocate the pixel, so free it. */
3471 Screen *screen = *(Screen **) args[0].addr;
3472 Colormap cmap = *(Colormap *) args[1].addr;
3473 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3474 (Pixel *) to->addr, 1, 0);
3479 #endif /* USE_X_TOOLKIT */
3482 /* Value is an array of XColor structures for the contents of the
3483 color map of display DPY. Set *NCELLS to the size of the array.
3484 Note that this probably shouldn't be called for large color maps,
3485 say a 24-bit TrueColor map. */
3487 static const XColor *
3488 x_color_cells (dpy, ncells)
3489 Display *dpy;
3490 int *ncells;
3492 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3494 if (dpyinfo->color_cells == NULL)
3496 Screen *screen = dpyinfo->screen;
3497 int i;
3499 dpyinfo->ncolor_cells
3500 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3501 dpyinfo->color_cells
3502 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3503 * sizeof *dpyinfo->color_cells);
3505 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3506 dpyinfo->color_cells[i].pixel = i;
3508 XQueryColors (dpy, dpyinfo->cmap,
3509 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3512 *ncells = dpyinfo->ncolor_cells;
3513 return dpyinfo->color_cells;
3517 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3518 colors in COLORS. Use cached information, if available. */
3520 void
3521 x_query_colors (f, colors, ncolors)
3522 struct frame *f;
3523 XColor *colors;
3524 int ncolors;
3526 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3528 if (dpyinfo->color_cells)
3530 int i;
3531 for (i = 0; i < ncolors; ++i)
3533 unsigned long pixel = colors[i].pixel;
3534 xassert (pixel < dpyinfo->ncolor_cells);
3535 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3536 colors[i] = dpyinfo->color_cells[pixel];
3539 else
3540 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3544 /* On frame F, translate pixel color to RGB values for the color in
3545 COLOR. Use cached information, if available. */
3547 void
3548 x_query_color (f, color)
3549 struct frame *f;
3550 XColor *color;
3552 x_query_colors (f, color, 1);
3556 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3557 exact match can't be allocated, try the nearest color available.
3558 Value is non-zero if successful. Set *COLOR to the color
3559 allocated. */
3561 static int
3562 x_alloc_nearest_color_1 (dpy, cmap, color)
3563 Display *dpy;
3564 Colormap cmap;
3565 XColor *color;
3567 int rc;
3569 rc = XAllocColor (dpy, cmap, color);
3570 if (rc == 0)
3572 /* If we got to this point, the colormap is full, so we're going
3573 to try to get the next closest color. The algorithm used is
3574 a least-squares matching, which is what X uses for closest
3575 color matching with StaticColor visuals. */
3576 int nearest, i;
3577 unsigned long nearest_delta = ~0;
3578 int ncells;
3579 const XColor *cells = x_color_cells (dpy, &ncells);
3581 for (nearest = i = 0; i < ncells; ++i)
3583 long dred = (color->red >> 8) - (cells[i].red >> 8);
3584 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3585 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3586 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3588 if (delta < nearest_delta)
3590 nearest = i;
3591 nearest_delta = delta;
3595 color->red = cells[nearest].red;
3596 color->green = cells[nearest].green;
3597 color->blue = cells[nearest].blue;
3598 rc = XAllocColor (dpy, cmap, color);
3600 else
3602 /* If allocation succeeded, and the allocated pixel color is not
3603 equal to a cached pixel color recorded earlier, there was a
3604 change in the colormap, so clear the color cache. */
3605 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3606 XColor *cached_color;
3608 if (dpyinfo->color_cells
3609 && (cached_color = &dpyinfo->color_cells[color->pixel],
3610 (cached_color->red != color->red
3611 || cached_color->blue != color->blue
3612 || cached_color->green != color->green)))
3614 xfree (dpyinfo->color_cells);
3615 dpyinfo->color_cells = NULL;
3616 dpyinfo->ncolor_cells = 0;
3620 #ifdef DEBUG_X_COLORS
3621 if (rc)
3622 register_color (color->pixel);
3623 #endif /* DEBUG_X_COLORS */
3625 return rc;
3629 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3630 exact match can't be allocated, try the nearest color available.
3631 Value is non-zero if successful. Set *COLOR to the color
3632 allocated. */
3635 x_alloc_nearest_color (f, cmap, color)
3636 struct frame *f;
3637 Colormap cmap;
3638 XColor *color;
3640 gamma_correct (f, color);
3641 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3645 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3646 It's necessary to do this instead of just using PIXEL directly to
3647 get color reference counts right. */
3649 unsigned long
3650 x_copy_color (f, pixel)
3651 struct frame *f;
3652 unsigned long pixel;
3654 XColor color;
3656 color.pixel = pixel;
3657 BLOCK_INPUT;
3658 x_query_color (f, &color);
3659 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3660 UNBLOCK_INPUT;
3661 #ifdef DEBUG_X_COLORS
3662 register_color (pixel);
3663 #endif
3664 return color.pixel;
3668 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3669 It's necessary to do this instead of just using PIXEL directly to
3670 get color reference counts right. */
3672 unsigned long
3673 x_copy_dpy_color (dpy, cmap, pixel)
3674 Display *dpy;
3675 Colormap cmap;
3676 unsigned long pixel;
3678 XColor color;
3680 color.pixel = pixel;
3681 BLOCK_INPUT;
3682 XQueryColor (dpy, cmap, &color);
3683 XAllocColor (dpy, cmap, &color);
3684 UNBLOCK_INPUT;
3685 #ifdef DEBUG_X_COLORS
3686 register_color (pixel);
3687 #endif
3688 return color.pixel;
3692 /* Brightness beyond which a color won't have its highlight brightness
3693 boosted.
3695 Nominally, highlight colors for `3d' faces are calculated by
3696 brightening an object's color by a constant scale factor, but this
3697 doesn't yield good results for dark colors, so for colors who's
3698 brightness is less than this value (on a scale of 0-65535) have an
3699 use an additional additive factor.
3701 The value here is set so that the default menu-bar/mode-line color
3702 (grey75) will not have its highlights changed at all. */
3703 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3706 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3707 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3708 If this produces the same color as PIXEL, try a color where all RGB
3709 values have DELTA added. Return the allocated color in *PIXEL.
3710 DISPLAY is the X display, CMAP is the colormap to operate on.
3711 Value is non-zero if successful. */
3713 static int
3714 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3715 struct frame *f;
3716 Display *display;
3717 Colormap cmap;
3718 unsigned long *pixel;
3719 double factor;
3720 int delta;
3722 XColor color, new;
3723 long bright;
3724 int success_p;
3726 /* Get RGB color values. */
3727 color.pixel = *pixel;
3728 x_query_color (f, &color);
3730 /* Change RGB values by specified FACTOR. Avoid overflow! */
3731 xassert (factor >= 0);
3732 new.red = min (0xffff, factor * color.red);
3733 new.green = min (0xffff, factor * color.green);
3734 new.blue = min (0xffff, factor * color.blue);
3736 /* Calculate brightness of COLOR. */
3737 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3739 /* We only boost colors that are darker than
3740 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3741 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3742 /* Make an additive adjustment to NEW, because it's dark enough so
3743 that scaling by FACTOR alone isn't enough. */
3745 /* How far below the limit this color is (0 - 1, 1 being darker). */
3746 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3747 /* The additive adjustment. */
3748 int min_delta = delta * dimness * factor / 2;
3750 if (factor < 1)
3752 new.red = max (0, new.red - min_delta);
3753 new.green = max (0, new.green - min_delta);
3754 new.blue = max (0, new.blue - min_delta);
3756 else
3758 new.red = min (0xffff, min_delta + new.red);
3759 new.green = min (0xffff, min_delta + new.green);
3760 new.blue = min (0xffff, min_delta + new.blue);
3764 /* Try to allocate the color. */
3765 success_p = x_alloc_nearest_color (f, cmap, &new);
3766 if (success_p)
3768 if (new.pixel == *pixel)
3770 /* If we end up with the same color as before, try adding
3771 delta to the RGB values. */
3772 x_free_colors (f, &new.pixel, 1);
3774 new.red = min (0xffff, delta + color.red);
3775 new.green = min (0xffff, delta + color.green);
3776 new.blue = min (0xffff, delta + color.blue);
3777 success_p = x_alloc_nearest_color (f, cmap, &new);
3779 else
3780 success_p = 1;
3781 *pixel = new.pixel;
3784 return success_p;
3788 /* Set up the foreground color for drawing relief lines of glyph
3789 string S. RELIEF is a pointer to a struct relief containing the GC
3790 with which lines will be drawn. Use a color that is FACTOR or
3791 DELTA lighter or darker than the relief's background which is found
3792 in S->f->output_data.x->relief_background. If such a color cannot
3793 be allocated, use DEFAULT_PIXEL, instead. */
3795 static void
3796 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3797 struct frame *f;
3798 struct relief *relief;
3799 double factor;
3800 int delta;
3801 unsigned long default_pixel;
3803 XGCValues xgcv;
3804 struct x_output *di = f->output_data.x;
3805 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3806 unsigned long pixel;
3807 unsigned long background = di->relief_background;
3808 Colormap cmap = FRAME_X_COLORMAP (f);
3809 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3810 Display *dpy = FRAME_X_DISPLAY (f);
3812 xgcv.graphics_exposures = False;
3813 xgcv.line_width = 1;
3815 /* Free previously allocated color. The color cell will be reused
3816 when it has been freed as many times as it was allocated, so this
3817 doesn't affect faces using the same colors. */
3818 if (relief->gc
3819 && relief->allocated_p)
3821 x_free_colors (f, &relief->pixel, 1);
3822 relief->allocated_p = 0;
3825 /* Allocate new color. */
3826 xgcv.foreground = default_pixel;
3827 pixel = background;
3828 if (dpyinfo->n_planes != 1
3829 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3831 relief->allocated_p = 1;
3832 xgcv.foreground = relief->pixel = pixel;
3835 if (relief->gc == 0)
3837 xgcv.stipple = dpyinfo->gray;
3838 mask |= GCStipple;
3839 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3841 else
3842 XChangeGC (dpy, relief->gc, mask, &xgcv);
3846 /* Set up colors for the relief lines around glyph string S. */
3848 static void
3849 x_setup_relief_colors (s)
3850 struct glyph_string *s;
3852 struct x_output *di = s->f->output_data.x;
3853 unsigned long color;
3855 if (s->face->use_box_color_for_shadows_p)
3856 color = s->face->box_color;
3857 else
3859 XGCValues xgcv;
3861 /* Get the background color of the face. */
3862 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3863 color = xgcv.background;
3866 if (di->white_relief.gc == 0
3867 || color != di->relief_background)
3869 di->relief_background = color;
3870 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3871 WHITE_PIX_DEFAULT (s->f));
3872 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3873 BLACK_PIX_DEFAULT (s->f));
3878 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3879 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3880 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3881 relief. LEFT_P non-zero means draw a relief on the left side of
3882 the rectangle. RIGHT_P non-zero means draw a relief on the right
3883 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3884 when drawing. */
3886 static void
3887 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3888 raised_p, left_p, right_p, clip_rect)
3889 struct frame *f;
3890 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3891 XRectangle *clip_rect;
3893 int i;
3894 GC gc;
3896 if (raised_p)
3897 gc = f->output_data.x->white_relief.gc;
3898 else
3899 gc = f->output_data.x->black_relief.gc;
3900 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3902 /* Top. */
3903 for (i = 0; i < width; ++i)
3904 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3905 left_x + i * left_p, top_y + i,
3906 right_x + 1 - i * right_p, top_y + i);
3908 /* Left. */
3909 if (left_p)
3910 for (i = 0; i < width; ++i)
3911 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3912 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3914 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3915 if (raised_p)
3916 gc = f->output_data.x->black_relief.gc;
3917 else
3918 gc = f->output_data.x->white_relief.gc;
3919 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3921 /* Bottom. */
3922 for (i = 0; i < width; ++i)
3923 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3924 left_x + i * left_p + 1, bottom_y - i,
3925 right_x + 1 - i * right_p, bottom_y - i);
3927 /* Right. */
3928 if (right_p)
3929 for (i = 0; i < width; ++i)
3930 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3931 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3933 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3937 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3938 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3939 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3940 left side of the rectangle. RIGHT_P non-zero means draw a line
3941 on the right side of the rectangle. CLIP_RECT is the clipping
3942 rectangle to use when drawing. */
3944 static void
3945 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3946 left_p, right_p, clip_rect)
3947 struct glyph_string *s;
3948 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3949 XRectangle *clip_rect;
3951 XGCValues xgcv;
3953 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3954 XSetForeground (s->display, s->gc, s->face->box_color);
3955 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3957 /* Top. */
3958 XFillRectangle (s->display, s->window, s->gc,
3959 left_x, top_y, right_x - left_x + 1, width);
3961 /* Left. */
3962 if (left_p)
3963 XFillRectangle (s->display, s->window, s->gc,
3964 left_x, top_y, width, bottom_y - top_y + 1);
3966 /* Bottom. */
3967 XFillRectangle (s->display, s->window, s->gc,
3968 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3970 /* Right. */
3971 if (right_p)
3972 XFillRectangle (s->display, s->window, s->gc,
3973 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3975 XSetForeground (s->display, s->gc, xgcv.foreground);
3976 XSetClipMask (s->display, s->gc, None);
3980 /* Draw a box around glyph string S. */
3982 static void
3983 x_draw_glyph_string_box (s)
3984 struct glyph_string *s;
3986 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3987 int left_p, right_p;
3988 struct glyph *last_glyph;
3989 XRectangle clip_rect;
3991 last_x = window_box_right (s->w, s->area);
3992 if (s->row->full_width_p
3993 && !s->w->pseudo_window_p)
3995 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3996 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3997 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4000 /* The glyph that may have a right box line. */
4001 last_glyph = (s->cmp || s->img
4002 ? s->first_glyph
4003 : s->first_glyph + s->nchars - 1);
4005 width = abs (s->face->box_line_width);
4006 raised_p = s->face->box == FACE_RAISED_BOX;
4007 left_x = s->x;
4008 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
4009 ? last_x - 1
4010 : min (last_x, s->x + s->background_width) - 1);
4011 top_y = s->y;
4012 bottom_y = top_y + s->height - 1;
4014 left_p = (s->first_glyph->left_box_line_p
4015 || (s->hl == DRAW_MOUSE_FACE
4016 && (s->prev == NULL
4017 || s->prev->hl != s->hl)));
4018 right_p = (last_glyph->right_box_line_p
4019 || (s->hl == DRAW_MOUSE_FACE
4020 && (s->next == NULL
4021 || s->next->hl != s->hl)));
4023 x_get_glyph_string_clip_rect (s, &clip_rect);
4025 if (s->face->box == FACE_SIMPLE_BOX)
4026 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4027 left_p, right_p, &clip_rect);
4028 else
4030 x_setup_relief_colors (s);
4031 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4032 width, raised_p, left_p, right_p, &clip_rect);
4037 /* Draw foreground of image glyph string S. */
4039 static void
4040 x_draw_image_foreground (s)
4041 struct glyph_string *s;
4043 int x;
4044 int y = s->ybase - image_ascent (s->img, s->face);
4046 /* If first glyph of S has a left box line, start drawing it to the
4047 right of that line. */
4048 if (s->face->box != FACE_NO_BOX
4049 && s->first_glyph->left_box_line_p)
4050 x = s->x + abs (s->face->box_line_width);
4051 else
4052 x = s->x;
4054 /* If there is a margin around the image, adjust x- and y-position
4055 by that margin. */
4056 x += s->img->hmargin;
4057 y += s->img->vmargin;
4059 if (s->img->pixmap)
4061 if (s->img->mask)
4063 /* We can't set both a clip mask and use XSetClipRectangles
4064 because the latter also sets a clip mask. We also can't
4065 trust on the shape extension to be available
4066 (XShapeCombineRegion). So, compute the rectangle to draw
4067 manually. */
4068 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4069 | GCFunction);
4070 XGCValues xgcv;
4071 XRectangle clip_rect, image_rect, r;
4073 xgcv.clip_mask = s->img->mask;
4074 xgcv.clip_x_origin = x;
4075 xgcv.clip_y_origin = y;
4076 xgcv.function = GXcopy;
4077 XChangeGC (s->display, s->gc, mask, &xgcv);
4079 x_get_glyph_string_clip_rect (s, &clip_rect);
4080 image_rect.x = x;
4081 image_rect.y = y;
4082 image_rect.width = s->img->width;
4083 image_rect.height = s->img->height;
4084 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4085 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4086 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4088 else
4090 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
4091 XGCValues xgcv;
4092 XRectangle clip_rect, image_rect, r;
4094 x_get_glyph_string_clip_rect (s, &clip_rect);
4095 image_rect.x = x;
4096 image_rect.y = y;
4097 image_rect.width = s->img->width;
4098 image_rect.height = s->img->height;
4099 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4100 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4101 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4103 /* When the image has a mask, we can expect that at
4104 least part of a mouse highlight or a block cursor will
4105 be visible. If the image doesn't have a mask, make
4106 a block cursor visible by drawing a rectangle around
4107 the image. I believe it's looking better if we do
4108 nothing here for mouse-face. */
4109 if (s->hl == DRAW_CURSOR)
4110 XDrawRectangle (s->display, s->window, s->gc, x, y,
4111 s->img->width - 1, s->img->height - 1);
4114 else
4115 /* Draw a rectangle if image could not be loaded. */
4116 XDrawRectangle (s->display, s->window, s->gc, x, y,
4117 s->img->width - 1, s->img->height - 1);
4121 /* Draw a relief around the image glyph string S. */
4123 static void
4124 x_draw_image_relief (s)
4125 struct glyph_string *s;
4127 int x0, y0, x1, y1, thick, raised_p;
4128 XRectangle r;
4129 int x;
4130 int y = s->ybase - image_ascent (s->img, s->face);
4132 /* If first glyph of S has a left box line, start drawing it to the
4133 right of that line. */
4134 if (s->face->box != FACE_NO_BOX
4135 && s->first_glyph->left_box_line_p)
4136 x = s->x + abs (s->face->box_line_width);
4137 else
4138 x = s->x;
4140 /* If there is a margin around the image, adjust x- and y-position
4141 by that margin. */
4142 x += s->img->hmargin;
4143 y += s->img->vmargin;
4145 if (s->hl == DRAW_IMAGE_SUNKEN
4146 || s->hl == DRAW_IMAGE_RAISED)
4148 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
4149 raised_p = s->hl == DRAW_IMAGE_RAISED;
4151 else
4153 thick = abs (s->img->relief);
4154 raised_p = s->img->relief > 0;
4157 x0 = x - thick;
4158 y0 = y - thick;
4159 x1 = x + s->img->width + thick - 1;
4160 y1 = y + s->img->height + thick - 1;
4162 x_setup_relief_colors (s);
4163 x_get_glyph_string_clip_rect (s, &r);
4164 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4168 /* Draw the foreground of image glyph string S to PIXMAP. */
4170 static void
4171 x_draw_image_foreground_1 (s, pixmap)
4172 struct glyph_string *s;
4173 Pixmap pixmap;
4175 int x;
4176 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4178 /* If first glyph of S has a left box line, start drawing it to the
4179 right of that line. */
4180 if (s->face->box != FACE_NO_BOX
4181 && s->first_glyph->left_box_line_p)
4182 x = abs (s->face->box_line_width);
4183 else
4184 x = 0;
4186 /* If there is a margin around the image, adjust x- and y-position
4187 by that margin. */
4188 x += s->img->hmargin;
4189 y += s->img->vmargin;
4191 if (s->img->pixmap)
4193 if (s->img->mask)
4195 /* We can't set both a clip mask and use XSetClipRectangles
4196 because the latter also sets a clip mask. We also can't
4197 trust on the shape extension to be available
4198 (XShapeCombineRegion). So, compute the rectangle to draw
4199 manually. */
4200 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4201 | GCFunction);
4202 XGCValues xgcv;
4204 xgcv.clip_mask = s->img->mask;
4205 xgcv.clip_x_origin = x;
4206 xgcv.clip_y_origin = y;
4207 xgcv.function = GXcopy;
4208 XChangeGC (s->display, s->gc, mask, &xgcv);
4210 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4211 0, 0, s->img->width, s->img->height, x, y);
4212 XSetClipMask (s->display, s->gc, None);
4214 else
4216 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4217 0, 0, s->img->width, s->img->height, x, y);
4219 /* When the image has a mask, we can expect that at
4220 least part of a mouse highlight or a block cursor will
4221 be visible. If the image doesn't have a mask, make
4222 a block cursor visible by drawing a rectangle around
4223 the image. I believe it's looking better if we do
4224 nothing here for mouse-face. */
4225 if (s->hl == DRAW_CURSOR)
4226 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4227 s->img->width - 1, s->img->height - 1);
4230 else
4231 /* Draw a rectangle if image could not be loaded. */
4232 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4233 s->img->width - 1, s->img->height - 1);
4237 /* Draw part of the background of glyph string S. X, Y, W, and H
4238 give the rectangle to draw. */
4240 static void
4241 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4242 struct glyph_string *s;
4243 int x, y, w, h;
4245 if (s->stippled_p)
4247 /* Fill background with a stipple pattern. */
4248 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4249 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4250 XSetFillStyle (s->display, s->gc, FillSolid);
4252 else
4253 x_clear_glyph_string_rect (s, x, y, w, h);
4257 /* Draw image glyph string S.
4259 s->y
4260 s->x +-------------------------
4261 | s->face->box
4263 | +-------------------------
4264 | | s->img->margin
4266 | | +-------------------
4267 | | | the image
4271 static void
4272 x_draw_image_glyph_string (s)
4273 struct glyph_string *s;
4275 int x, y;
4276 int box_line_hwidth = abs (s->face->box_line_width);
4277 int box_line_vwidth = max (s->face->box_line_width, 0);
4278 int height;
4279 Pixmap pixmap = None;
4281 height = s->height - 2 * box_line_vwidth;
4283 /* Fill background with face under the image. Do it only if row is
4284 taller than image or if image has a clip mask to reduce
4285 flickering. */
4286 s->stippled_p = s->face->stipple != 0;
4287 if (height > s->img->height
4288 || s->img->hmargin
4289 || s->img->vmargin
4290 || s->img->mask
4291 || s->img->pixmap == 0
4292 || s->width != s->background_width)
4294 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4295 x = s->x + box_line_hwidth;
4296 else
4297 x = s->x;
4299 y = s->y + box_line_vwidth;
4301 if (s->img->mask)
4303 /* Create a pixmap as large as the glyph string. Fill it
4304 with the background color. Copy the image to it, using
4305 its mask. Copy the temporary pixmap to the display. */
4306 Screen *screen = FRAME_X_SCREEN (s->f);
4307 int depth = DefaultDepthOfScreen (screen);
4309 /* Create a pixmap as large as the glyph string. */
4310 pixmap = XCreatePixmap (s->display, s->window,
4311 s->background_width,
4312 s->height, depth);
4314 /* Don't clip in the following because we're working on the
4315 pixmap. */
4316 XSetClipMask (s->display, s->gc, None);
4318 /* Fill the pixmap with the background color/stipple. */
4319 if (s->stippled_p)
4321 /* Fill background with a stipple pattern. */
4322 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4323 XFillRectangle (s->display, pixmap, s->gc,
4324 0, 0, s->background_width, s->height);
4325 XSetFillStyle (s->display, s->gc, FillSolid);
4327 else
4329 XGCValues xgcv;
4330 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4331 &xgcv);
4332 XSetForeground (s->display, s->gc, xgcv.background);
4333 XFillRectangle (s->display, pixmap, s->gc,
4334 0, 0, s->background_width, s->height);
4335 XSetForeground (s->display, s->gc, xgcv.foreground);
4338 else
4339 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4341 s->background_filled_p = 1;
4344 /* Draw the foreground. */
4345 if (pixmap != None)
4347 x_draw_image_foreground_1 (s, pixmap);
4348 x_set_glyph_string_clipping (s);
4349 XCopyArea (s->display, pixmap, s->window, s->gc,
4350 0, 0, s->background_width, s->height, s->x, s->y);
4351 XFreePixmap (s->display, pixmap);
4353 else
4354 x_draw_image_foreground (s);
4356 /* If we must draw a relief around the image, do it. */
4357 if (s->img->relief
4358 || s->hl == DRAW_IMAGE_RAISED
4359 || s->hl == DRAW_IMAGE_SUNKEN)
4360 x_draw_image_relief (s);
4364 /* Draw stretch glyph string S. */
4366 static void
4367 x_draw_stretch_glyph_string (s)
4368 struct glyph_string *s;
4370 xassert (s->first_glyph->type == STRETCH_GLYPH);
4371 s->stippled_p = s->face->stipple != 0;
4373 if (s->hl == DRAW_CURSOR
4374 && !x_stretch_cursor_p)
4376 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4377 as wide as the stretch glyph. */
4378 int width = min (CANON_X_UNIT (s->f), s->background_width);
4380 /* Draw cursor. */
4381 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4383 /* Clear rest using the GC of the original non-cursor face. */
4384 if (width < s->background_width)
4386 GC gc = s->face->gc;
4387 int x = s->x + width, y = s->y;
4388 int w = s->background_width - width, h = s->height;
4389 XRectangle r;
4391 x_get_glyph_string_clip_rect (s, &r);
4392 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4394 if (s->face->stipple)
4396 /* Fill background with a stipple pattern. */
4397 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4398 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4399 XSetFillStyle (s->display, gc, FillSolid);
4401 else
4403 XGCValues xgcv;
4404 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4405 XSetForeground (s->display, gc, xgcv.background);
4406 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4407 XSetForeground (s->display, gc, xgcv.foreground);
4411 else
4412 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4413 s->height);
4415 s->background_filled_p = 1;
4419 /* Draw glyph string S. */
4421 static void
4422 x_draw_glyph_string (s)
4423 struct glyph_string *s;
4425 int relief_drawn_p = 0;
4427 /* If S draws into the background of its successor, draw the
4428 background of the successor first so that S can draw into it.
4429 This makes S->next use XDrawString instead of XDrawImageString. */
4430 if (s->next && s->right_overhang && !s->for_overlaps_p)
4432 xassert (s->next->img == NULL);
4433 x_set_glyph_string_gc (s->next);
4434 x_set_glyph_string_clipping (s->next);
4435 x_draw_glyph_string_background (s->next, 1);
4438 /* Set up S->gc, set clipping and draw S. */
4439 x_set_glyph_string_gc (s);
4440 x_set_glyph_string_clipping (s);
4442 /* Draw relief (if any) in advance for char/composition so that the
4443 glyph string can be drawn over it. */
4444 if (!s->for_overlaps_p
4445 && s->face->box != FACE_NO_BOX
4446 && (s->first_glyph->type == CHAR_GLYPH
4447 || s->first_glyph->type == COMPOSITE_GLYPH))
4450 x_draw_glyph_string_background (s, 1);
4451 x_draw_glyph_string_box (s);
4452 relief_drawn_p = 1;
4455 switch (s->first_glyph->type)
4457 case IMAGE_GLYPH:
4458 x_draw_image_glyph_string (s);
4459 break;
4461 case STRETCH_GLYPH:
4462 x_draw_stretch_glyph_string (s);
4463 break;
4465 case CHAR_GLYPH:
4466 if (s->for_overlaps_p)
4467 s->background_filled_p = 1;
4468 else
4469 x_draw_glyph_string_background (s, 0);
4470 x_draw_glyph_string_foreground (s);
4471 break;
4473 case COMPOSITE_GLYPH:
4474 if (s->for_overlaps_p || s->gidx > 0)
4475 s->background_filled_p = 1;
4476 else
4477 x_draw_glyph_string_background (s, 1);
4478 x_draw_composite_glyph_string_foreground (s);
4479 break;
4481 default:
4482 abort ();
4485 if (!s->for_overlaps_p)
4487 /* Draw underline. */
4488 if (s->face->underline_p)
4490 unsigned long tem, h;
4491 int y;
4493 /* Get the underline thickness. Default is 1 pixel. */
4494 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4495 h = 1;
4497 /* Get the underline position. This is the recommended
4498 vertical offset in pixels from the baseline to the top of
4499 the underline. This is a signed value according to the
4500 specs, and its default is
4502 ROUND ((maximum descent) / 2), with
4503 ROUND(x) = floor (x + 0.5) */
4505 if (x_use_underline_position_properties
4506 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4507 y = s->ybase + (long) tem;
4508 else if (s->face->font)
4509 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4510 else
4511 y = s->y + s->height - h;
4513 if (s->face->underline_defaulted_p)
4514 XFillRectangle (s->display, s->window, s->gc,
4515 s->x, y, s->width, h);
4516 else
4518 XGCValues xgcv;
4519 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4520 XSetForeground (s->display, s->gc, s->face->underline_color);
4521 XFillRectangle (s->display, s->window, s->gc,
4522 s->x, y, s->width, h);
4523 XSetForeground (s->display, s->gc, xgcv.foreground);
4527 /* Draw overline. */
4528 if (s->face->overline_p)
4530 unsigned long dy = 0, h = 1;
4532 if (s->face->overline_color_defaulted_p)
4533 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4534 s->width, h);
4535 else
4537 XGCValues xgcv;
4538 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4539 XSetForeground (s->display, s->gc, s->face->overline_color);
4540 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4541 s->width, h);
4542 XSetForeground (s->display, s->gc, xgcv.foreground);
4546 /* Draw strike-through. */
4547 if (s->face->strike_through_p)
4549 unsigned long h = 1;
4550 unsigned long dy = (s->height - h) / 2;
4552 if (s->face->strike_through_color_defaulted_p)
4553 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4554 s->width, h);
4555 else
4557 XGCValues xgcv;
4558 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4559 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4560 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4561 s->width, h);
4562 XSetForeground (s->display, s->gc, xgcv.foreground);
4566 /* Draw relief if not yet drawn. */
4567 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4568 x_draw_glyph_string_box (s);
4571 /* Reset clipping. */
4572 XSetClipMask (s->display, s->gc, None);
4576 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4577 struct face **, int));
4580 /* Fill glyph string S with composition components specified by S->cmp.
4582 FACES is an array of faces for all components of this composition.
4583 S->gidx is the index of the first component for S.
4584 OVERLAPS_P non-zero means S should draw the foreground only, and
4585 use its physical height for clipping.
4587 Value is the index of a component not in S. */
4589 static int
4590 x_fill_composite_glyph_string (s, faces, overlaps_p)
4591 struct glyph_string *s;
4592 struct face **faces;
4593 int overlaps_p;
4595 int i;
4597 xassert (s);
4599 s->for_overlaps_p = overlaps_p;
4601 s->face = faces[s->gidx];
4602 s->font = s->face->font;
4603 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4605 /* For all glyphs of this composition, starting at the offset
4606 S->gidx, until we reach the end of the definition or encounter a
4607 glyph that requires the different face, add it to S. */
4608 ++s->nchars;
4609 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4610 ++s->nchars;
4612 /* All glyph strings for the same composition has the same width,
4613 i.e. the width set for the first component of the composition. */
4615 s->width = s->first_glyph->pixel_width;
4617 /* If the specified font could not be loaded, use the frame's
4618 default font, but record the fact that we couldn't load it in
4619 the glyph string so that we can draw rectangles for the
4620 characters of the glyph string. */
4621 if (s->font == NULL)
4623 s->font_not_found_p = 1;
4624 s->font = FRAME_FONT (s->f);
4627 /* Adjust base line for subscript/superscript text. */
4628 s->ybase += s->first_glyph->voffset;
4630 xassert (s->face && s->face->gc);
4632 /* This glyph string must always be drawn with 16-bit functions. */
4633 s->two_byte_p = 1;
4635 return s->gidx + s->nchars;
4639 /* Fill glyph string S from a sequence of character glyphs.
4641 FACE_ID is the face id of the string. START is the index of the
4642 first glyph to consider, END is the index of the last + 1.
4643 OVERLAPS_P non-zero means S should draw the foreground only, and
4644 use its physical height for clipping.
4646 Value is the index of the first glyph not in S. */
4648 static int
4649 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4650 struct glyph_string *s;
4651 int face_id;
4652 int start, end, overlaps_p;
4654 struct glyph *glyph, *last;
4655 int voffset;
4656 int glyph_not_available_p;
4658 xassert (s->f == XFRAME (s->w->frame));
4659 xassert (s->nchars == 0);
4660 xassert (start >= 0 && end > start);
4662 s->for_overlaps_p = overlaps_p,
4663 glyph = s->row->glyphs[s->area] + start;
4664 last = s->row->glyphs[s->area] + end;
4665 voffset = glyph->voffset;
4667 glyph_not_available_p = glyph->glyph_not_available_p;
4669 while (glyph < last
4670 && glyph->type == CHAR_GLYPH
4671 && glyph->voffset == voffset
4672 /* Same face id implies same font, nowadays. */
4673 && glyph->face_id == face_id
4674 && glyph->glyph_not_available_p == glyph_not_available_p)
4676 int two_byte_p;
4678 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4679 s->char2b + s->nchars,
4680 &two_byte_p);
4681 s->two_byte_p = two_byte_p;
4682 ++s->nchars;
4683 xassert (s->nchars <= end - start);
4684 s->width += glyph->pixel_width;
4685 ++glyph;
4688 s->font = s->face->font;
4689 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4691 /* If the specified font could not be loaded, use the frame's font,
4692 but record the fact that we couldn't load it in
4693 S->font_not_found_p so that we can draw rectangles for the
4694 characters of the glyph string. */
4695 if (s->font == NULL || glyph_not_available_p)
4697 s->font_not_found_p = 1;
4698 s->font = FRAME_FONT (s->f);
4701 /* Adjust base line for subscript/superscript text. */
4702 s->ybase += voffset;
4704 xassert (s->face && s->face->gc);
4705 return glyph - s->row->glyphs[s->area];
4709 /* Fill glyph string S from image glyph S->first_glyph. */
4711 static void
4712 x_fill_image_glyph_string (s)
4713 struct glyph_string *s;
4715 xassert (s->first_glyph->type == IMAGE_GLYPH);
4716 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4717 xassert (s->img);
4718 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4719 s->font = s->face->font;
4720 s->width = s->first_glyph->pixel_width;
4722 /* Adjust base line for subscript/superscript text. */
4723 s->ybase += s->first_glyph->voffset;
4727 /* Fill glyph string S from a sequence of stretch glyphs.
4729 ROW is the glyph row in which the glyphs are found, AREA is the
4730 area within the row. START is the index of the first glyph to
4731 consider, END is the index of the last + 1.
4733 Value is the index of the first glyph not in S. */
4735 static int
4736 x_fill_stretch_glyph_string (s, row, area, start, end)
4737 struct glyph_string *s;
4738 struct glyph_row *row;
4739 enum glyph_row_area area;
4740 int start, end;
4742 struct glyph *glyph, *last;
4743 int voffset, face_id;
4745 xassert (s->first_glyph->type == STRETCH_GLYPH);
4747 glyph = s->row->glyphs[s->area] + start;
4748 last = s->row->glyphs[s->area] + end;
4749 face_id = glyph->face_id;
4750 s->face = FACE_FROM_ID (s->f, face_id);
4751 s->font = s->face->font;
4752 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4753 s->width = glyph->pixel_width;
4754 voffset = glyph->voffset;
4756 for (++glyph;
4757 (glyph < last
4758 && glyph->type == STRETCH_GLYPH
4759 && glyph->voffset == voffset
4760 && glyph->face_id == face_id);
4761 ++glyph)
4762 s->width += glyph->pixel_width;
4764 /* Adjust base line for subscript/superscript text. */
4765 s->ybase += voffset;
4767 xassert (s->face && s->face->gc);
4768 return glyph - s->row->glyphs[s->area];
4772 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4773 of XChar2b structures for S; it can't be allocated in
4774 x_init_glyph_string because it must be allocated via `alloca'. W
4775 is the window on which S is drawn. ROW and AREA are the glyph row
4776 and area within the row from which S is constructed. START is the
4777 index of the first glyph structure covered by S. HL is a
4778 face-override for drawing S. */
4780 static void
4781 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4782 struct glyph_string *s;
4783 XChar2b *char2b;
4784 struct window *w;
4785 struct glyph_row *row;
4786 enum glyph_row_area area;
4787 int start;
4788 enum draw_glyphs_face hl;
4790 bzero (s, sizeof *s);
4791 s->w = w;
4792 s->f = XFRAME (w->frame);
4793 s->display = FRAME_X_DISPLAY (s->f);
4794 s->window = FRAME_X_WINDOW (s->f);
4795 s->char2b = char2b;
4796 s->hl = hl;
4797 s->row = row;
4798 s->area = area;
4799 s->first_glyph = row->glyphs[area] + start;
4800 s->height = row->height;
4801 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4803 /* Display the internal border below the tool-bar window. */
4804 if (s->w == XWINDOW (s->f->tool_bar_window))
4805 s->y -= s->f->output_data.x->internal_border_width;
4807 s->ybase = s->y + row->ascent;
4811 /* Set background width of glyph string S. START is the index of the
4812 first glyph following S. LAST_X is the right-most x-position + 1
4813 in the drawing area. */
4815 static INLINE void
4816 x_set_glyph_string_background_width (s, start, last_x)
4817 struct glyph_string *s;
4818 int start;
4819 int last_x;
4821 /* If the face of this glyph string has to be drawn to the end of
4822 the drawing area, set S->extends_to_end_of_line_p. */
4823 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4825 if (start == s->row->used[s->area]
4826 && s->hl == DRAW_NORMAL_TEXT
4827 && s->area == TEXT_AREA
4828 && (s->row->fill_line_p
4829 || s->face->background != default_face->background
4830 || s->face->stipple != default_face->stipple))
4831 s->extends_to_end_of_line_p = 1;
4833 /* If S extends its face to the end of the line, set its
4834 background_width to the distance to the right edge of the drawing
4835 area. */
4836 if (s->extends_to_end_of_line_p)
4837 s->background_width = last_x - s->x + 1;
4838 else
4839 s->background_width = s->width;
4843 /* Add a glyph string for a stretch glyph to the list of strings
4844 between HEAD and TAIL. START is the index of the stretch glyph in
4845 row area AREA of glyph row ROW. END is the index of the last glyph
4846 in that glyph row area. X is the current output position assigned
4847 to the new glyph string constructed. HL overrides that face of the
4848 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4849 is the right-most x-position of the drawing area. */
4851 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4852 and below -- keep them on one line. */
4853 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4854 do \
4856 s = (struct glyph_string *) alloca (sizeof *s); \
4857 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4858 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4859 x_append_glyph_string (&HEAD, &TAIL, s); \
4860 s->x = (X); \
4862 while (0)
4865 /* Add a glyph string for an image glyph to the list of strings
4866 between HEAD and TAIL. START is the index of the image glyph in
4867 row area AREA of glyph row ROW. END is the index of the last glyph
4868 in that glyph row area. X is the current output position assigned
4869 to the new glyph string constructed. HL overrides that face of the
4870 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4871 is the right-most x-position of the drawing area. */
4873 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4874 do \
4876 s = (struct glyph_string *) alloca (sizeof *s); \
4877 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4878 x_fill_image_glyph_string (s); \
4879 x_append_glyph_string (&HEAD, &TAIL, s); \
4880 ++START; \
4881 s->x = (X); \
4883 while (0)
4886 /* Add a glyph string for a sequence of character glyphs to the list
4887 of strings between HEAD and TAIL. START is the index of the first
4888 glyph in row area AREA of glyph row ROW that is part of the new
4889 glyph string. END is the index of the last glyph in that glyph row
4890 area. X is the current output position assigned to the new glyph
4891 string constructed. HL overrides that face of the glyph; e.g. it
4892 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4893 right-most x-position of the drawing area. */
4895 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4896 do \
4898 int c, face_id; \
4899 XChar2b *char2b; \
4901 c = (ROW)->glyphs[AREA][START].u.ch; \
4902 face_id = (ROW)->glyphs[AREA][START].face_id; \
4904 s = (struct glyph_string *) alloca (sizeof *s); \
4905 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4906 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4907 x_append_glyph_string (&HEAD, &TAIL, s); \
4908 s->x = (X); \
4909 START = x_fill_glyph_string (s, face_id, START, END, \
4910 OVERLAPS_P); \
4912 while (0)
4915 /* Add a glyph string for a composite sequence to the list of strings
4916 between HEAD and TAIL. START is the index of the first glyph in
4917 row area AREA of glyph row ROW that is part of the new glyph
4918 string. END is the index of the last glyph in that glyph row area.
4919 X is the current output position assigned to the new glyph string
4920 constructed. HL overrides that face of the glyph; e.g. it is
4921 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4922 x-position of the drawing area. */
4924 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4925 do { \
4926 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4927 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4928 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4929 struct composition *cmp = composition_table[cmp_id]; \
4930 int glyph_len = cmp->glyph_len; \
4931 XChar2b *char2b; \
4932 struct face **faces; \
4933 struct glyph_string *first_s = NULL; \
4934 int n; \
4936 base_face = base_face->ascii_face; \
4937 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4938 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4939 /* At first, fill in `char2b' and `faces'. */ \
4940 for (n = 0; n < glyph_len; n++) \
4942 int c = COMPOSITION_GLYPH (cmp, n); \
4943 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4944 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4945 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4946 this_face_id, char2b + n, 1); \
4949 /* Make glyph_strings for each glyph sequence that is drawable by \
4950 the same face, and append them to HEAD/TAIL. */ \
4951 for (n = 0; n < cmp->glyph_len;) \
4953 s = (struct glyph_string *) alloca (sizeof *s); \
4954 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4955 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4956 s->cmp = cmp; \
4957 s->gidx = n; \
4958 s->x = (X); \
4960 if (n == 0) \
4961 first_s = s; \
4963 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4966 ++START; \
4967 s = first_s; \
4968 } while (0)
4971 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4972 of AREA of glyph row ROW on window W between indices START and END.
4973 HL overrides the face for drawing glyph strings, e.g. it is
4974 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4975 x-positions of the drawing area.
4977 This is an ugly monster macro construct because we must use alloca
4978 to allocate glyph strings (because x_draw_glyphs can be called
4979 asynchronously). */
4981 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4982 do \
4984 HEAD = TAIL = NULL; \
4985 while (START < END) \
4987 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4988 switch (first_glyph->type) \
4990 case CHAR_GLYPH: \
4991 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4992 TAIL, HL, X, LAST_X, \
4993 OVERLAPS_P); \
4994 break; \
4996 case COMPOSITE_GLYPH: \
4997 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4998 HEAD, TAIL, HL, X, LAST_X,\
4999 OVERLAPS_P); \
5000 break; \
5002 case STRETCH_GLYPH: \
5003 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5004 HEAD, TAIL, HL, X, LAST_X); \
5005 break; \
5007 case IMAGE_GLYPH: \
5008 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5009 TAIL, HL, X, LAST_X); \
5010 break; \
5012 default: \
5013 abort (); \
5016 x_set_glyph_string_background_width (s, START, LAST_X); \
5017 (X) += s->width; \
5020 while (0)
5023 /* Draw glyphs between START and END in AREA of ROW on window W,
5024 starting at x-position X. X is relative to AREA in W. HL is a
5025 face-override with the following meaning:
5027 DRAW_NORMAL_TEXT draw normally
5028 DRAW_CURSOR draw in cursor face
5029 DRAW_MOUSE_FACE draw in mouse face.
5030 DRAW_INVERSE_VIDEO draw in mode line face
5031 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5032 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5034 If REAL_START is non-null, return in *REAL_START the real starting
5035 position for display. This can be different from START in case
5036 overlapping glyphs must be displayed. If REAL_END is non-null,
5037 return in *REAL_END the real end position for display. This can be
5038 different from END in case overlapping glyphs must be displayed.
5040 If OVERLAPS_P is non-zero, draw only the foreground of characters
5041 and clip to the physical height of ROW.
5043 Value is the x-position reached, relative to AREA of W. */
5045 static int
5046 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
5047 overlaps_p)
5048 struct window *w;
5049 int x;
5050 struct glyph_row *row;
5051 enum glyph_row_area area;
5052 int start, end;
5053 enum draw_glyphs_face hl;
5054 int *real_start, *real_end;
5055 int overlaps_p;
5057 struct glyph_string *head, *tail;
5058 struct glyph_string *s;
5059 int last_x, area_width;
5060 int x_reached;
5061 int i, j;
5063 /* Let's rather be paranoid than getting a SEGV. */
5064 end = min (end, row->used[area]);
5065 start = max (0, start);
5066 start = min (end, start);
5067 if (real_start)
5068 *real_start = start;
5069 if (real_end)
5070 *real_end = end;
5072 /* Translate X to frame coordinates. Set last_x to the right
5073 end of the drawing area. */
5074 if (row->full_width_p)
5076 /* X is relative to the left edge of W, without scroll bars
5077 or flag areas. */
5078 struct frame *f = XFRAME (w->frame);
5079 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
5080 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5082 x += window_left_x;
5083 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5084 last_x = window_left_x + area_width;
5086 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5088 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5089 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5090 last_x += width;
5091 else
5092 x -= width;
5095 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5096 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5098 else
5100 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5101 area_width = window_box_width (w, area);
5102 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5105 /* Build a doubly-linked list of glyph_string structures between
5106 head and tail from what we have to draw. Note that the macro
5107 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5108 the reason we use a separate variable `i'. */
5109 i = start;
5110 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5111 overlaps_p);
5112 if (tail)
5113 x_reached = tail->x + tail->background_width;
5114 else
5115 x_reached = x;
5117 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5118 the row, redraw some glyphs in front or following the glyph
5119 strings built above. */
5120 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5122 int dummy_x = 0;
5123 struct glyph_string *h, *t;
5125 /* Compute overhangs for all glyph strings. */
5126 for (s = head; s; s = s->next)
5127 x_compute_glyph_string_overhangs (s);
5129 /* Prepend glyph strings for glyphs in front of the first glyph
5130 string that are overwritten because of the first glyph
5131 string's left overhang. The background of all strings
5132 prepended must be drawn because the first glyph string
5133 draws over it. */
5134 i = x_left_overwritten (head);
5135 if (i >= 0)
5137 j = i;
5138 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5139 DRAW_NORMAL_TEXT, dummy_x, last_x,
5140 overlaps_p);
5141 start = i;
5142 if (real_start)
5143 *real_start = start;
5144 x_compute_overhangs_and_x (t, head->x, 1);
5145 x_prepend_glyph_string_lists (&head, &tail, h, t);
5148 /* Prepend glyph strings for glyphs in front of the first glyph
5149 string that overwrite that glyph string because of their
5150 right overhang. For these strings, only the foreground must
5151 be drawn, because it draws over the glyph string at `head'.
5152 The background must not be drawn because this would overwrite
5153 right overhangs of preceding glyphs for which no glyph
5154 strings exist. */
5155 i = x_left_overwriting (head);
5156 if (i >= 0)
5158 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5159 DRAW_NORMAL_TEXT, dummy_x, last_x,
5160 overlaps_p);
5161 for (s = h; s; s = s->next)
5162 s->background_filled_p = 1;
5163 if (real_start)
5164 *real_start = i;
5165 x_compute_overhangs_and_x (t, head->x, 1);
5166 x_prepend_glyph_string_lists (&head, &tail, h, t);
5169 /* Append glyphs strings for glyphs following the last glyph
5170 string tail that are overwritten by tail. The background of
5171 these strings has to be drawn because tail's foreground draws
5172 over it. */
5173 i = x_right_overwritten (tail);
5174 if (i >= 0)
5176 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5177 DRAW_NORMAL_TEXT, x, last_x,
5178 overlaps_p);
5179 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5180 x_append_glyph_string_lists (&head, &tail, h, t);
5181 if (real_end)
5182 *real_end = i;
5185 /* Append glyph strings for glyphs following the last glyph
5186 string tail that overwrite tail. The foreground of such
5187 glyphs has to be drawn because it writes into the background
5188 of tail. The background must not be drawn because it could
5189 paint over the foreground of following glyphs. */
5190 i = x_right_overwriting (tail);
5191 if (i >= 0)
5193 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5194 DRAW_NORMAL_TEXT, x, last_x,
5195 overlaps_p);
5196 for (s = h; s; s = s->next)
5197 s->background_filled_p = 1;
5198 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5199 x_append_glyph_string_lists (&head, &tail, h, t);
5200 if (real_end)
5201 *real_end = i;
5205 /* Draw all strings. */
5206 for (s = head; s; s = s->next)
5207 x_draw_glyph_string (s);
5209 /* Value is the x-position up to which drawn, relative to AREA of W.
5210 This doesn't include parts drawn because of overhangs. */
5211 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5212 if (!row->full_width_p)
5214 if (area > LEFT_MARGIN_AREA)
5215 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5216 if (area > TEXT_AREA)
5217 x_reached -= window_box_width (w, TEXT_AREA);
5220 return x_reached;
5224 /* Fix the display of area AREA of overlapping row ROW in window W. */
5226 static void
5227 x_fix_overlapping_area (w, row, area)
5228 struct window *w;
5229 struct glyph_row *row;
5230 enum glyph_row_area area;
5232 int i, x;
5234 BLOCK_INPUT;
5236 if (area == LEFT_MARGIN_AREA)
5237 x = 0;
5238 else if (area == TEXT_AREA)
5239 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5240 else
5241 x = (window_box_width (w, LEFT_MARGIN_AREA)
5242 + window_box_width (w, TEXT_AREA));
5244 for (i = 0; i < row->used[area];)
5246 if (row->glyphs[area][i].overlaps_vertically_p)
5248 int start = i, start_x = x;
5252 x += row->glyphs[area][i].pixel_width;
5253 ++i;
5255 while (i < row->used[area]
5256 && row->glyphs[area][i].overlaps_vertically_p);
5258 x_draw_glyphs (w, start_x, row, area, start, i,
5259 (row->inverse_p
5260 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5261 NULL, NULL, 1);
5263 else
5265 x += row->glyphs[area][i].pixel_width;
5266 ++i;
5270 UNBLOCK_INPUT;
5274 /* Output LEN glyphs starting at START at the nominal cursor position.
5275 Advance the nominal cursor over the text. The global variable
5276 updated_window contains the window being updated, updated_row is
5277 the glyph row being updated, and updated_area is the area of that
5278 row being updated. */
5280 static void
5281 x_write_glyphs (start, len)
5282 struct glyph *start;
5283 int len;
5285 int x, hpos, real_start, real_end;
5287 xassert (updated_window && updated_row);
5288 BLOCK_INPUT;
5290 /* Write glyphs. */
5292 hpos = start - updated_row->glyphs[updated_area];
5293 x = x_draw_glyphs (updated_window, output_cursor.x,
5294 updated_row, updated_area,
5295 hpos, hpos + len,
5296 (updated_row->inverse_p
5297 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5298 &real_start, &real_end, 0);
5300 /* If we drew over the cursor, note that it is not visible any more. */
5301 note_overwritten_text_cursor (updated_window, real_start,
5302 real_end - real_start);
5304 UNBLOCK_INPUT;
5306 /* Advance the output cursor. */
5307 output_cursor.hpos += len;
5308 output_cursor.x = x;
5312 /* Insert LEN glyphs from START at the nominal cursor position. */
5314 static void
5315 x_insert_glyphs (start, len)
5316 struct glyph *start;
5317 register int len;
5319 struct frame *f;
5320 struct window *w;
5321 int line_height, shift_by_width, shifted_region_width;
5322 struct glyph_row *row;
5323 struct glyph *glyph;
5324 int frame_x, frame_y, hpos, real_start, real_end;
5326 xassert (updated_window && updated_row);
5327 BLOCK_INPUT;
5328 w = updated_window;
5329 f = XFRAME (WINDOW_FRAME (w));
5331 /* Get the height of the line we are in. */
5332 row = updated_row;
5333 line_height = row->height;
5335 /* Get the width of the glyphs to insert. */
5336 shift_by_width = 0;
5337 for (glyph = start; glyph < start + len; ++glyph)
5338 shift_by_width += glyph->pixel_width;
5340 /* Get the width of the region to shift right. */
5341 shifted_region_width = (window_box_width (w, updated_area)
5342 - output_cursor.x
5343 - shift_by_width);
5345 /* Shift right. */
5346 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5347 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5348 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5349 f->output_data.x->normal_gc,
5350 frame_x, frame_y,
5351 shifted_region_width, line_height,
5352 frame_x + shift_by_width, frame_y);
5354 /* Write the glyphs. */
5355 hpos = start - row->glyphs[updated_area];
5356 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5357 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5358 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5360 /* Advance the output cursor. */
5361 output_cursor.hpos += len;
5362 output_cursor.x += shift_by_width;
5363 UNBLOCK_INPUT;
5367 /* Delete N glyphs at the nominal cursor position. Not implemented
5368 for X frames. */
5370 static void
5371 x_delete_glyphs (n)
5372 register int n;
5374 abort ();
5378 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5379 If they are <= 0, this is probably an error. */
5381 void
5382 x_clear_area (dpy, window, x, y, width, height, exposures)
5383 Display *dpy;
5384 Window window;
5385 int x, y;
5386 int width, height;
5387 int exposures;
5389 xassert (width > 0 && height > 0);
5390 XClearArea (dpy, window, x, y, width, height, exposures);
5394 /* Erase the current text line from the nominal cursor position
5395 (inclusive) to pixel column TO_X (exclusive). The idea is that
5396 everything from TO_X onward is already erased.
5398 TO_X is a pixel position relative to updated_area of
5399 updated_window. TO_X == -1 means clear to the end of this area. */
5401 static void
5402 x_clear_end_of_line (to_x)
5403 int to_x;
5405 struct frame *f;
5406 struct window *w = updated_window;
5407 int max_x, min_y, max_y;
5408 int from_x, from_y, to_y;
5410 xassert (updated_window && updated_row);
5411 f = XFRAME (w->frame);
5413 if (updated_row->full_width_p)
5415 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5416 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5417 && !w->pseudo_window_p)
5418 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5420 else
5421 max_x = window_box_width (w, updated_area);
5422 max_y = window_text_bottom_y (w);
5424 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5425 of window. For TO_X > 0, truncate to end of drawing area. */
5426 if (to_x == 0)
5427 return;
5428 else if (to_x < 0)
5429 to_x = max_x;
5430 else
5431 to_x = min (to_x, max_x);
5433 to_y = min (max_y, output_cursor.y + updated_row->height);
5435 /* Notice if the cursor will be cleared by this operation. */
5436 if (!updated_row->full_width_p)
5437 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5439 from_x = output_cursor.x;
5441 /* Translate to frame coordinates. */
5442 if (updated_row->full_width_p)
5444 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5445 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5447 else
5449 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5450 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5453 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5454 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5455 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5457 /* Prevent inadvertently clearing to end of the X window. */
5458 if (to_x > from_x && to_y > from_y)
5460 BLOCK_INPUT;
5461 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5462 from_x, from_y, to_x - from_x, to_y - from_y,
5463 False);
5464 UNBLOCK_INPUT;
5469 /* Clear entire frame. If updating_frame is non-null, clear that
5470 frame. Otherwise clear the selected frame. */
5472 static void
5473 x_clear_frame ()
5475 struct frame *f;
5477 if (updating_frame)
5478 f = updating_frame;
5479 else
5480 f = SELECTED_FRAME ();
5482 /* Clearing the frame will erase any cursor, so mark them all as no
5483 longer visible. */
5484 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5485 output_cursor.hpos = output_cursor.vpos = 0;
5486 output_cursor.x = -1;
5488 /* We don't set the output cursor here because there will always
5489 follow an explicit cursor_to. */
5490 BLOCK_INPUT;
5491 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5493 /* We have to clear the scroll bars, too. If we have changed
5494 colors or something like that, then they should be notified. */
5495 x_scroll_bar_clear (f);
5497 XFlush (FRAME_X_DISPLAY (f));
5498 UNBLOCK_INPUT;
5503 /* Invert the middle quarter of the frame for .15 sec. */
5505 /* We use the select system call to do the waiting, so we have to make
5506 sure it's available. If it isn't, we just won't do visual bells. */
5508 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5511 /* Subtract the `struct timeval' values X and Y, storing the result in
5512 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5514 static int
5515 timeval_subtract (result, x, y)
5516 struct timeval *result, x, y;
5518 /* Perform the carry for the later subtraction by updating y. This
5519 is safer because on some systems the tv_sec member is unsigned. */
5520 if (x.tv_usec < y.tv_usec)
5522 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5523 y.tv_usec -= 1000000 * nsec;
5524 y.tv_sec += nsec;
5527 if (x.tv_usec - y.tv_usec > 1000000)
5529 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5530 y.tv_usec += 1000000 * nsec;
5531 y.tv_sec -= nsec;
5534 /* Compute the time remaining to wait. tv_usec is certainly
5535 positive. */
5536 result->tv_sec = x.tv_sec - y.tv_sec;
5537 result->tv_usec = x.tv_usec - y.tv_usec;
5539 /* Return indication of whether the result should be considered
5540 negative. */
5541 return x.tv_sec < y.tv_sec;
5544 void
5545 XTflash (f)
5546 struct frame *f;
5548 BLOCK_INPUT;
5551 GC gc;
5553 /* Create a GC that will use the GXxor function to flip foreground
5554 pixels into background pixels. */
5556 XGCValues values;
5558 values.function = GXxor;
5559 values.foreground = (f->output_data.x->foreground_pixel
5560 ^ f->output_data.x->background_pixel);
5562 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5563 GCFunction | GCForeground, &values);
5567 /* Get the height not including a menu bar widget. */
5568 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5569 /* Height of each line to flash. */
5570 int flash_height = FRAME_LINE_HEIGHT (f);
5571 /* These will be the left and right margins of the rectangles. */
5572 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5573 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5575 int width;
5577 /* Don't flash the area between a scroll bar and the frame
5578 edge it is next to. */
5579 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5581 case vertical_scroll_bar_left:
5582 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5583 break;
5585 case vertical_scroll_bar_right:
5586 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5587 break;
5589 default:
5590 break;
5593 width = flash_right - flash_left;
5595 /* If window is tall, flash top and bottom line. */
5596 if (height > 3 * FRAME_LINE_HEIGHT (f))
5598 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5599 flash_left,
5600 (FRAME_INTERNAL_BORDER_WIDTH (f)
5601 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5602 width, flash_height);
5603 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5604 flash_left,
5605 (height - flash_height
5606 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5607 width, flash_height);
5609 else
5610 /* If it is short, flash it all. */
5611 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5612 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5613 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5615 x_flush (f);
5618 struct timeval wakeup;
5620 EMACS_GET_TIME (wakeup);
5622 /* Compute time to wait until, propagating carry from usecs. */
5623 wakeup.tv_usec += 150000;
5624 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5625 wakeup.tv_usec %= 1000000;
5627 /* Keep waiting until past the time wakeup or any input gets
5628 available. */
5629 while (! detect_input_pending ())
5631 struct timeval current;
5632 struct timeval timeout;
5634 EMACS_GET_TIME (current);
5636 /* Break if result would be negative. */
5637 if (timeval_subtract (&current, wakeup, current))
5638 break;
5640 /* How long `select' should wait. */
5641 timeout.tv_sec = 0;
5642 timeout.tv_usec = 10000;
5644 /* Try to wait that long--but we might wake up sooner. */
5645 select (0, NULL, NULL, NULL, &timeout);
5649 /* If window is tall, flash top and bottom line. */
5650 if (height > 3 * FRAME_LINE_HEIGHT (f))
5652 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5653 flash_left,
5654 (FRAME_INTERNAL_BORDER_WIDTH (f)
5655 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5656 width, flash_height);
5657 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5658 flash_left,
5659 (height - flash_height
5660 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5661 width, flash_height);
5663 else
5664 /* If it is short, flash it all. */
5665 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5666 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5667 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5669 XFreeGC (FRAME_X_DISPLAY (f), gc);
5670 x_flush (f);
5674 UNBLOCK_INPUT;
5677 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5680 /* Make audible bell. */
5682 void
5683 XTring_bell ()
5685 struct frame *f = SELECTED_FRAME ();
5687 if (FRAME_X_DISPLAY (f))
5689 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5690 if (visible_bell)
5691 XTflash (f);
5692 else
5693 #endif
5695 BLOCK_INPUT;
5696 XBell (FRAME_X_DISPLAY (f), 0);
5697 XFlush (FRAME_X_DISPLAY (f));
5698 UNBLOCK_INPUT;
5704 /* Specify how many text lines, from the top of the window,
5705 should be affected by insert-lines and delete-lines operations.
5706 This, and those operations, are used only within an update
5707 that is bounded by calls to x_update_begin and x_update_end. */
5709 static void
5710 XTset_terminal_window (n)
5711 register int n;
5713 /* This function intentionally left blank. */
5718 /***********************************************************************
5719 Line Dance
5720 ***********************************************************************/
5722 /* Perform an insert-lines or delete-lines operation, inserting N
5723 lines or deleting -N lines at vertical position VPOS. */
5725 static void
5726 x_ins_del_lines (vpos, n)
5727 int vpos, n;
5729 abort ();
5733 /* Scroll part of the display as described by RUN. */
5735 static void
5736 x_scroll_run (w, run)
5737 struct window *w;
5738 struct run *run;
5740 struct frame *f = XFRAME (w->frame);
5741 int x, y, width, height, from_y, to_y, bottom_y;
5743 /* Get frame-relative bounding box of the text display area of W,
5744 without mode lines. Include in this box the flags areas to the
5745 left and right of W. */
5746 window_box (w, -1, &x, &y, &width, &height);
5747 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5748 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5750 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5751 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5752 bottom_y = y + height;
5754 if (to_y < from_y)
5756 /* Scrolling up. Make sure we don't copy part of the mode
5757 line at the bottom. */
5758 if (from_y + run->height > bottom_y)
5759 height = bottom_y - from_y;
5760 else
5761 height = run->height;
5763 else
5765 /* Scolling down. Make sure we don't copy over the mode line.
5766 at the bottom. */
5767 if (to_y + run->height > bottom_y)
5768 height = bottom_y - to_y;
5769 else
5770 height = run->height;
5773 BLOCK_INPUT;
5775 /* Cursor off. Will be switched on again in x_update_window_end. */
5776 updated_window = w;
5777 x_clear_cursor (w);
5779 XCopyArea (FRAME_X_DISPLAY (f),
5780 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5781 f->output_data.x->normal_gc,
5782 x, from_y,
5783 width, height,
5784 x, to_y);
5786 UNBLOCK_INPUT;
5791 /***********************************************************************
5792 Exposure Events
5793 ***********************************************************************/
5795 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5796 corner of the exposed rectangle. W and H are width and height of
5797 the exposed area. All are pixel values. W or H zero means redraw
5798 the entire frame. */
5800 static void
5801 expose_frame (f, x, y, w, h)
5802 struct frame *f;
5803 int x, y, w, h;
5805 XRectangle r;
5807 TRACE ((stderr, "expose_frame "));
5809 /* No need to redraw if frame will be redrawn soon. */
5810 if (FRAME_GARBAGED_P (f))
5812 TRACE ((stderr, " garbaged\n"));
5813 return;
5816 /* If basic faces haven't been realized yet, there is no point in
5817 trying to redraw anything. This can happen when we get an expose
5818 event while Emacs is starting, e.g. by moving another window. */
5819 if (FRAME_FACE_CACHE (f) == NULL
5820 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5822 TRACE ((stderr, " no faces\n"));
5823 return;
5826 if (w == 0 || h == 0)
5828 r.x = r.y = 0;
5829 r.width = CANON_X_UNIT (f) * f->width;
5830 r.height = CANON_Y_UNIT (f) * f->height;
5832 else
5834 r.x = x;
5835 r.y = y;
5836 r.width = w;
5837 r.height = h;
5840 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5841 expose_window_tree (XWINDOW (f->root_window), &r);
5843 if (WINDOWP (f->tool_bar_window))
5844 expose_window (XWINDOW (f->tool_bar_window), &r);
5846 #ifndef USE_X_TOOLKIT
5847 if (WINDOWP (f->menu_bar_window))
5848 expose_window (XWINDOW (f->menu_bar_window), &r);
5849 #endif /* not USE_X_TOOLKIT */
5853 /* Redraw (parts) of all windows in the window tree rooted at W that
5854 intersect R. R contains frame pixel coordinates. */
5856 static void
5857 expose_window_tree (w, r)
5858 struct window *w;
5859 XRectangle *r;
5861 while (w)
5863 if (!NILP (w->hchild))
5864 expose_window_tree (XWINDOW (w->hchild), r);
5865 else if (!NILP (w->vchild))
5866 expose_window_tree (XWINDOW (w->vchild), r);
5867 else
5868 expose_window (w, r);
5869 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5874 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5875 which intersects rectangle R. R is in window-relative coordinates. */
5877 static void
5878 expose_area (w, row, r, area)
5879 struct window *w;
5880 struct glyph_row *row;
5881 XRectangle *r;
5882 enum glyph_row_area area;
5884 struct glyph *first = row->glyphs[area];
5885 struct glyph *end = row->glyphs[area] + row->used[area];
5886 struct glyph *last;
5887 int first_x, start_x, x;
5889 if (area == TEXT_AREA && row->fill_line_p)
5890 /* If row extends face to end of line write the whole line. */
5891 x_draw_glyphs (w, 0, row, area,
5892 0, row->used[area],
5893 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5894 NULL, NULL, 0);
5895 else
5897 /* Set START_X to the window-relative start position for drawing glyphs of
5898 AREA. The first glyph of the text area can be partially visible.
5899 The first glyphs of other areas cannot. */
5900 if (area == LEFT_MARGIN_AREA)
5901 start_x = 0;
5902 else if (area == TEXT_AREA)
5903 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5904 else
5905 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5906 + window_box_width (w, TEXT_AREA));
5907 x = start_x;
5909 /* Find the first glyph that must be redrawn. */
5910 while (first < end
5911 && x + first->pixel_width < r->x)
5913 x += first->pixel_width;
5914 ++first;
5917 /* Find the last one. */
5918 last = first;
5919 first_x = x;
5920 while (last < end
5921 && x < r->x + r->width)
5923 x += last->pixel_width;
5924 ++last;
5927 /* Repaint. */
5928 if (last > first)
5929 x_draw_glyphs (w, first_x - start_x, row, area,
5930 first - row->glyphs[area],
5931 last - row->glyphs[area],
5932 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5933 NULL, NULL, 0);
5938 /* Redraw the parts of the glyph row ROW on window W intersecting
5939 rectangle R. R is in window-relative coordinates. */
5941 static void
5942 expose_line (w, row, r)
5943 struct window *w;
5944 struct glyph_row *row;
5945 XRectangle *r;
5947 xassert (row->enabled_p);
5949 if (row->mode_line_p || w->pseudo_window_p)
5950 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5951 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5952 NULL, NULL, 0);
5953 else
5955 if (row->used[LEFT_MARGIN_AREA])
5956 expose_area (w, row, r, LEFT_MARGIN_AREA);
5957 if (row->used[TEXT_AREA])
5958 expose_area (w, row, r, TEXT_AREA);
5959 if (row->used[RIGHT_MARGIN_AREA])
5960 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5961 x_draw_row_bitmaps (w, row);
5966 /* Return non-zero if W's cursor intersects rectangle R. */
5968 static int
5969 x_phys_cursor_in_rect_p (w, r)
5970 struct window *w;
5971 XRectangle *r;
5973 XRectangle cr, result;
5974 struct glyph *cursor_glyph;
5976 cursor_glyph = get_phys_cursor_glyph (w);
5977 if (cursor_glyph)
5979 cr.x = w->phys_cursor.x;
5980 cr.y = w->phys_cursor.y;
5981 cr.width = cursor_glyph->pixel_width;
5982 cr.height = w->phys_cursor_height;
5983 return x_intersect_rectangles (&cr, r, &result);
5985 else
5986 return 0;
5990 /* Redraw the part of window W intersection rectangle FR. Pixel
5991 coordinates in FR are frame-relative. Call this function with
5992 input blocked. */
5994 static void
5995 expose_window (w, fr)
5996 struct window *w;
5997 XRectangle *fr;
5999 struct frame *f = XFRAME (w->frame);
6000 struct glyph_row *row;
6001 int y, yb, cursor_cleared_p;
6002 XRectangle wr, r;
6004 /* If window is not yet fully initialized, do nothing. This can
6005 happen when toolkit scroll bars are used and a window is split.
6006 Reconfiguring the scroll bar will generate an expose for a newly
6007 created window. */
6008 if (w->current_matrix == NULL || w == updated_window)
6009 return;
6011 /* Frame-relative pixel rectangle of W. */
6012 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6013 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6014 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6015 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6017 if (!x_intersect_rectangles (fr, &wr, &r))
6018 return;
6020 yb = window_text_bottom_y (w);
6022 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6023 r.x, r.y, r.width, r.height));
6025 /* Convert to window coordinates. */
6026 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6027 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6029 /* Turn off the cursor. */
6030 if (!w->pseudo_window_p
6031 && x_phys_cursor_in_rect_p (w, &r))
6033 x_clear_cursor (w);
6034 cursor_cleared_p = 1;
6036 else
6037 cursor_cleared_p = 0;
6039 /* Find the first row intersecting the rectangle R. */
6040 row = w->current_matrix->rows;
6041 y = 0;
6042 while (row->enabled_p
6043 && y < yb
6044 && y + row->height < r.y)
6046 y += row->height;
6047 ++row;
6050 /* Display the text in the rectangle, one text line at a time. */
6051 while (row->enabled_p
6052 && y < yb
6053 && y < r.y + r.height)
6055 expose_line (w, row, &r);
6056 y += row->height;
6057 ++row;
6060 /* Display the mode line if there is one. */
6061 if (WINDOW_WANTS_MODELINE_P (w)
6062 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6063 row->enabled_p)
6064 && row->y < r.y + r.height)
6065 expose_line (w, row, &r);
6067 if (!w->pseudo_window_p)
6069 /* Draw border between windows. */
6070 x_draw_vertical_border (w);
6072 /* Turn the cursor on again. */
6073 if (cursor_cleared_p)
6074 x_update_window_cursor (w, 1);
6079 /* Determine the intersection of two rectangles R1 and R2. Return
6080 the intersection in *RESULT. Value is non-zero if RESULT is not
6081 empty. */
6083 static int
6084 x_intersect_rectangles (r1, r2, result)
6085 XRectangle *r1, *r2, *result;
6087 XRectangle *left, *right;
6088 XRectangle *upper, *lower;
6089 int intersection_p = 0;
6091 /* Rearrange so that R1 is the left-most rectangle. */
6092 if (r1->x < r2->x)
6093 left = r1, right = r2;
6094 else
6095 left = r2, right = r1;
6097 /* X0 of the intersection is right.x0, if this is inside R1,
6098 otherwise there is no intersection. */
6099 if (right->x <= left->x + left->width)
6101 result->x = right->x;
6103 /* The right end of the intersection is the minimum of the
6104 the right ends of left and right. */
6105 result->width = (min (left->x + left->width, right->x + right->width)
6106 - result->x);
6108 /* Same game for Y. */
6109 if (r1->y < r2->y)
6110 upper = r1, lower = r2;
6111 else
6112 upper = r2, lower = r1;
6114 /* The upper end of the intersection is lower.y0, if this is inside
6115 of upper. Otherwise, there is no intersection. */
6116 if (lower->y <= upper->y + upper->height)
6118 result->y = lower->y;
6120 /* The lower end of the intersection is the minimum of the lower
6121 ends of upper and lower. */
6122 result->height = (min (lower->y + lower->height,
6123 upper->y + upper->height)
6124 - result->y);
6125 intersection_p = 1;
6129 return intersection_p;
6136 static void
6137 frame_highlight (f)
6138 struct frame *f;
6140 /* We used to only do this if Vx_no_window_manager was non-nil, but
6141 the ICCCM (section 4.1.6) says that the window's border pixmap
6142 and border pixel are window attributes which are "private to the
6143 client", so we can always change it to whatever we want. */
6144 BLOCK_INPUT;
6145 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6146 f->output_data.x->border_pixel);
6147 UNBLOCK_INPUT;
6148 x_update_cursor (f, 1);
6151 static void
6152 frame_unhighlight (f)
6153 struct frame *f;
6155 /* We used to only do this if Vx_no_window_manager was non-nil, but
6156 the ICCCM (section 4.1.6) says that the window's border pixmap
6157 and border pixel are window attributes which are "private to the
6158 client", so we can always change it to whatever we want. */
6159 BLOCK_INPUT;
6160 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6161 f->output_data.x->border_tile);
6162 UNBLOCK_INPUT;
6163 x_update_cursor (f, 1);
6166 /* The focus has changed. Update the frames as necessary to reflect
6167 the new situation. Note that we can't change the selected frame
6168 here, because the Lisp code we are interrupting might become confused.
6169 Each event gets marked with the frame in which it occurred, so the
6170 Lisp code can tell when the switch took place by examining the events. */
6172 static void
6173 x_new_focus_frame (dpyinfo, frame)
6174 struct x_display_info *dpyinfo;
6175 struct frame *frame;
6177 struct frame *old_focus = dpyinfo->x_focus_frame;
6179 if (frame != dpyinfo->x_focus_frame)
6181 /* Set this before calling other routines, so that they see
6182 the correct value of x_focus_frame. */
6183 dpyinfo->x_focus_frame = frame;
6185 if (old_focus && old_focus->auto_lower)
6186 x_lower_frame (old_focus);
6188 #if 0
6189 selected_frame = frame;
6190 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6191 selected_frame);
6192 Fselect_window (selected_frame->selected_window);
6193 choose_minibuf_frame ();
6194 #endif /* ! 0 */
6196 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6197 pending_autoraise_frame = dpyinfo->x_focus_frame;
6198 else
6199 pending_autoraise_frame = 0;
6202 x_frame_rehighlight (dpyinfo);
6205 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6207 void
6208 x_mouse_leave (dpyinfo)
6209 struct x_display_info *dpyinfo;
6211 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6214 /* The focus has changed, or we have redirected a frame's focus to
6215 another frame (this happens when a frame uses a surrogate
6216 mini-buffer frame). Shift the highlight as appropriate.
6218 The FRAME argument doesn't necessarily have anything to do with which
6219 frame is being highlighted or un-highlighted; we only use it to find
6220 the appropriate X display info. */
6222 static void
6223 XTframe_rehighlight (frame)
6224 struct frame *frame;
6226 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6229 static void
6230 x_frame_rehighlight (dpyinfo)
6231 struct x_display_info *dpyinfo;
6233 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6235 if (dpyinfo->x_focus_frame)
6237 dpyinfo->x_highlight_frame
6238 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6239 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6240 : dpyinfo->x_focus_frame);
6241 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6243 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6244 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6247 else
6248 dpyinfo->x_highlight_frame = 0;
6250 if (dpyinfo->x_highlight_frame != old_highlight)
6252 if (old_highlight)
6253 frame_unhighlight (old_highlight);
6254 if (dpyinfo->x_highlight_frame)
6255 frame_highlight (dpyinfo->x_highlight_frame);
6261 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6263 /* Initialize mode_switch_bit and modifier_meaning. */
6264 static void
6265 x_find_modifier_meanings (dpyinfo)
6266 struct x_display_info *dpyinfo;
6268 int min_code, max_code;
6269 KeySym *syms;
6270 int syms_per_code;
6271 XModifierKeymap *mods;
6273 dpyinfo->meta_mod_mask = 0;
6274 dpyinfo->shift_lock_mask = 0;
6275 dpyinfo->alt_mod_mask = 0;
6276 dpyinfo->super_mod_mask = 0;
6277 dpyinfo->hyper_mod_mask = 0;
6279 #ifdef HAVE_X11R4
6280 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6281 #else
6282 min_code = dpyinfo->display->min_keycode;
6283 max_code = dpyinfo->display->max_keycode;
6284 #endif
6286 syms = XGetKeyboardMapping (dpyinfo->display,
6287 min_code, max_code - min_code + 1,
6288 &syms_per_code);
6289 mods = XGetModifierMapping (dpyinfo->display);
6291 /* Scan the modifier table to see which modifier bits the Meta and
6292 Alt keysyms are on. */
6294 int row, col; /* The row and column in the modifier table. */
6296 for (row = 3; row < 8; row++)
6297 for (col = 0; col < mods->max_keypermod; col++)
6299 KeyCode code
6300 = mods->modifiermap[(row * mods->max_keypermod) + col];
6302 /* Zeroes are used for filler. Skip them. */
6303 if (code == 0)
6304 continue;
6306 /* Are any of this keycode's keysyms a meta key? */
6308 int code_col;
6310 for (code_col = 0; code_col < syms_per_code; code_col++)
6312 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6314 switch (sym)
6316 case XK_Meta_L:
6317 case XK_Meta_R:
6318 dpyinfo->meta_mod_mask |= (1 << row);
6319 break;
6321 case XK_Alt_L:
6322 case XK_Alt_R:
6323 dpyinfo->alt_mod_mask |= (1 << row);
6324 break;
6326 case XK_Hyper_L:
6327 case XK_Hyper_R:
6328 dpyinfo->hyper_mod_mask |= (1 << row);
6329 break;
6331 case XK_Super_L:
6332 case XK_Super_R:
6333 dpyinfo->super_mod_mask |= (1 << row);
6334 break;
6336 case XK_Shift_Lock:
6337 /* Ignore this if it's not on the lock modifier. */
6338 if ((1 << row) == LockMask)
6339 dpyinfo->shift_lock_mask = LockMask;
6340 break;
6347 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6348 if (! dpyinfo->meta_mod_mask)
6350 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6351 dpyinfo->alt_mod_mask = 0;
6354 /* If some keys are both alt and meta,
6355 make them just meta, not alt. */
6356 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6358 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6361 XFree ((char *) syms);
6362 XFreeModifiermap (mods);
6365 /* Convert between the modifier bits X uses and the modifier bits
6366 Emacs uses. */
6368 static unsigned int
6369 x_x_to_emacs_modifiers (dpyinfo, state)
6370 struct x_display_info *dpyinfo;
6371 unsigned int state;
6373 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6374 | ((state & ControlMask) ? ctrl_modifier : 0)
6375 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6376 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6377 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6378 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6381 static unsigned int
6382 x_emacs_to_x_modifiers (dpyinfo, state)
6383 struct x_display_info *dpyinfo;
6384 unsigned int state;
6386 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6387 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6388 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6389 | ((state & shift_modifier) ? ShiftMask : 0)
6390 | ((state & ctrl_modifier) ? ControlMask : 0)
6391 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6394 /* Convert a keysym to its name. */
6396 char *
6397 x_get_keysym_name (keysym)
6398 KeySym keysym;
6400 char *value;
6402 BLOCK_INPUT;
6403 value = XKeysymToString (keysym);
6404 UNBLOCK_INPUT;
6406 return value;
6411 /* Mouse clicks and mouse movement. Rah. */
6413 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6414 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6415 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6416 not force the value into range. */
6418 void
6419 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6420 FRAME_PTR f;
6421 register int pix_x, pix_y;
6422 register int *x, *y;
6423 XRectangle *bounds;
6424 int noclip;
6426 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6427 even for negative values. */
6428 if (pix_x < 0)
6429 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6430 if (pix_y < 0)
6431 pix_y -= (f)->output_data.x->line_height - 1;
6433 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6434 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6436 if (bounds)
6438 bounds->width = FONT_WIDTH (f->output_data.x->font);
6439 bounds->height = f->output_data.x->line_height;
6440 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6441 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6444 if (!noclip)
6446 if (pix_x < 0)
6447 pix_x = 0;
6448 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6449 pix_x = FRAME_WINDOW_WIDTH (f);
6451 if (pix_y < 0)
6452 pix_y = 0;
6453 else if (pix_y > f->height)
6454 pix_y = f->height;
6457 *x = pix_x;
6458 *y = pix_y;
6462 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6463 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6464 can't tell the positions because W's display is not up to date,
6465 return 0. */
6468 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6469 struct window *w;
6470 int hpos, vpos;
6471 int *frame_x, *frame_y;
6473 int success_p;
6475 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6476 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6478 if (display_completed)
6480 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6481 struct glyph *glyph = row->glyphs[TEXT_AREA];
6482 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6484 *frame_y = row->y;
6485 *frame_x = row->x;
6486 while (glyph < end)
6488 *frame_x += glyph->pixel_width;
6489 ++glyph;
6492 success_p = 1;
6494 else
6496 *frame_y = *frame_x = 0;
6497 success_p = 0;
6500 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6501 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6502 return success_p;
6506 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6508 If the event is a button press, then note that we have grabbed
6509 the mouse. */
6511 static Lisp_Object
6512 construct_mouse_click (result, event, f)
6513 struct input_event *result;
6514 XButtonEvent *event;
6515 struct frame *f;
6517 /* Make the event type no_event; we'll change that when we decide
6518 otherwise. */
6519 result->kind = mouse_click;
6520 result->code = event->button - Button1;
6521 result->timestamp = event->time;
6522 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6523 event->state)
6524 | (event->type == ButtonRelease
6525 ? up_modifier
6526 : down_modifier));
6528 XSETINT (result->x, event->x);
6529 XSETINT (result->y, event->y);
6530 XSETFRAME (result->frame_or_window, f);
6531 result->arg = Qnil;
6532 return Qnil;
6536 /* Function to report a mouse movement to the mainstream Emacs code.
6537 The input handler calls this.
6539 We have received a mouse movement event, which is given in *event.
6540 If the mouse is over a different glyph than it was last time, tell
6541 the mainstream emacs code by setting mouse_moved. If not, ask for
6542 another motion event, so we can check again the next time it moves. */
6544 static XMotionEvent last_mouse_motion_event;
6545 static Lisp_Object last_mouse_motion_frame;
6547 static void
6548 note_mouse_movement (frame, event)
6549 FRAME_PTR frame;
6550 XMotionEvent *event;
6552 last_mouse_movement_time = event->time;
6553 last_mouse_motion_event = *event;
6554 XSETFRAME (last_mouse_motion_frame, frame);
6556 if (event->window != FRAME_X_WINDOW (frame))
6558 frame->mouse_moved = 1;
6559 last_mouse_scroll_bar = Qnil;
6560 note_mouse_highlight (frame, -1, -1);
6563 /* Has the mouse moved off the glyph it was on at the last sighting? */
6564 else if (event->x < last_mouse_glyph.x
6565 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6566 || event->y < last_mouse_glyph.y
6567 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6569 frame->mouse_moved = 1;
6570 last_mouse_scroll_bar = Qnil;
6571 note_mouse_highlight (frame, event->x, event->y);
6575 /* This is used for debugging, to turn off note_mouse_highlight. */
6577 int disable_mouse_highlight;
6581 /************************************************************************
6582 Mouse Face
6583 ************************************************************************/
6585 /* Find the glyph under window-relative coordinates X/Y in window W.
6586 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6587 strings. Return in *HPOS and *VPOS the row and column number of
6588 the glyph found. Return in *AREA the glyph area containing X.
6589 Value is a pointer to the glyph found or null if X/Y is not on
6590 text, or we can't tell because W's current matrix is not up to
6591 date. */
6593 static struct glyph *
6594 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6595 struct window *w;
6596 int x, y;
6597 int *hpos, *vpos, *area;
6598 int buffer_only_p;
6600 struct glyph *glyph, *end;
6601 struct glyph_row *row = NULL;
6602 int x0, i, left_area_width;
6604 /* Find row containing Y. Give up if some row is not enabled. */
6605 for (i = 0; i < w->current_matrix->nrows; ++i)
6607 row = MATRIX_ROW (w->current_matrix, i);
6608 if (!row->enabled_p)
6609 return NULL;
6610 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6611 break;
6614 *vpos = i;
6615 *hpos = 0;
6617 /* Give up if Y is not in the window. */
6618 if (i == w->current_matrix->nrows)
6619 return NULL;
6621 /* Get the glyph area containing X. */
6622 if (w->pseudo_window_p)
6624 *area = TEXT_AREA;
6625 x0 = 0;
6627 else
6629 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6630 if (x < left_area_width)
6632 *area = LEFT_MARGIN_AREA;
6633 x0 = 0;
6635 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6637 *area = TEXT_AREA;
6638 x0 = row->x + left_area_width;
6640 else
6642 *area = RIGHT_MARGIN_AREA;
6643 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6647 /* Find glyph containing X. */
6648 glyph = row->glyphs[*area];
6649 end = glyph + row->used[*area];
6650 while (glyph < end)
6652 if (x < x0 + glyph->pixel_width)
6654 if (w->pseudo_window_p)
6655 break;
6656 else if (!buffer_only_p || BUFFERP (glyph->object))
6657 break;
6660 x0 += glyph->pixel_width;
6661 ++glyph;
6664 if (glyph == end)
6665 return NULL;
6667 *hpos = glyph - row->glyphs[*area];
6668 return glyph;
6672 /* Convert frame-relative x/y to coordinates relative to window W.
6673 Takes pseudo-windows into account. */
6675 static void
6676 frame_to_window_pixel_xy (w, x, y)
6677 struct window *w;
6678 int *x, *y;
6680 if (w->pseudo_window_p)
6682 /* A pseudo-window is always full-width, and starts at the
6683 left edge of the frame, plus a frame border. */
6684 struct frame *f = XFRAME (w->frame);
6685 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6686 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6688 else
6690 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6691 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6696 /* Take proper action when mouse has moved to the mode or header line of
6697 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6698 mode line. X is relative to the start of the text display area of
6699 W, so the width of bitmap areas and scroll bars must be subtracted
6700 to get a position relative to the start of the mode line. */
6702 static void
6703 note_mode_line_highlight (w, x, mode_line_p)
6704 struct window *w;
6705 int x, mode_line_p;
6707 struct frame *f = XFRAME (w->frame);
6708 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6709 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6710 struct glyph_row *row;
6712 if (mode_line_p)
6713 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6714 else
6715 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6717 if (row->enabled_p)
6719 struct glyph *glyph, *end;
6720 Lisp_Object help, map;
6721 int x0;
6723 /* Find the glyph under X. */
6724 glyph = row->glyphs[TEXT_AREA];
6725 end = glyph + row->used[TEXT_AREA];
6726 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6727 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6729 while (glyph < end
6730 && x >= x0 + glyph->pixel_width)
6732 x0 += glyph->pixel_width;
6733 ++glyph;
6736 if (glyph < end
6737 && STRINGP (glyph->object)
6738 && XSTRING (glyph->object)->intervals
6739 && glyph->charpos >= 0
6740 && glyph->charpos < XSTRING (glyph->object)->size)
6742 /* If we're on a string with `help-echo' text property,
6743 arrange for the help to be displayed. This is done by
6744 setting the global variable help_echo to the help string. */
6745 help = Fget_text_property (make_number (glyph->charpos),
6746 Qhelp_echo, glyph->object);
6747 if (!NILP (help))
6749 help_echo = help;
6750 XSETWINDOW (help_echo_window, w);
6751 help_echo_object = glyph->object;
6752 help_echo_pos = glyph->charpos;
6755 /* Change the mouse pointer according to what is under X/Y. */
6756 map = Fget_text_property (make_number (glyph->charpos),
6757 Qlocal_map, glyph->object);
6758 if (KEYMAPP (map))
6759 cursor = f->output_data.x->nontext_cursor;
6760 else
6762 map = Fget_text_property (make_number (glyph->charpos),
6763 Qkeymap, glyph->object);
6764 if (KEYMAPP (map))
6765 cursor = f->output_data.x->nontext_cursor;
6770 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6774 /* Take proper action when the mouse has moved to position X, Y on
6775 frame F as regards highlighting characters that have mouse-face
6776 properties. Also de-highlighting chars where the mouse was before.
6777 X and Y can be negative or out of range. */
6779 static void
6780 note_mouse_highlight (f, x, y)
6781 struct frame *f;
6782 int x, y;
6784 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6785 int portion;
6786 Lisp_Object window;
6787 struct window *w;
6789 /* When a menu is active, don't highlight because this looks odd. */
6790 #ifdef USE_X_TOOLKIT
6791 if (popup_activated ())
6792 return;
6793 #endif
6795 if (disable_mouse_highlight
6796 || !f->glyphs_initialized_p)
6797 return;
6799 dpyinfo->mouse_face_mouse_x = x;
6800 dpyinfo->mouse_face_mouse_y = y;
6801 dpyinfo->mouse_face_mouse_frame = f;
6803 if (dpyinfo->mouse_face_defer)
6804 return;
6806 if (gc_in_progress)
6808 dpyinfo->mouse_face_deferred_gc = 1;
6809 return;
6812 /* Which window is that in? */
6813 window = window_from_coordinates (f, x, y, &portion, 1);
6815 /* If we were displaying active text in another window, clear that. */
6816 if (! EQ (window, dpyinfo->mouse_face_window))
6817 clear_mouse_face (dpyinfo);
6819 /* Not on a window -> return. */
6820 if (!WINDOWP (window))
6821 return;
6823 /* Convert to window-relative pixel coordinates. */
6824 w = XWINDOW (window);
6825 frame_to_window_pixel_xy (w, &x, &y);
6827 /* Handle tool-bar window differently since it doesn't display a
6828 buffer. */
6829 if (EQ (window, f->tool_bar_window))
6831 note_tool_bar_highlight (f, x, y);
6832 return;
6835 if (portion == 1 || portion == 3)
6837 /* Mouse is on the mode or top line. */
6838 note_mode_line_highlight (w, x, portion == 1);
6839 return;
6841 else if (portion == 2)
6842 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6843 f->output_data.x->horizontal_drag_cursor);
6844 else
6845 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6846 f->output_data.x->text_cursor);
6848 /* Are we in a window whose display is up to date?
6849 And verify the buffer's text has not changed. */
6850 if (/* Within text portion of the window. */
6851 portion == 0
6852 && EQ (w->window_end_valid, w->buffer)
6853 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6854 && (XFASTINT (w->last_overlay_modified)
6855 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6857 int hpos, vpos, pos, i, area;
6858 struct glyph *glyph;
6859 Lisp_Object object;
6861 /* Find the glyph under X/Y. */
6862 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6864 /* Clear mouse face if X/Y not over text. */
6865 if (glyph == NULL
6866 || area != TEXT_AREA
6867 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6869 clear_mouse_face (dpyinfo);
6870 return;
6873 pos = glyph->charpos;
6874 object = glyph->object;
6875 if (!STRINGP (object) && !BUFFERP (object))
6876 return;
6879 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6880 Lisp_Object *overlay_vec = NULL;
6881 int len, noverlays;
6882 struct buffer *obuf;
6883 int obegv, ozv;
6885 /* If we get an out-of-range value, return now; avoid an error. */
6886 if (BUFFERP (object) && pos > BUF_Z (XBUFFER (w->buffer)))
6887 return;
6889 /* Make the window's buffer temporarily current for
6890 overlays_at and compute_char_face. */
6891 obuf = current_buffer;
6892 current_buffer = XBUFFER (w->buffer);
6893 obegv = BEGV;
6894 ozv = ZV;
6895 BEGV = BEG;
6896 ZV = Z;
6898 /* Is this char mouse-active or does it have help-echo? */
6899 position = make_number (pos);
6901 if (BUFFERP (object))
6903 /* Put all the overlays we want in a vector in overlay_vec.
6904 Store the length in len. If there are more than 10, make
6905 enough space for all, and try again. */
6906 len = 10;
6907 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6908 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6909 if (noverlays > len)
6911 len = noverlays;
6912 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6913 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6916 /* Sort overlays into increasing priority order. */
6917 noverlays = sort_overlays (overlay_vec, noverlays, w);
6919 else
6920 noverlays = 0;
6922 /* Check mouse-face highlighting. */
6923 if (! (EQ (window, dpyinfo->mouse_face_window)
6924 && vpos >= dpyinfo->mouse_face_beg_row
6925 && vpos <= dpyinfo->mouse_face_end_row
6926 && (vpos > dpyinfo->mouse_face_beg_row
6927 || hpos >= dpyinfo->mouse_face_beg_col)
6928 && (vpos < dpyinfo->mouse_face_end_row
6929 || hpos < dpyinfo->mouse_face_end_col
6930 || dpyinfo->mouse_face_past_end))
6931 /* If there exists an overlay with mouse-face overlapping
6932 the one we are currently highlighting, we have to
6933 check if we enter the overlapping overlay, and then
6934 highlight only that. */
6935 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6936 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6939 /* Clear the display of the old active region, if any. */
6940 clear_mouse_face (dpyinfo);
6942 /* Find the highest priority overlay that has a mouse-face
6943 property. */
6944 overlay = Qnil;
6945 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6947 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6948 if (!NILP (mouse_face))
6949 overlay = overlay_vec[i];
6951 dpyinfo->mouse_face_overlay = overlay;
6953 /* If no overlay applies, get a text property. */
6954 if (NILP (overlay))
6955 mouse_face = Fget_text_property (position, Qmouse_face, object);
6957 /* Handle the overlay case. */
6958 if (!NILP (overlay))
6960 /* Find the range of text around this char that
6961 should be active. */
6962 Lisp_Object before, after;
6963 int ignore;
6965 before = Foverlay_start (overlay);
6966 after = Foverlay_end (overlay);
6967 /* Record this as the current active region. */
6968 fast_find_position (w, XFASTINT (before),
6969 &dpyinfo->mouse_face_beg_col,
6970 &dpyinfo->mouse_face_beg_row,
6971 &dpyinfo->mouse_face_beg_x,
6972 &dpyinfo->mouse_face_beg_y);
6973 dpyinfo->mouse_face_past_end
6974 = !fast_find_position (w, XFASTINT (after),
6975 &dpyinfo->mouse_face_end_col,
6976 &dpyinfo->mouse_face_end_row,
6977 &dpyinfo->mouse_face_end_x,
6978 &dpyinfo->mouse_face_end_y);
6979 dpyinfo->mouse_face_window = window;
6980 dpyinfo->mouse_face_face_id
6981 = face_at_buffer_position (w, pos, 0, 0,
6982 &ignore, pos + 1, 1);
6984 /* Display it as active. */
6985 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6987 /* Handle the text property case. */
6988 else if (!NILP (mouse_face) && BUFFERP (object))
6990 /* Find the range of text around this char that
6991 should be active. */
6992 Lisp_Object before, after, beginning, end;
6993 int ignore;
6995 beginning = Fmarker_position (w->start);
6996 end = make_number (BUF_Z (XBUFFER (object))
6997 - XFASTINT (w->window_end_pos));
6998 before
6999 = Fprevious_single_property_change (make_number (pos + 1),
7000 Qmouse_face,
7001 object, beginning);
7002 after
7003 = Fnext_single_property_change (position, Qmouse_face,
7004 object, end);
7006 /* Record this as the current active region. */
7007 fast_find_position (w, XFASTINT (before),
7008 &dpyinfo->mouse_face_beg_col,
7009 &dpyinfo->mouse_face_beg_row,
7010 &dpyinfo->mouse_face_beg_x,
7011 &dpyinfo->mouse_face_beg_y);
7012 dpyinfo->mouse_face_past_end
7013 = !fast_find_position (w, XFASTINT (after),
7014 &dpyinfo->mouse_face_end_col,
7015 &dpyinfo->mouse_face_end_row,
7016 &dpyinfo->mouse_face_end_x,
7017 &dpyinfo->mouse_face_end_y);
7018 dpyinfo->mouse_face_window = window;
7020 if (BUFFERP (object))
7021 dpyinfo->mouse_face_face_id
7022 = face_at_buffer_position (w, pos, 0, 0,
7023 &ignore, pos + 1, 1);
7025 /* Display it as active. */
7026 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7028 else if (!NILP (mouse_face) && STRINGP (object))
7030 Lisp_Object b, e;
7031 int ignore;
7033 b = Fprevious_single_property_change (make_number (pos + 1),
7034 Qmouse_face,
7035 object, Qnil);
7036 e = Fnext_single_property_change (position, Qmouse_face,
7037 object, Qnil);
7038 if (NILP (b))
7039 b = make_number (0);
7040 if (NILP (e))
7041 e = make_number (XSTRING (object)->size - 1);
7042 fast_find_string_pos (w, XINT (b), object,
7043 &dpyinfo->mouse_face_beg_col,
7044 &dpyinfo->mouse_face_beg_row,
7045 &dpyinfo->mouse_face_beg_x,
7046 &dpyinfo->mouse_face_beg_y, 0);
7047 fast_find_string_pos (w, XINT (e), object,
7048 &dpyinfo->mouse_face_end_col,
7049 &dpyinfo->mouse_face_end_row,
7050 &dpyinfo->mouse_face_end_x,
7051 &dpyinfo->mouse_face_end_y, 1);
7052 dpyinfo->mouse_face_past_end = 0;
7053 dpyinfo->mouse_face_window = window;
7054 dpyinfo->mouse_face_face_id
7055 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7056 glyph->face_id, 1);
7057 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7061 /* Look for a `help-echo' property. */
7063 Lisp_Object help, overlay;
7065 /* Check overlays first. */
7066 help = overlay = Qnil;
7067 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7069 overlay = overlay_vec[i];
7070 help = Foverlay_get (overlay, Qhelp_echo);
7073 if (!NILP (help))
7075 help_echo = help;
7076 help_echo_window = window;
7077 help_echo_object = overlay;
7078 help_echo_pos = pos;
7080 else
7082 Lisp_Object object = glyph->object;
7083 int charpos = glyph->charpos;
7085 /* Try text properties. */
7086 if (STRINGP (object)
7087 && charpos >= 0
7088 && charpos < XSTRING (object)->size)
7090 help = Fget_text_property (make_number (charpos),
7091 Qhelp_echo, object);
7092 if (NILP (help))
7094 /* If the string itself doesn't specify a help-echo,
7095 see if the buffer text ``under'' it does. */
7096 struct glyph_row *r
7097 = MATRIX_ROW (w->current_matrix, vpos);
7098 int start = MATRIX_ROW_START_CHARPOS (r);
7099 int pos = string_buffer_position (w, object, start);
7100 if (pos > 0)
7102 help = Fget_text_property (make_number (pos),
7103 Qhelp_echo, w->buffer);
7104 if (!NILP (help))
7106 charpos = pos;
7107 object = w->buffer;
7112 else if (BUFFERP (object)
7113 && charpos >= BEGV
7114 && charpos < ZV)
7115 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7116 object);
7118 if (!NILP (help))
7120 help_echo = help;
7121 help_echo_window = window;
7122 help_echo_object = object;
7123 help_echo_pos = charpos;
7128 BEGV = obegv;
7129 ZV = ozv;
7130 current_buffer = obuf;
7135 static void
7136 redo_mouse_highlight ()
7138 if (!NILP (last_mouse_motion_frame)
7139 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7140 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7141 last_mouse_motion_event.x,
7142 last_mouse_motion_event.y);
7147 /***********************************************************************
7148 Tool-bars
7149 ***********************************************************************/
7151 static int x_tool_bar_item P_ ((struct frame *, int, int,
7152 struct glyph **, int *, int *, int *));
7154 /* Tool-bar item index of the item on which a mouse button was pressed
7155 or -1. */
7157 static int last_tool_bar_item;
7160 /* Get information about the tool-bar item at position X/Y on frame F.
7161 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7162 the current matrix of the tool-bar window of F, or NULL if not
7163 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7164 item in F->tool_bar_items. Value is
7166 -1 if X/Y is not on a tool-bar item
7167 0 if X/Y is on the same item that was highlighted before.
7168 1 otherwise. */
7170 static int
7171 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7172 struct frame *f;
7173 int x, y;
7174 struct glyph **glyph;
7175 int *hpos, *vpos, *prop_idx;
7177 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7178 struct window *w = XWINDOW (f->tool_bar_window);
7179 int area;
7181 /* Find the glyph under X/Y. */
7182 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7183 if (*glyph == NULL)
7184 return -1;
7186 /* Get the start of this tool-bar item's properties in
7187 f->tool_bar_items. */
7188 if (!tool_bar_item_info (f, *glyph, prop_idx))
7189 return -1;
7191 /* Is mouse on the highlighted item? */
7192 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7193 && *vpos >= dpyinfo->mouse_face_beg_row
7194 && *vpos <= dpyinfo->mouse_face_end_row
7195 && (*vpos > dpyinfo->mouse_face_beg_row
7196 || *hpos >= dpyinfo->mouse_face_beg_col)
7197 && (*vpos < dpyinfo->mouse_face_end_row
7198 || *hpos < dpyinfo->mouse_face_end_col
7199 || dpyinfo->mouse_face_past_end))
7200 return 0;
7202 return 1;
7206 /* Handle mouse button event on the tool-bar of frame F, at
7207 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7208 or ButtonRelase. */
7210 static void
7211 x_handle_tool_bar_click (f, button_event)
7212 struct frame *f;
7213 XButtonEvent *button_event;
7215 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7216 struct window *w = XWINDOW (f->tool_bar_window);
7217 int hpos, vpos, prop_idx;
7218 struct glyph *glyph;
7219 Lisp_Object enabled_p;
7220 int x = button_event->x;
7221 int y = button_event->y;
7223 /* If not on the highlighted tool-bar item, return. */
7224 frame_to_window_pixel_xy (w, &x, &y);
7225 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7226 return;
7228 /* If item is disabled, do nothing. */
7229 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7230 if (NILP (enabled_p))
7231 return;
7233 if (button_event->type == ButtonPress)
7235 /* Show item in pressed state. */
7236 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7237 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7238 last_tool_bar_item = prop_idx;
7240 else
7242 Lisp_Object key, frame;
7243 struct input_event event;
7245 /* Show item in released state. */
7246 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7247 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7249 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7251 XSETFRAME (frame, f);
7252 event.kind = TOOL_BAR_EVENT;
7253 event.frame_or_window = frame;
7254 event.arg = frame;
7255 kbd_buffer_store_event (&event);
7257 event.kind = TOOL_BAR_EVENT;
7258 event.frame_or_window = frame;
7259 event.arg = key;
7260 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7261 button_event->state);
7262 kbd_buffer_store_event (&event);
7263 last_tool_bar_item = -1;
7268 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7269 tool-bar window-relative coordinates X/Y. Called from
7270 note_mouse_highlight. */
7272 static void
7273 note_tool_bar_highlight (f, x, y)
7274 struct frame *f;
7275 int x, y;
7277 Lisp_Object window = f->tool_bar_window;
7278 struct window *w = XWINDOW (window);
7279 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7280 int hpos, vpos;
7281 struct glyph *glyph;
7282 struct glyph_row *row;
7283 int i;
7284 Lisp_Object enabled_p;
7285 int prop_idx;
7286 enum draw_glyphs_face draw;
7287 int mouse_down_p, rc;
7289 /* Function note_mouse_highlight is called with negative x(y
7290 values when mouse moves outside of the frame. */
7291 if (x <= 0 || y <= 0)
7293 clear_mouse_face (dpyinfo);
7294 return;
7297 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7298 if (rc < 0)
7300 /* Not on tool-bar item. */
7301 clear_mouse_face (dpyinfo);
7302 return;
7304 else if (rc == 0)
7305 goto set_help_echo;
7307 clear_mouse_face (dpyinfo);
7309 /* Mouse is down, but on different tool-bar item? */
7310 mouse_down_p = (dpyinfo->grabbed
7311 && f == last_mouse_frame
7312 && FRAME_LIVE_P (f));
7313 if (mouse_down_p
7314 && last_tool_bar_item != prop_idx)
7315 return;
7317 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7318 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7320 /* If tool-bar item is not enabled, don't highlight it. */
7321 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7322 if (!NILP (enabled_p))
7324 /* Compute the x-position of the glyph. In front and past the
7325 image is a space. We include this is the highlighted area. */
7326 row = MATRIX_ROW (w->current_matrix, vpos);
7327 for (i = x = 0; i < hpos; ++i)
7328 x += row->glyphs[TEXT_AREA][i].pixel_width;
7330 /* Record this as the current active region. */
7331 dpyinfo->mouse_face_beg_col = hpos;
7332 dpyinfo->mouse_face_beg_row = vpos;
7333 dpyinfo->mouse_face_beg_x = x;
7334 dpyinfo->mouse_face_beg_y = row->y;
7335 dpyinfo->mouse_face_past_end = 0;
7337 dpyinfo->mouse_face_end_col = hpos + 1;
7338 dpyinfo->mouse_face_end_row = vpos;
7339 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7340 dpyinfo->mouse_face_end_y = row->y;
7341 dpyinfo->mouse_face_window = window;
7342 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7344 /* Display it as active. */
7345 show_mouse_face (dpyinfo, draw);
7346 dpyinfo->mouse_face_image_state = draw;
7349 set_help_echo:
7351 /* Set help_echo to a help string.to display for this tool-bar item.
7352 XTread_socket does the rest. */
7353 help_echo_object = help_echo_window = Qnil;
7354 help_echo_pos = -1;
7355 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7356 if (NILP (help_echo))
7357 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7362 /* Find the glyph matrix position of buffer position POS in window W.
7363 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7364 current glyphs must be up to date. If POS is above window start
7365 return (0, 0, 0, 0). If POS is after end of W, return end of
7366 last line in W. */
7368 static int
7369 fast_find_position (w, pos, hpos, vpos, x, y)
7370 struct window *w;
7371 int pos;
7372 int *hpos, *vpos, *x, *y;
7374 int i;
7375 int lastcol;
7376 int maybe_next_line_p = 0;
7377 int line_start_position;
7378 int yb = window_text_bottom_y (w);
7379 struct glyph_row *row, *best_row;
7380 int row_vpos, best_row_vpos;
7381 int current_x;
7383 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7384 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7386 while (row->y < yb)
7388 if (row->used[TEXT_AREA])
7389 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7390 else
7391 line_start_position = 0;
7393 if (line_start_position > pos)
7394 break;
7395 /* If the position sought is the end of the buffer,
7396 don't include the blank lines at the bottom of the window. */
7397 else if (line_start_position == pos
7398 && pos == BUF_ZV (XBUFFER (w->buffer)))
7400 maybe_next_line_p = 1;
7401 break;
7403 else if (line_start_position > 0)
7405 best_row = row;
7406 best_row_vpos = row_vpos;
7409 if (row->y + row->height >= yb)
7410 break;
7412 ++row;
7413 ++row_vpos;
7416 /* Find the right column within BEST_ROW. */
7417 lastcol = 0;
7418 current_x = best_row->x;
7419 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7421 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7422 int charpos;
7424 charpos = glyph->charpos;
7425 if (charpos == pos)
7427 *hpos = i;
7428 *vpos = best_row_vpos;
7429 *x = current_x;
7430 *y = best_row->y;
7431 return 1;
7433 else if (charpos > pos)
7434 break;
7435 else if (charpos > 0)
7436 lastcol = i;
7438 current_x += glyph->pixel_width;
7441 /* If we're looking for the end of the buffer,
7442 and we didn't find it in the line we scanned,
7443 use the start of the following line. */
7444 if (maybe_next_line_p)
7446 ++best_row;
7447 ++best_row_vpos;
7448 lastcol = 0;
7449 current_x = best_row->x;
7452 *vpos = best_row_vpos;
7453 *hpos = lastcol + 1;
7454 *x = current_x;
7455 *y = best_row->y;
7456 return 0;
7460 /* Find the position of the the glyph for position POS in OBJECT in
7461 window W's current matrix, and return in *X/*Y the pixel
7462 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7464 RIGHT_P non-zero means return the position of the right edge of the
7465 glyph, RIGHT_P zero means return the left edge position.
7467 If no glyph for POS exists in the matrix, return the position of
7468 the glyph with the next smaller position that is in the matrix, if
7469 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7470 exists in the matrix, return the position of the glyph with the
7471 next larger position in OBJECT.
7473 Value is non-zero if a glyph was found. */
7475 static int
7476 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7477 struct window *w;
7478 int pos;
7479 Lisp_Object object;
7480 int *hpos, *vpos, *x, *y;
7481 int right_p;
7483 int yb = window_text_bottom_y (w);
7484 struct glyph_row *r;
7485 struct glyph *best_glyph = NULL;
7486 struct glyph_row *best_row = NULL;
7487 int best_x = 0;
7489 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7490 r->enabled_p && r->y < yb;
7491 ++r)
7493 struct glyph *g = r->glyphs[TEXT_AREA];
7494 struct glyph *e = g + r->used[TEXT_AREA];
7495 int gx;
7497 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7498 if (EQ (g->object, object))
7500 if (g->charpos == pos)
7502 best_glyph = g;
7503 best_x = gx;
7504 best_row = r;
7505 goto found;
7507 else if (best_glyph == NULL
7508 || ((abs (g->charpos - pos)
7509 < abs (best_glyph->charpos - pos))
7510 && (right_p
7511 ? g->charpos < pos
7512 : g->charpos > pos)))
7514 best_glyph = g;
7515 best_x = gx;
7516 best_row = r;
7521 found:
7523 if (best_glyph)
7525 *x = best_x;
7526 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7528 if (right_p)
7530 *x += best_glyph->pixel_width;
7531 ++*hpos;
7534 *y = best_row->y;
7535 *vpos = best_row - w->current_matrix->rows;
7538 return best_glyph != NULL;
7542 /* Display the active region described by mouse_face_*
7543 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7545 static void
7546 show_mouse_face (dpyinfo, draw)
7547 struct x_display_info *dpyinfo;
7548 enum draw_glyphs_face draw;
7550 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7551 struct frame *f = XFRAME (WINDOW_FRAME (w));
7552 int i;
7553 int cursor_off_p = 0;
7554 struct cursor_pos saved_cursor;
7556 saved_cursor = output_cursor;
7558 /* If window is in the process of being destroyed, don't bother
7559 to do anything. */
7560 if (w->current_matrix == NULL)
7561 goto set_x_cursor;
7563 /* Recognize when we are called to operate on rows that don't exist
7564 anymore. This can happen when a window is split. */
7565 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7566 goto set_x_cursor;
7568 set_output_cursor (&w->phys_cursor);
7570 /* Note that mouse_face_beg_row etc. are window relative. */
7571 for (i = dpyinfo->mouse_face_beg_row;
7572 i <= dpyinfo->mouse_face_end_row;
7573 i++)
7575 int start_hpos, end_hpos, start_x;
7576 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7578 /* Don't do anything if row doesn't have valid contents. */
7579 if (!row->enabled_p)
7580 continue;
7582 /* For all but the first row, the highlight starts at column 0. */
7583 if (i == dpyinfo->mouse_face_beg_row)
7585 start_hpos = dpyinfo->mouse_face_beg_col;
7586 start_x = dpyinfo->mouse_face_beg_x;
7588 else
7590 start_hpos = 0;
7591 start_x = 0;
7594 if (i == dpyinfo->mouse_face_end_row)
7595 end_hpos = dpyinfo->mouse_face_end_col;
7596 else
7597 end_hpos = row->used[TEXT_AREA];
7599 /* If the cursor's in the text we are about to rewrite, turn the
7600 cursor off. */
7601 if (!w->pseudo_window_p
7602 && i == output_cursor.vpos
7603 && output_cursor.hpos >= start_hpos - 1
7604 && output_cursor.hpos <= end_hpos)
7606 x_update_window_cursor (w, 0);
7607 cursor_off_p = 1;
7610 if (end_hpos > start_hpos)
7612 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7613 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7614 start_hpos, end_hpos, draw, NULL, NULL, 0);
7618 /* If we turned the cursor off, turn it back on. */
7619 if (cursor_off_p)
7620 x_display_cursor (w, 1,
7621 output_cursor.hpos, output_cursor.vpos,
7622 output_cursor.x, output_cursor.y);
7624 output_cursor = saved_cursor;
7626 set_x_cursor:
7628 /* Change the mouse cursor. */
7629 if (draw == DRAW_NORMAL_TEXT)
7630 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7631 f->output_data.x->text_cursor);
7632 else if (draw == DRAW_MOUSE_FACE)
7633 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7634 f->output_data.x->cross_cursor);
7635 else
7636 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7637 f->output_data.x->nontext_cursor);
7640 /* Clear out the mouse-highlighted active region.
7641 Redraw it un-highlighted first. */
7643 void
7644 clear_mouse_face (dpyinfo)
7645 struct x_display_info *dpyinfo;
7647 #if 0 /* This prevents redrawing tool bar items when changing from one
7648 to another while a tooltip is open, so don't do it. */
7649 if (!NILP (tip_frame))
7650 return;
7651 #endif
7653 if (! NILP (dpyinfo->mouse_face_window))
7654 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7656 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7657 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7658 dpyinfo->mouse_face_window = Qnil;
7662 /* Clear any mouse-face on window W. This function is part of the
7663 redisplay interface, and is called from try_window_id and similar
7664 functions to ensure the mouse-highlight is off. */
7666 static void
7667 x_clear_mouse_face (w)
7668 struct window *w;
7670 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7671 Lisp_Object window;
7673 BLOCK_INPUT;
7674 XSETWINDOW (window, w);
7675 if (EQ (window, dpyinfo->mouse_face_window))
7676 clear_mouse_face (dpyinfo);
7677 UNBLOCK_INPUT;
7681 /* Just discard the mouse face information for frame F, if any.
7682 This is used when the size of F is changed. */
7684 void
7685 cancel_mouse_face (f)
7686 FRAME_PTR f;
7688 Lisp_Object window;
7689 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7691 window = dpyinfo->mouse_face_window;
7692 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7694 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7695 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7696 dpyinfo->mouse_face_window = Qnil;
7701 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7704 /* Try to determine frame pixel position and size of the glyph under
7705 frame pixel coordinates X/Y on frame F . Return the position and
7706 size in *RECT. Value is non-zero if we could compute these
7707 values. */
7709 static int
7710 glyph_rect (f, x, y, rect)
7711 struct frame *f;
7712 int x, y;
7713 XRectangle *rect;
7715 Lisp_Object window;
7716 int part, found = 0;
7718 window = window_from_coordinates (f, x, y, &part, 0);
7719 if (!NILP (window))
7721 struct window *w = XWINDOW (window);
7722 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7723 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7724 int area;
7726 frame_to_window_pixel_xy (w, &x, &y);
7728 for (; !found && r < end && r->enabled_p; ++r)
7729 if (r->y >= y)
7731 struct glyph *g = r->glyphs[TEXT_AREA];
7732 struct glyph *end = g + r->used[TEXT_AREA];
7733 int gx;
7735 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7736 if (gx >= x)
7738 rect->width = g->pixel_width;
7739 rect->height = r->height;
7740 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7741 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7742 found = 1;
7747 return found;
7751 /* Return the current position of the mouse.
7752 *FP should be a frame which indicates which display to ask about.
7754 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7755 and *PART to the frame, window, and scroll bar part that the mouse
7756 is over. Set *X and *Y to the portion and whole of the mouse's
7757 position on the scroll bar.
7759 If the mouse movement started elsewhere, set *FP to the frame the
7760 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7761 the mouse is over.
7763 Set *TIME to the server time-stamp for the time at which the mouse
7764 was at this position.
7766 Don't store anything if we don't have a valid set of values to report.
7768 This clears the mouse_moved flag, so we can wait for the next mouse
7769 movement. */
7771 static void
7772 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7773 FRAME_PTR *fp;
7774 int insist;
7775 Lisp_Object *bar_window;
7776 enum scroll_bar_part *part;
7777 Lisp_Object *x, *y;
7778 unsigned long *time;
7780 FRAME_PTR f1;
7782 BLOCK_INPUT;
7784 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7785 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7786 else
7788 Window root;
7789 int root_x, root_y;
7791 Window dummy_window;
7792 int dummy;
7794 Lisp_Object frame, tail;
7796 /* Clear the mouse-moved flag for every frame on this display. */
7797 FOR_EACH_FRAME (tail, frame)
7798 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7799 XFRAME (frame)->mouse_moved = 0;
7801 last_mouse_scroll_bar = Qnil;
7803 /* Figure out which root window we're on. */
7804 XQueryPointer (FRAME_X_DISPLAY (*fp),
7805 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7807 /* The root window which contains the pointer. */
7808 &root,
7810 /* Trash which we can't trust if the pointer is on
7811 a different screen. */
7812 &dummy_window,
7814 /* The position on that root window. */
7815 &root_x, &root_y,
7817 /* More trash we can't trust. */
7818 &dummy, &dummy,
7820 /* Modifier keys and pointer buttons, about which
7821 we don't care. */
7822 (unsigned int *) &dummy);
7824 /* Now we have a position on the root; find the innermost window
7825 containing the pointer. */
7827 Window win, child;
7828 int win_x, win_y;
7829 int parent_x = 0, parent_y = 0;
7830 int count;
7832 win = root;
7834 /* XTranslateCoordinates can get errors if the window
7835 structure is changing at the same time this function
7836 is running. So at least we must not crash from them. */
7838 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7840 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7841 && FRAME_LIVE_P (last_mouse_frame))
7843 /* If mouse was grabbed on a frame, give coords for that frame
7844 even if the mouse is now outside it. */
7845 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7847 /* From-window, to-window. */
7848 root, FRAME_X_WINDOW (last_mouse_frame),
7850 /* From-position, to-position. */
7851 root_x, root_y, &win_x, &win_y,
7853 /* Child of win. */
7854 &child);
7855 f1 = last_mouse_frame;
7857 else
7859 while (1)
7861 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7863 /* From-window, to-window. */
7864 root, win,
7866 /* From-position, to-position. */
7867 root_x, root_y, &win_x, &win_y,
7869 /* Child of win. */
7870 &child);
7872 if (child == None || child == win)
7873 break;
7875 win = child;
7876 parent_x = win_x;
7877 parent_y = win_y;
7880 /* Now we know that:
7881 win is the innermost window containing the pointer
7882 (XTC says it has no child containing the pointer),
7883 win_x and win_y are the pointer's position in it
7884 (XTC did this the last time through), and
7885 parent_x and parent_y are the pointer's position in win's parent.
7886 (They are what win_x and win_y were when win was child.
7887 If win is the root window, it has no parent, and
7888 parent_{x,y} are invalid, but that's okay, because we'll
7889 never use them in that case.) */
7891 /* Is win one of our frames? */
7892 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7894 #ifdef USE_X_TOOLKIT
7895 /* If we end up with the menu bar window, say it's not
7896 on the frame. */
7897 if (f1 != NULL
7898 && f1->output_data.x->menubar_widget
7899 && win == XtWindow (f1->output_data.x->menubar_widget))
7900 f1 = NULL;
7901 #endif /* USE_X_TOOLKIT */
7904 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7905 f1 = 0;
7907 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7909 /* If not, is it one of our scroll bars? */
7910 if (! f1)
7912 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7914 if (bar)
7916 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7917 win_x = parent_x;
7918 win_y = parent_y;
7922 if (f1 == 0 && insist > 0)
7923 f1 = SELECTED_FRAME ();
7925 if (f1)
7927 /* Ok, we found a frame. Store all the values.
7928 last_mouse_glyph is a rectangle used to reduce the
7929 generation of mouse events. To not miss any motion
7930 events, we must divide the frame into rectangles of the
7931 size of the smallest character that could be displayed
7932 on it, i.e. into the same rectangles that matrices on
7933 the frame are divided into. */
7935 int width, height, gx, gy;
7936 XRectangle rect;
7938 if (glyph_rect (f1, win_x, win_y, &rect))
7939 last_mouse_glyph = rect;
7940 else
7942 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7943 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7944 gx = win_x;
7945 gy = win_y;
7947 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7948 round down even for negative values. */
7949 if (gx < 0)
7950 gx -= width - 1;
7951 if (gy < 0)
7952 gy -= height - 1;
7953 gx = (gx + width - 1) / width * width;
7954 gy = (gy + height - 1) / height * height;
7956 last_mouse_glyph.width = width;
7957 last_mouse_glyph.height = height;
7958 last_mouse_glyph.x = gx;
7959 last_mouse_glyph.y = gy;
7962 *bar_window = Qnil;
7963 *part = 0;
7964 *fp = f1;
7965 XSETINT (*x, win_x);
7966 XSETINT (*y, win_y);
7967 *time = last_mouse_movement_time;
7972 UNBLOCK_INPUT;
7976 #ifdef USE_X_TOOLKIT
7978 /* Atimer callback function for TIMER. Called every 0.1s to process
7979 Xt timeouts, if needed. We must avoid calling XtAppPending as
7980 much as possible because that function does an implicit XFlush
7981 that slows us down. */
7983 static void
7984 x_process_timeouts (timer)
7985 struct atimer *timer;
7987 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7989 BLOCK_INPUT;
7990 while (XtAppPending (Xt_app_con) & XtIMTimer)
7991 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7992 UNBLOCK_INPUT;
7996 #endif /* USE_X_TOOLKIT */
7999 /* Scroll bar support. */
8001 /* Given an X window ID, find the struct scroll_bar which manages it.
8002 This can be called in GC, so we have to make sure to strip off mark
8003 bits. */
8005 static struct scroll_bar *
8006 x_window_to_scroll_bar (window_id)
8007 Window window_id;
8009 Lisp_Object tail;
8011 for (tail = Vframe_list;
8012 XGCTYPE (tail) == Lisp_Cons;
8013 tail = XCDR (tail))
8015 Lisp_Object frame, bar, condemned;
8017 frame = XCAR (tail);
8018 /* All elements of Vframe_list should be frames. */
8019 if (! GC_FRAMEP (frame))
8020 abort ();
8022 /* Scan this frame's scroll bar list for a scroll bar with the
8023 right window ID. */
8024 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8025 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8026 /* This trick allows us to search both the ordinary and
8027 condemned scroll bar lists with one loop. */
8028 ! GC_NILP (bar) || (bar = condemned,
8029 condemned = Qnil,
8030 ! GC_NILP (bar));
8031 bar = XSCROLL_BAR (bar)->next)
8032 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8033 return XSCROLL_BAR (bar);
8036 return 0;
8041 /************************************************************************
8042 Toolkit scroll bars
8043 ************************************************************************/
8045 #ifdef USE_TOOLKIT_SCROLL_BARS
8047 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8048 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8049 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8050 struct scroll_bar *));
8051 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8052 int, int, int));
8055 /* Id of action hook installed for scroll bars. */
8057 static XtActionHookId action_hook_id;
8059 /* Lisp window being scrolled. Set when starting to interact with
8060 a toolkit scroll bar, reset to nil when ending the interaction. */
8062 static Lisp_Object window_being_scrolled;
8064 /* Last scroll bar part sent in xm_scroll_callback. */
8066 static int last_scroll_bar_part;
8068 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8069 that movements of 1/20 of the screen size are mapped to up/down. */
8071 static Boolean xaw3d_arrow_scroll;
8073 /* Whether the drag scrolling maintains the mouse at the top of the
8074 thumb. If not, resizing the thumb needs to be done more carefully
8075 to avoid jerkyness. */
8077 static Boolean xaw3d_pick_top;
8080 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8081 bars are used.. The hook is responsible for detecting when
8082 the user ends an interaction with the scroll bar, and generates
8083 a `end-scroll' scroll_bar_click' event if so. */
8085 static void
8086 xt_action_hook (widget, client_data, action_name, event, params,
8087 num_params)
8088 Widget widget;
8089 XtPointer client_data;
8090 String action_name;
8091 XEvent *event;
8092 String *params;
8093 Cardinal *num_params;
8095 int scroll_bar_p;
8096 char *end_action;
8098 #ifdef USE_MOTIF
8099 scroll_bar_p = XmIsScrollBar (widget);
8100 end_action = "Release";
8101 #else /* !USE_MOTIF i.e. use Xaw */
8102 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8103 end_action = "EndScroll";
8104 #endif /* USE_MOTIF */
8106 if (scroll_bar_p
8107 && strcmp (action_name, end_action) == 0
8108 && WINDOWP (window_being_scrolled))
8110 struct window *w;
8112 x_send_scroll_bar_event (window_being_scrolled,
8113 scroll_bar_end_scroll, 0, 0);
8114 w = XWINDOW (window_being_scrolled);
8115 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8116 window_being_scrolled = Qnil;
8117 last_scroll_bar_part = -1;
8119 /* Xt timeouts no longer needed. */
8120 toolkit_scroll_bar_interaction = 0;
8124 /* A vector of windows used for communication between
8125 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8127 static struct window **scroll_bar_windows;
8128 static int scroll_bar_windows_size;
8131 /* Send a client message with message type Xatom_Scrollbar for a
8132 scroll action to the frame of WINDOW. PART is a value identifying
8133 the part of the scroll bar that was clicked on. PORTION is the
8134 amount to scroll of a whole of WHOLE. */
8136 static void
8137 x_send_scroll_bar_event (window, part, portion, whole)
8138 Lisp_Object window;
8139 int part, portion, whole;
8141 XEvent event;
8142 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8143 struct window *w = XWINDOW (window);
8144 struct frame *f = XFRAME (w->frame);
8145 int i;
8147 BLOCK_INPUT;
8149 /* Construct a ClientMessage event to send to the frame. */
8150 ev->type = ClientMessage;
8151 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8152 ev->display = FRAME_X_DISPLAY (f);
8153 ev->window = FRAME_X_WINDOW (f);
8154 ev->format = 32;
8156 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8157 not enough to store a pointer or Lisp_Object on a 64 bit system.
8158 So, store the window in scroll_bar_windows and pass the index
8159 into that array in the event. */
8160 for (i = 0; i < scroll_bar_windows_size; ++i)
8161 if (scroll_bar_windows[i] == NULL)
8162 break;
8164 if (i == scroll_bar_windows_size)
8166 int new_size = max (10, 2 * scroll_bar_windows_size);
8167 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8168 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8170 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8171 nbytes);
8172 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8173 scroll_bar_windows_size = new_size;
8176 scroll_bar_windows[i] = w;
8177 ev->data.l[0] = (long) i;
8178 ev->data.l[1] = (long) part;
8179 ev->data.l[2] = (long) 0;
8180 ev->data.l[3] = (long) portion;
8181 ev->data.l[4] = (long) whole;
8183 /* Make Xt timeouts work while the scroll bar is active. */
8184 toolkit_scroll_bar_interaction = 1;
8186 /* Setting the event mask to zero means that the message will
8187 be sent to the client that created the window, and if that
8188 window no longer exists, no event will be sent. */
8189 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8190 UNBLOCK_INPUT;
8194 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8195 in *IEVENT. */
8197 static void
8198 x_scroll_bar_to_input_event (event, ievent)
8199 XEvent *event;
8200 struct input_event *ievent;
8202 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8203 Lisp_Object window;
8204 struct frame *f;
8205 struct window *w;
8207 w = scroll_bar_windows[ev->data.l[0]];
8208 scroll_bar_windows[ev->data.l[0]] = NULL;
8210 XSETWINDOW (window, w);
8211 f = XFRAME (w->frame);
8213 ievent->kind = scroll_bar_click;
8214 ievent->frame_or_window = window;
8215 ievent->arg = Qnil;
8216 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8217 ievent->part = ev->data.l[1];
8218 ievent->code = ev->data.l[2];
8219 ievent->x = make_number ((int) ev->data.l[3]);
8220 ievent->y = make_number ((int) ev->data.l[4]);
8221 ievent->modifiers = 0;
8225 #ifdef USE_MOTIF
8227 /* Minimum and maximum values used for Motif scroll bars. */
8229 #define XM_SB_MIN 1
8230 #define XM_SB_MAX 10000000
8231 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8234 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8235 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8236 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8238 static void
8239 xm_scroll_callback (widget, client_data, call_data)
8240 Widget widget;
8241 XtPointer client_data, call_data;
8243 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8244 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8245 double percent;
8246 int part = -1, whole = 0, portion = 0;
8248 switch (cs->reason)
8250 case XmCR_DECREMENT:
8251 bar->dragging = Qnil;
8252 part = scroll_bar_up_arrow;
8253 break;
8255 case XmCR_INCREMENT:
8256 bar->dragging = Qnil;
8257 part = scroll_bar_down_arrow;
8258 break;
8260 case XmCR_PAGE_DECREMENT:
8261 bar->dragging = Qnil;
8262 part = scroll_bar_above_handle;
8263 break;
8265 case XmCR_PAGE_INCREMENT:
8266 bar->dragging = Qnil;
8267 part = scroll_bar_below_handle;
8268 break;
8270 case XmCR_TO_TOP:
8271 bar->dragging = Qnil;
8272 part = scroll_bar_to_top;
8273 break;
8275 case XmCR_TO_BOTTOM:
8276 bar->dragging = Qnil;
8277 part = scroll_bar_to_bottom;
8278 break;
8280 case XmCR_DRAG:
8282 int slider_size;
8283 int dragging_down_p = (INTEGERP (bar->dragging)
8284 && XINT (bar->dragging) <= cs->value);
8286 /* Get the slider size. */
8287 BLOCK_INPUT;
8288 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8289 UNBLOCK_INPUT;
8291 /* At the max position of the scroll bar, do a line-wise
8292 movement. Without doing anything, we would be called with
8293 the same cs->value again and again. If we want to make
8294 sure that we can reach the end of the buffer, we have to do
8295 something.
8297 Implementation note: setting bar->dragging always to
8298 cs->value gives a smoother movement at the max position.
8299 Setting it to nil when doing line-wise movement gives
8300 a better slider behavior. */
8302 if (cs->value + slider_size == XM_SB_MAX
8303 || (dragging_down_p
8304 && last_scroll_bar_part == scroll_bar_down_arrow))
8306 part = scroll_bar_down_arrow;
8307 bar->dragging = Qnil;
8309 else
8311 whole = XM_SB_RANGE;
8312 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8313 part = scroll_bar_handle;
8314 bar->dragging = make_number (cs->value);
8317 break;
8319 case XmCR_VALUE_CHANGED:
8320 break;
8323 if (part >= 0)
8325 window_being_scrolled = bar->window;
8326 last_scroll_bar_part = part;
8327 x_send_scroll_bar_event (bar->window, part, portion, whole);
8332 #else /* !USE_MOTIF, i.e. Xaw. */
8335 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8336 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8337 scroll bar struct. CALL_DATA is a pointer to a float saying where
8338 the thumb is. */
8340 static void
8341 xaw_jump_callback (widget, client_data, call_data)
8342 Widget widget;
8343 XtPointer client_data, call_data;
8345 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8346 float top = *(float *) call_data;
8347 float shown;
8348 int whole, portion, height;
8349 int part;
8351 /* Get the size of the thumb, a value between 0 and 1. */
8352 BLOCK_INPUT;
8353 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8354 UNBLOCK_INPUT;
8356 whole = 10000000;
8357 portion = shown < 1 ? top * whole : 0;
8359 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8360 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8361 the bottom, so we force the scrolling whenever we see that we're
8362 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8363 we try to ensure that we always stay two pixels away from the
8364 bottom). */
8365 part = scroll_bar_down_arrow;
8366 else
8367 part = scroll_bar_handle;
8369 window_being_scrolled = bar->window;
8370 bar->dragging = make_number (portion);
8371 last_scroll_bar_part = part;
8372 x_send_scroll_bar_event (bar->window, part, portion, whole);
8376 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8377 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8378 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8379 the scroll bar. CALL_DATA is an integer specifying the action that
8380 has taken place. It's magnitude is in the range 0..height of the
8381 scroll bar. Negative values mean scroll towards buffer start.
8382 Values < height of scroll bar mean line-wise movement. */
8384 static void
8385 xaw_scroll_callback (widget, client_data, call_data)
8386 Widget widget;
8387 XtPointer client_data, call_data;
8389 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8390 int position = (int) call_data;
8391 Dimension height;
8392 int part;
8394 /* Get the height of the scroll bar. */
8395 BLOCK_INPUT;
8396 XtVaGetValues (widget, XtNheight, &height, NULL);
8397 UNBLOCK_INPUT;
8399 if (abs (position) >= height)
8400 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8402 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8403 it maps line-movement to call_data = max(5, height/20). */
8404 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8405 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8406 else
8407 part = scroll_bar_move_ratio;
8409 window_being_scrolled = bar->window;
8410 bar->dragging = Qnil;
8411 last_scroll_bar_part = part;
8412 x_send_scroll_bar_event (bar->window, part, position, height);
8416 #endif /* not USE_MOTIF */
8419 /* Create the widget for scroll bar BAR on frame F. Record the widget
8420 and X window of the scroll bar in BAR. */
8422 static void
8423 x_create_toolkit_scroll_bar (f, bar)
8424 struct frame *f;
8425 struct scroll_bar *bar;
8427 Window xwindow;
8428 Widget widget;
8429 Arg av[20];
8430 int ac = 0;
8431 char *scroll_bar_name = "verticalScrollBar";
8432 unsigned long pixel;
8434 BLOCK_INPUT;
8436 #ifdef USE_MOTIF
8437 /* Set resources. Create the widget. */
8438 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8439 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8440 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8441 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8442 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8443 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8444 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8446 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8447 if (pixel != -1)
8449 XtSetArg (av[ac], XmNforeground, pixel);
8450 ++ac;
8453 pixel = f->output_data.x->scroll_bar_background_pixel;
8454 if (pixel != -1)
8456 XtSetArg (av[ac], XmNbackground, pixel);
8457 ++ac;
8460 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8461 scroll_bar_name, av, ac);
8463 /* Add one callback for everything that can happen. */
8464 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8465 (XtPointer) bar);
8466 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8467 (XtPointer) bar);
8468 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8469 (XtPointer) bar);
8470 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8471 (XtPointer) bar);
8472 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8473 (XtPointer) bar);
8474 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8475 (XtPointer) bar);
8476 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8477 (XtPointer) bar);
8479 /* Realize the widget. Only after that is the X window created. */
8480 XtRealizeWidget (widget);
8482 /* Set the cursor to an arrow. I didn't find a resource to do that.
8483 And I'm wondering why it hasn't an arrow cursor by default. */
8484 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8485 f->output_data.x->nontext_cursor);
8487 #else /* !USE_MOTIF i.e. use Xaw */
8489 /* Set resources. Create the widget. The background of the
8490 Xaw3d scroll bar widget is a little bit light for my taste.
8491 We don't alter it here to let users change it according
8492 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8493 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8494 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8495 /* For smoother scrolling with Xaw3d -sm */
8496 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8497 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8499 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8500 if (pixel != -1)
8502 XtSetArg (av[ac], XtNforeground, pixel);
8503 ++ac;
8506 pixel = f->output_data.x->scroll_bar_background_pixel;
8507 if (pixel != -1)
8509 XtSetArg (av[ac], XtNbackground, pixel);
8510 ++ac;
8513 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8514 f->output_data.x->edit_widget, av, ac);
8517 char *initial = "";
8518 char *val = initial;
8519 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8520 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8521 if (val == initial)
8522 { /* ARROW_SCROLL */
8523 xaw3d_arrow_scroll = True;
8524 /* Isn't that just a personal preference ? -sm */
8525 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8529 /* Define callbacks. */
8530 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8531 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8532 (XtPointer) bar);
8534 /* Realize the widget. Only after that is the X window created. */
8535 XtRealizeWidget (widget);
8537 #endif /* !USE_MOTIF */
8539 /* Install an action hook that let's us detect when the user
8540 finishes interacting with a scroll bar. */
8541 if (action_hook_id == 0)
8542 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8544 /* Remember X window and widget in the scroll bar vector. */
8545 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8546 xwindow = XtWindow (widget);
8547 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8549 UNBLOCK_INPUT;
8553 /* Set the thumb size and position of scroll bar BAR. We are currently
8554 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8556 static void
8557 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8558 struct scroll_bar *bar;
8559 int portion, position, whole;
8561 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8562 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8563 float top, shown;
8565 if (whole == 0)
8566 top = 0, shown = 1;
8567 else
8569 top = (float) position / whole;
8570 shown = (float) portion / whole;
8573 BLOCK_INPUT;
8575 #ifdef USE_MOTIF
8577 int size, value;
8578 XmScrollBarWidget sb;
8580 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8581 is the scroll bar's maximum and MIN is the scroll bar's minimum
8582 value. */
8583 size = shown * XM_SB_RANGE;
8584 size = min (size, XM_SB_RANGE);
8585 size = max (size, 1);
8587 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8588 value = top * XM_SB_RANGE;
8589 value = min (value, XM_SB_MAX - size);
8590 value = max (value, XM_SB_MIN);
8592 if (NILP (bar->dragging))
8593 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8594 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8595 /* This has the negative side effect that the slider value is
8596 not what it would be if we scrolled here using line-wise or
8597 page-wise movement. */
8598 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8599 else
8601 /* If currently dragging, only update the slider size.
8602 This reduces flicker effects. */
8603 int old_value, old_size, increment, page_increment;
8605 XmScrollBarGetValues (widget, &old_value, &old_size,
8606 &increment, &page_increment);
8607 XmScrollBarSetValues (widget, old_value,
8608 min (size, XM_SB_RANGE - old_value),
8609 0, 0, False);
8612 #else /* !USE_MOTIF i.e. use Xaw */
8614 float old_top, old_shown;
8615 Dimension height;
8616 XtVaGetValues (widget,
8617 XtNtopOfThumb, &old_top,
8618 XtNshown, &old_shown,
8619 XtNheight, &height,
8620 NULL);
8622 /* Massage the top+shown values. */
8623 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8624 top = max (0, min (1, top));
8625 else
8626 top = old_top;
8627 /* Keep two pixels available for moving the thumb down. */
8628 shown = max (0, min (1 - top - (2.0 / height), shown));
8630 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8631 check that your system's configuration file contains a define
8632 for `NARROWPROTO'. See s/freebsd.h for an example. */
8633 if (top != old_top || shown != old_shown)
8635 if (NILP (bar->dragging))
8636 XawScrollbarSetThumb (widget, top, shown);
8637 else
8639 #ifdef HAVE_XAW3D
8640 ScrollbarWidget sb = (ScrollbarWidget) widget;
8641 int scroll_mode = 0;
8643 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8644 if (xaw3d_arrow_scroll)
8646 /* Xaw3d stupidly ignores resize requests while dragging
8647 so we have to make it believe it's not in dragging mode. */
8648 scroll_mode = sb->scrollbar.scroll_mode;
8649 if (scroll_mode == 2)
8650 sb->scrollbar.scroll_mode = 0;
8652 #endif
8653 /* Try to make the scrolling a tad smoother. */
8654 if (!xaw3d_pick_top)
8655 shown = min (shown, old_shown);
8657 XawScrollbarSetThumb (widget, top, shown);
8659 #ifdef HAVE_XAW3D
8660 if (xaw3d_arrow_scroll && scroll_mode == 2)
8661 sb->scrollbar.scroll_mode = scroll_mode;
8662 #endif
8666 #endif /* !USE_MOTIF */
8668 UNBLOCK_INPUT;
8671 #endif /* USE_TOOLKIT_SCROLL_BARS */
8675 /************************************************************************
8676 Scroll bars, general
8677 ************************************************************************/
8679 /* Create a scroll bar and return the scroll bar vector for it. W is
8680 the Emacs window on which to create the scroll bar. TOP, LEFT,
8681 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8682 scroll bar. */
8684 static struct scroll_bar *
8685 x_scroll_bar_create (w, top, left, width, height)
8686 struct window *w;
8687 int top, left, width, height;
8689 struct frame *f = XFRAME (w->frame);
8690 struct scroll_bar *bar
8691 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8693 BLOCK_INPUT;
8695 #ifdef USE_TOOLKIT_SCROLL_BARS
8696 x_create_toolkit_scroll_bar (f, bar);
8697 #else /* not USE_TOOLKIT_SCROLL_BARS */
8699 XSetWindowAttributes a;
8700 unsigned long mask;
8701 Window window;
8703 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8704 if (a.background_pixel == -1)
8705 a.background_pixel = f->output_data.x->background_pixel;
8707 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8708 | ButtonMotionMask | PointerMotionHintMask
8709 | ExposureMask);
8710 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8712 mask = (CWBackPixel | CWEventMask | CWCursor);
8714 /* Clear the area of W that will serve as a scroll bar. This is
8715 for the case that a window has been split horizontally. In
8716 this case, no clear_frame is generated to reduce flickering. */
8717 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8718 left, top, width,
8719 window_box_height (w), False);
8721 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8722 /* Position and size of scroll bar. */
8723 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8724 top,
8725 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8726 height,
8727 /* Border width, depth, class, and visual. */
8729 CopyFromParent,
8730 CopyFromParent,
8731 CopyFromParent,
8732 /* Attributes. */
8733 mask, &a);
8734 SET_SCROLL_BAR_X_WINDOW (bar, window);
8736 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8738 XSETWINDOW (bar->window, w);
8739 XSETINT (bar->top, top);
8740 XSETINT (bar->left, left);
8741 XSETINT (bar->width, width);
8742 XSETINT (bar->height, height);
8743 XSETINT (bar->start, 0);
8744 XSETINT (bar->end, 0);
8745 bar->dragging = Qnil;
8747 /* Add bar to its frame's list of scroll bars. */
8748 bar->next = FRAME_SCROLL_BARS (f);
8749 bar->prev = Qnil;
8750 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8751 if (!NILP (bar->next))
8752 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8754 /* Map the window/widget. */
8755 #ifdef USE_TOOLKIT_SCROLL_BARS
8757 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8758 XtConfigureWidget (scroll_bar,
8759 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8760 top,
8761 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8762 max (height, 1), 0);
8763 XtMapWidget (scroll_bar);
8765 #else /* not USE_TOOLKIT_SCROLL_BARS */
8766 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8767 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8769 UNBLOCK_INPUT;
8770 return bar;
8774 /* Draw BAR's handle in the proper position.
8776 If the handle is already drawn from START to END, don't bother
8777 redrawing it, unless REBUILD is non-zero; in that case, always
8778 redraw it. (REBUILD is handy for drawing the handle after expose
8779 events.)
8781 Normally, we want to constrain the start and end of the handle to
8782 fit inside its rectangle, but if the user is dragging the scroll
8783 bar handle, we want to let them drag it down all the way, so that
8784 the bar's top is as far down as it goes; otherwise, there's no way
8785 to move to the very end of the buffer. */
8787 #ifndef USE_TOOLKIT_SCROLL_BARS
8789 static void
8790 x_scroll_bar_set_handle (bar, start, end, rebuild)
8791 struct scroll_bar *bar;
8792 int start, end;
8793 int rebuild;
8795 int dragging = ! NILP (bar->dragging);
8796 Window w = SCROLL_BAR_X_WINDOW (bar);
8797 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8798 GC gc = f->output_data.x->normal_gc;
8800 /* If the display is already accurate, do nothing. */
8801 if (! rebuild
8802 && start == XINT (bar->start)
8803 && end == XINT (bar->end))
8804 return;
8806 BLOCK_INPUT;
8809 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8810 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8811 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8813 /* Make sure the values are reasonable, and try to preserve
8814 the distance between start and end. */
8816 int length = end - start;
8818 if (start < 0)
8819 start = 0;
8820 else if (start > top_range)
8821 start = top_range;
8822 end = start + length;
8824 if (end < start)
8825 end = start;
8826 else if (end > top_range && ! dragging)
8827 end = top_range;
8830 /* Store the adjusted setting in the scroll bar. */
8831 XSETINT (bar->start, start);
8832 XSETINT (bar->end, end);
8834 /* Clip the end position, just for display. */
8835 if (end > top_range)
8836 end = top_range;
8838 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8839 below top positions, to make sure the handle is always at least
8840 that many pixels tall. */
8841 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8843 /* Draw the empty space above the handle. Note that we can't clear
8844 zero-height areas; that means "clear to end of window." */
8845 if (0 < start)
8846 x_clear_area (FRAME_X_DISPLAY (f), w,
8847 /* x, y, width, height, and exposures. */
8848 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8849 VERTICAL_SCROLL_BAR_TOP_BORDER,
8850 inside_width, start,
8851 False);
8853 /* Change to proper foreground color if one is specified. */
8854 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8855 XSetForeground (FRAME_X_DISPLAY (f), gc,
8856 f->output_data.x->scroll_bar_foreground_pixel);
8858 /* Draw the handle itself. */
8859 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8860 /* x, y, width, height */
8861 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8862 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8863 inside_width, end - start);
8865 /* Restore the foreground color of the GC if we changed it above. */
8866 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8867 XSetForeground (FRAME_X_DISPLAY (f), gc,
8868 f->output_data.x->foreground_pixel);
8870 /* Draw the empty space below the handle. Note that we can't
8871 clear zero-height areas; that means "clear to end of window." */
8872 if (end < inside_height)
8873 x_clear_area (FRAME_X_DISPLAY (f), w,
8874 /* x, y, width, height, and exposures. */
8875 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8876 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8877 inside_width, inside_height - end,
8878 False);
8882 UNBLOCK_INPUT;
8885 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8887 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8888 nil. */
8890 static void
8891 x_scroll_bar_remove (bar)
8892 struct scroll_bar *bar;
8894 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8895 BLOCK_INPUT;
8897 #ifdef USE_TOOLKIT_SCROLL_BARS
8898 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8899 #else
8900 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8901 #endif
8903 /* Disassociate this scroll bar from its window. */
8904 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8906 UNBLOCK_INPUT;
8910 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8911 that we are displaying PORTION characters out of a total of WHOLE
8912 characters, starting at POSITION. If WINDOW has no scroll bar,
8913 create one. */
8915 static void
8916 XTset_vertical_scroll_bar (w, portion, whole, position)
8917 struct window *w;
8918 int portion, whole, position;
8920 struct frame *f = XFRAME (w->frame);
8921 struct scroll_bar *bar;
8922 int top, height, left, sb_left, width, sb_width;
8923 int window_x, window_y, window_width, window_height;
8925 /* Get window dimensions. */
8926 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8927 top = window_y;
8928 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8929 height = window_height;
8931 /* Compute the left edge of the scroll bar area. */
8932 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8933 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8934 else
8935 left = XFASTINT (w->left);
8936 left *= CANON_X_UNIT (f);
8937 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8939 /* Compute the width of the scroll bar which might be less than
8940 the width of the area reserved for the scroll bar. */
8941 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8942 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8943 else
8944 sb_width = width;
8946 /* Compute the left edge of the scroll bar. */
8947 #ifdef USE_TOOLKIT_SCROLL_BARS
8948 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8949 sb_left = left + width - sb_width - (width - sb_width) / 2;
8950 else
8951 sb_left = left + (width - sb_width) / 2;
8952 #else
8953 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8954 sb_left = left + width - sb_width;
8955 else
8956 sb_left = left;
8957 #endif
8959 /* Does the scroll bar exist yet? */
8960 if (NILP (w->vertical_scroll_bar))
8962 BLOCK_INPUT;
8963 if (width && height)
8964 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8965 left, top, width, height, False);
8966 UNBLOCK_INPUT;
8967 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8969 else
8971 /* It may just need to be moved and resized. */
8972 unsigned int mask = 0;
8974 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8976 BLOCK_INPUT;
8978 if (sb_left != XINT (bar->left))
8979 mask |= CWX;
8980 if (top != XINT (bar->top))
8981 mask |= CWY;
8982 if (sb_width != XINT (bar->width))
8983 mask |= CWWidth;
8984 if (height != XINT (bar->height))
8985 mask |= CWHeight;
8987 #ifdef USE_TOOLKIT_SCROLL_BARS
8989 /* Since toolkit scroll bars are smaller than the space reserved
8990 for them on the frame, we have to clear "under" them. */
8991 if (width && height)
8992 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8993 left, top, width, height, False);
8995 /* Move/size the scroll bar widget. */
8996 if (mask)
8997 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
8998 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8999 top,
9000 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9001 max (height, 1), 0);
9003 #else /* not USE_TOOLKIT_SCROLL_BARS */
9005 /* Clear areas not covered by the scroll bar because of
9006 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9007 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9009 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9010 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9011 height, False);
9012 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9013 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9014 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9015 height, False);
9018 /* Clear areas not covered by the scroll bar because it's not as
9019 wide as the area reserved for it . This makes sure a
9020 previous mode line display is cleared after C-x 2 C-x 1, for
9021 example. */
9023 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9024 int rest = area_width - sb_width;
9025 if (rest > 0)
9026 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9027 left + area_width - rest, 0,
9028 rest, max (height, 1), False);
9031 /* Move/size the scroll bar window. */
9032 if (mask)
9034 XWindowChanges wc;
9036 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9037 wc.y = top;
9038 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9039 wc.height = height;
9040 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9041 mask, &wc);
9044 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9046 /* Remember new settings. */
9047 XSETINT (bar->left, sb_left);
9048 XSETINT (bar->top, top);
9049 XSETINT (bar->width, sb_width);
9050 XSETINT (bar->height, height);
9052 UNBLOCK_INPUT;
9055 #ifdef USE_TOOLKIT_SCROLL_BARS
9056 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9057 #else /* not USE_TOOLKIT_SCROLL_BARS */
9058 /* Set the scroll bar's current state, unless we're currently being
9059 dragged. */
9060 if (NILP (bar->dragging))
9062 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9064 if (whole == 0)
9065 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9066 else
9068 int start = ((double) position * top_range) / whole;
9069 int end = ((double) (position + portion) * top_range) / whole;
9070 x_scroll_bar_set_handle (bar, start, end, 0);
9073 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9075 XSETVECTOR (w->vertical_scroll_bar, bar);
9079 /* The following three hooks are used when we're doing a thorough
9080 redisplay of the frame. We don't explicitly know which scroll bars
9081 are going to be deleted, because keeping track of when windows go
9082 away is a real pain - "Can you say set-window-configuration, boys
9083 and girls?" Instead, we just assert at the beginning of redisplay
9084 that *all* scroll bars are to be removed, and then save a scroll bar
9085 from the fiery pit when we actually redisplay its window. */
9087 /* Arrange for all scroll bars on FRAME to be removed at the next call
9088 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9089 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9091 static void
9092 XTcondemn_scroll_bars (frame)
9093 FRAME_PTR frame;
9095 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9096 while (! NILP (FRAME_SCROLL_BARS (frame)))
9098 Lisp_Object bar;
9099 bar = FRAME_SCROLL_BARS (frame);
9100 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9101 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9102 XSCROLL_BAR (bar)->prev = Qnil;
9103 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9104 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9105 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9110 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9111 Note that WINDOW isn't necessarily condemned at all. */
9113 static void
9114 XTredeem_scroll_bar (window)
9115 struct window *window;
9117 struct scroll_bar *bar;
9118 struct frame *f;
9120 /* We can't redeem this window's scroll bar if it doesn't have one. */
9121 if (NILP (window->vertical_scroll_bar))
9122 abort ();
9124 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9126 /* Unlink it from the condemned list. */
9127 f = XFRAME (WINDOW_FRAME (window));
9128 if (NILP (bar->prev))
9130 /* If the prev pointer is nil, it must be the first in one of
9131 the lists. */
9132 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9133 /* It's not condemned. Everything's fine. */
9134 return;
9135 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9136 window->vertical_scroll_bar))
9137 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9138 else
9139 /* If its prev pointer is nil, it must be at the front of
9140 one or the other! */
9141 abort ();
9143 else
9144 XSCROLL_BAR (bar->prev)->next = bar->next;
9146 if (! NILP (bar->next))
9147 XSCROLL_BAR (bar->next)->prev = bar->prev;
9149 bar->next = FRAME_SCROLL_BARS (f);
9150 bar->prev = Qnil;
9151 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9152 if (! NILP (bar->next))
9153 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9156 /* Remove all scroll bars on FRAME that haven't been saved since the
9157 last call to `*condemn_scroll_bars_hook'. */
9159 static void
9160 XTjudge_scroll_bars (f)
9161 FRAME_PTR f;
9163 Lisp_Object bar, next;
9165 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9167 /* Clear out the condemned list now so we won't try to process any
9168 more events on the hapless scroll bars. */
9169 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9171 for (; ! NILP (bar); bar = next)
9173 struct scroll_bar *b = XSCROLL_BAR (bar);
9175 x_scroll_bar_remove (b);
9177 next = b->next;
9178 b->next = b->prev = Qnil;
9181 /* Now there should be no references to the condemned scroll bars,
9182 and they should get garbage-collected. */
9186 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9187 is a no-op when using toolkit scroll bars.
9189 This may be called from a signal handler, so we have to ignore GC
9190 mark bits. */
9192 static void
9193 x_scroll_bar_expose (bar, event)
9194 struct scroll_bar *bar;
9195 XEvent *event;
9197 #ifndef USE_TOOLKIT_SCROLL_BARS
9199 Window w = SCROLL_BAR_X_WINDOW (bar);
9200 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9201 GC gc = f->output_data.x->normal_gc;
9202 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9204 BLOCK_INPUT;
9206 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9208 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9209 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9211 /* x, y, width, height */
9212 0, 0,
9213 XINT (bar->width) - 1 - width_trim - width_trim,
9214 XINT (bar->height) - 1);
9216 UNBLOCK_INPUT;
9218 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9221 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9222 is set to something other than no_event, it is enqueued.
9224 This may be called from a signal handler, so we have to ignore GC
9225 mark bits. */
9227 #ifndef USE_TOOLKIT_SCROLL_BARS
9229 static void
9230 x_scroll_bar_handle_click (bar, event, emacs_event)
9231 struct scroll_bar *bar;
9232 XEvent *event;
9233 struct input_event *emacs_event;
9235 if (! GC_WINDOWP (bar->window))
9236 abort ();
9238 emacs_event->kind = scroll_bar_click;
9239 emacs_event->code = event->xbutton.button - Button1;
9240 emacs_event->modifiers
9241 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9242 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9243 event->xbutton.state)
9244 | (event->type == ButtonRelease
9245 ? up_modifier
9246 : down_modifier));
9247 emacs_event->frame_or_window = bar->window;
9248 emacs_event->arg = Qnil;
9249 emacs_event->timestamp = event->xbutton.time;
9251 #if 0
9252 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9253 int internal_height
9254 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9255 #endif
9256 int top_range
9257 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9258 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9260 if (y < 0) y = 0;
9261 if (y > top_range) y = top_range;
9263 if (y < XINT (bar->start))
9264 emacs_event->part = scroll_bar_above_handle;
9265 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9266 emacs_event->part = scroll_bar_handle;
9267 else
9268 emacs_event->part = scroll_bar_below_handle;
9270 /* Just because the user has clicked on the handle doesn't mean
9271 they want to drag it. Lisp code needs to be able to decide
9272 whether or not we're dragging. */
9273 #if 0
9274 /* If the user has just clicked on the handle, record where they're
9275 holding it. */
9276 if (event->type == ButtonPress
9277 && emacs_event->part == scroll_bar_handle)
9278 XSETINT (bar->dragging, y - XINT (bar->start));
9279 #endif
9281 /* If the user has released the handle, set it to its final position. */
9282 if (event->type == ButtonRelease
9283 && ! NILP (bar->dragging))
9285 int new_start = y - XINT (bar->dragging);
9286 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9288 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9289 bar->dragging = Qnil;
9292 /* Same deal here as the other #if 0. */
9293 #if 0
9294 /* Clicks on the handle are always reported as occurring at the top of
9295 the handle. */
9296 if (emacs_event->part == scroll_bar_handle)
9297 emacs_event->x = bar->start;
9298 else
9299 XSETINT (emacs_event->x, y);
9300 #else
9301 XSETINT (emacs_event->x, y);
9302 #endif
9304 XSETINT (emacs_event->y, top_range);
9308 /* Handle some mouse motion while someone is dragging the scroll bar.
9310 This may be called from a signal handler, so we have to ignore GC
9311 mark bits. */
9313 static void
9314 x_scroll_bar_note_movement (bar, event)
9315 struct scroll_bar *bar;
9316 XEvent *event;
9318 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9320 last_mouse_movement_time = event->xmotion.time;
9322 f->mouse_moved = 1;
9323 XSETVECTOR (last_mouse_scroll_bar, bar);
9325 /* If we're dragging the bar, display it. */
9326 if (! GC_NILP (bar->dragging))
9328 /* Where should the handle be now? */
9329 int new_start = event->xmotion.y - XINT (bar->dragging);
9331 if (new_start != XINT (bar->start))
9333 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9335 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9340 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9342 /* Return information to the user about the current position of the mouse
9343 on the scroll bar. */
9345 static void
9346 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9347 FRAME_PTR *fp;
9348 Lisp_Object *bar_window;
9349 enum scroll_bar_part *part;
9350 Lisp_Object *x, *y;
9351 unsigned long *time;
9353 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9354 Window w = SCROLL_BAR_X_WINDOW (bar);
9355 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9356 int win_x, win_y;
9357 Window dummy_window;
9358 int dummy_coord;
9359 unsigned int dummy_mask;
9361 BLOCK_INPUT;
9363 /* Get the mouse's position relative to the scroll bar window, and
9364 report that. */
9365 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9367 /* Root, child, root x and root y. */
9368 &dummy_window, &dummy_window,
9369 &dummy_coord, &dummy_coord,
9371 /* Position relative to scroll bar. */
9372 &win_x, &win_y,
9374 /* Mouse buttons and modifier keys. */
9375 &dummy_mask))
9377 else
9379 #if 0
9380 int inside_height
9381 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9382 #endif
9383 int top_range
9384 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9386 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9388 if (! NILP (bar->dragging))
9389 win_y -= XINT (bar->dragging);
9391 if (win_y < 0)
9392 win_y = 0;
9393 if (win_y > top_range)
9394 win_y = top_range;
9396 *fp = f;
9397 *bar_window = bar->window;
9399 if (! NILP (bar->dragging))
9400 *part = scroll_bar_handle;
9401 else if (win_y < XINT (bar->start))
9402 *part = scroll_bar_above_handle;
9403 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9404 *part = scroll_bar_handle;
9405 else
9406 *part = scroll_bar_below_handle;
9408 XSETINT (*x, win_y);
9409 XSETINT (*y, top_range);
9411 f->mouse_moved = 0;
9412 last_mouse_scroll_bar = Qnil;
9415 *time = last_mouse_movement_time;
9417 UNBLOCK_INPUT;
9421 /* The screen has been cleared so we may have changed foreground or
9422 background colors, and the scroll bars may need to be redrawn.
9423 Clear out the scroll bars, and ask for expose events, so we can
9424 redraw them. */
9426 void
9427 x_scroll_bar_clear (f)
9428 FRAME_PTR f;
9430 #ifndef USE_TOOLKIT_SCROLL_BARS
9431 Lisp_Object bar;
9433 /* We can have scroll bars even if this is 0,
9434 if we just turned off scroll bar mode.
9435 But in that case we should not clear them. */
9436 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9437 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9438 bar = XSCROLL_BAR (bar)->next)
9439 XClearArea (FRAME_X_DISPLAY (f),
9440 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9441 0, 0, 0, 0, True);
9442 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9445 /* This processes Expose events from the menu-bar specific X event
9446 loop in xmenu.c. This allows to redisplay the frame if necessary
9447 when handling menu-bar or pop-up items. */
9450 process_expose_from_menu (event)
9451 XEvent event;
9453 FRAME_PTR f;
9454 struct x_display_info *dpyinfo;
9455 int frame_exposed_p = 0;
9457 BLOCK_INPUT;
9459 dpyinfo = x_display_info_for_display (event.xexpose.display);
9460 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9461 if (f)
9463 if (f->async_visible == 0)
9465 f->async_visible = 1;
9466 f->async_iconified = 0;
9467 f->output_data.x->has_been_visible = 1;
9468 SET_FRAME_GARBAGED (f);
9470 else
9472 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9473 event.xexpose.x, event.xexpose.y,
9474 event.xexpose.width, event.xexpose.height);
9475 frame_exposed_p = 1;
9478 else
9480 struct scroll_bar *bar
9481 = x_window_to_scroll_bar (event.xexpose.window);
9483 if (bar)
9484 x_scroll_bar_expose (bar, &event);
9487 UNBLOCK_INPUT;
9488 return frame_exposed_p;
9491 /* Define a queue to save up SelectionRequest events for later handling. */
9493 struct selection_event_queue
9495 XEvent event;
9496 struct selection_event_queue *next;
9499 static struct selection_event_queue *queue;
9501 /* Nonzero means queue up certain events--don't process them yet. */
9503 static int x_queue_selection_requests;
9505 /* Queue up an X event *EVENT, to be processed later. */
9507 static void
9508 x_queue_event (f, event)
9509 FRAME_PTR f;
9510 XEvent *event;
9512 struct selection_event_queue *queue_tmp
9513 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9515 if (queue_tmp != NULL)
9517 queue_tmp->event = *event;
9518 queue_tmp->next = queue;
9519 queue = queue_tmp;
9523 /* Take all the queued events and put them back
9524 so that they get processed afresh. */
9526 static void
9527 x_unqueue_events (display)
9528 Display *display;
9530 while (queue != NULL)
9532 struct selection_event_queue *queue_tmp = queue;
9533 XPutBackEvent (display, &queue_tmp->event);
9534 queue = queue_tmp->next;
9535 xfree ((char *)queue_tmp);
9539 /* Start queuing SelectionRequest events. */
9541 void
9542 x_start_queuing_selection_requests (display)
9543 Display *display;
9545 x_queue_selection_requests++;
9548 /* Stop queuing SelectionRequest events. */
9550 void
9551 x_stop_queuing_selection_requests (display)
9552 Display *display;
9554 x_queue_selection_requests--;
9555 x_unqueue_events (display);
9558 /* The main X event-reading loop - XTread_socket. */
9560 /* Time stamp of enter window event. This is only used by XTread_socket,
9561 but we have to put it out here, since static variables within functions
9562 sometimes don't work. */
9564 static Time enter_timestamp;
9566 /* This holds the state XLookupString needs to implement dead keys
9567 and other tricks known as "compose processing". _X Window System_
9568 says that a portable program can't use this, but Stephen Gildea assures
9569 me that letting the compiler initialize it to zeros will work okay.
9571 This must be defined outside of XTread_socket, for the same reasons
9572 given for enter_time stamp, above. */
9574 static XComposeStatus compose_status;
9576 /* Record the last 100 characters stored
9577 to help debug the loss-of-chars-during-GC problem. */
9579 static int temp_index;
9580 static short temp_buffer[100];
9582 /* Set this to nonzero to fake an "X I/O error"
9583 on a particular display. */
9585 struct x_display_info *XTread_socket_fake_io_error;
9587 /* When we find no input here, we occasionally do a no-op command
9588 to verify that the X server is still running and we can still talk with it.
9589 We try all the open displays, one by one.
9590 This variable is used for cycling thru the displays. */
9592 static struct x_display_info *next_noop_dpyinfo;
9594 #define SET_SAVED_MENU_EVENT(size) \
9595 do \
9597 if (f->output_data.x->saved_menu_event == 0) \
9598 f->output_data.x->saved_menu_event \
9599 = (XEvent *) xmalloc (sizeof (XEvent)); \
9600 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9601 if (numchars >= 1) \
9603 bufp->kind = menu_bar_activate_event; \
9604 XSETFRAME (bufp->frame_or_window, f); \
9605 bufp->arg = Qnil; \
9606 bufp++; \
9607 count++; \
9608 numchars--; \
9611 while (0)
9613 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9614 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9616 /* Read events coming from the X server.
9617 This routine is called by the SIGIO handler.
9618 We return as soon as there are no more events to be read.
9620 Events representing keys are stored in buffer BUFP,
9621 which can hold up to NUMCHARS characters.
9622 We return the number of characters stored into the buffer,
9623 thus pretending to be `read'.
9625 EXPECTED is nonzero if the caller knows input is available. */
9628 XTread_socket (sd, bufp, numchars, expected)
9629 register int sd;
9630 /* register */ struct input_event *bufp;
9631 /* register */ int numchars;
9632 int expected;
9634 int count = 0;
9635 int nbytes = 0;
9636 XEvent event;
9637 struct frame *f;
9638 int event_found = 0;
9639 struct x_display_info *dpyinfo;
9640 struct coding_system coding;
9642 if (interrupt_input_blocked)
9644 interrupt_input_pending = 1;
9645 return -1;
9648 interrupt_input_pending = 0;
9649 BLOCK_INPUT;
9651 /* So people can tell when we have read the available input. */
9652 input_signal_count++;
9654 if (numchars <= 0)
9655 abort (); /* Don't think this happens. */
9657 ++handling_signal;
9659 /* The input should be decoded if it is from XIM. Currently the
9660 locale of XIM is the same as that of the system. So, we can use
9661 Vlocale_coding_system which is initialized properly at Emacs
9662 startup time. */
9663 setup_coding_system (Vlocale_coding_system, &coding);
9664 coding.src_multibyte = 0;
9665 coding.dst_multibyte = 1;
9666 /* The input is converted to events, thus we can't handle
9667 composition. Anyway, there's no XIM that gives us composition
9668 information. */
9669 coding.composing = COMPOSITION_DISABLED;
9671 /* Find the display we are supposed to read input for.
9672 It's the one communicating on descriptor SD. */
9673 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9675 #if 0 /* This ought to be unnecessary; let's verify it. */
9676 #ifdef FIOSNBIO
9677 /* If available, Xlib uses FIOSNBIO to make the socket
9678 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9679 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9680 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9681 fcntl (dpyinfo->connection, F_SETFL, 0);
9682 #endif /* ! defined (FIOSNBIO) */
9683 #endif
9685 #if 0 /* This code can't be made to work, with multiple displays,
9686 and appears not to be used on any system any more.
9687 Also keyboard.c doesn't turn O_NDELAY on and off
9688 for X connections. */
9689 #ifndef SIGIO
9690 #ifndef HAVE_SELECT
9691 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9693 extern int read_alarm_should_throw;
9694 read_alarm_should_throw = 1;
9695 XPeekEvent (dpyinfo->display, &event);
9696 read_alarm_should_throw = 0;
9698 #endif /* HAVE_SELECT */
9699 #endif /* SIGIO */
9700 #endif
9702 /* For debugging, this gives a way to fake an I/O error. */
9703 if (dpyinfo == XTread_socket_fake_io_error)
9705 XTread_socket_fake_io_error = 0;
9706 x_io_error_quitter (dpyinfo->display);
9709 while (XPending (dpyinfo->display))
9711 XNextEvent (dpyinfo->display, &event);
9713 #ifdef HAVE_X_I18N
9715 /* Filter events for the current X input method.
9716 XFilterEvent returns non-zero if the input method has
9717 consumed the event. We pass the frame's X window to
9718 XFilterEvent because that's the one for which the IC
9719 was created. */
9720 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9721 event.xclient.window);
9722 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9723 break;
9725 #endif
9726 event_found = 1;
9728 switch (event.type)
9730 case ClientMessage:
9732 if (event.xclient.message_type
9733 == dpyinfo->Xatom_wm_protocols
9734 && event.xclient.format == 32)
9736 if (event.xclient.data.l[0]
9737 == dpyinfo->Xatom_wm_take_focus)
9739 /* Use x_any_window_to_frame because this
9740 could be the shell widget window
9741 if the frame has no title bar. */
9742 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9743 #ifdef HAVE_X_I18N
9744 /* Not quite sure this is needed -pd */
9745 if (f && FRAME_XIC (f))
9746 XSetICFocus (FRAME_XIC (f));
9747 #endif
9748 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9749 instructs the WM to set the input focus automatically for
9750 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9751 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9752 it has set the focus. So, XSetInputFocus below is not
9753 needed.
9755 The call to XSetInputFocus below has also caused trouble. In
9756 cases where the XSetInputFocus done by the WM and the one
9757 below are temporally close (on a fast machine), the call
9758 below can generate additional FocusIn events which confuse
9759 Emacs. */
9761 /* Since we set WM_TAKE_FOCUS, we must call
9762 XSetInputFocus explicitly. But not if f is null,
9763 since that might be an event for a deleted frame. */
9764 if (f)
9766 Display *d = event.xclient.display;
9767 /* Catch and ignore errors, in case window has been
9768 iconified by a window manager such as GWM. */
9769 int count = x_catch_errors (d);
9770 XSetInputFocus (d, event.xclient.window,
9771 /* The ICCCM says this is
9772 the only valid choice. */
9773 RevertToParent,
9774 event.xclient.data.l[1]);
9775 /* This is needed to detect the error
9776 if there is an error. */
9777 XSync (d, False);
9778 x_uncatch_errors (d, count);
9780 /* Not certain about handling scroll bars here */
9781 #endif /* 0 */
9783 else if (event.xclient.data.l[0]
9784 == dpyinfo->Xatom_wm_save_yourself)
9786 /* Save state modify the WM_COMMAND property to
9787 something which can reinstate us. This notifies
9788 the session manager, who's looking for such a
9789 PropertyNotify. Can restart processing when
9790 a keyboard or mouse event arrives. */
9791 if (numchars > 0)
9793 f = x_top_window_to_frame (dpyinfo,
9794 event.xclient.window);
9796 /* This is just so we only give real data once
9797 for a single Emacs process. */
9798 if (f == SELECTED_FRAME ())
9799 XSetCommand (FRAME_X_DISPLAY (f),
9800 event.xclient.window,
9801 initial_argv, initial_argc);
9802 else if (f)
9803 XSetCommand (FRAME_X_DISPLAY (f),
9804 event.xclient.window,
9805 0, 0);
9808 else if (event.xclient.data.l[0]
9809 == dpyinfo->Xatom_wm_delete_window)
9811 struct frame *f
9812 = x_any_window_to_frame (dpyinfo,
9813 event.xclient.window);
9815 if (f)
9817 if (numchars == 0)
9818 abort ();
9820 bufp->kind = delete_window_event;
9821 XSETFRAME (bufp->frame_or_window, f);
9822 bufp->arg = Qnil;
9823 bufp++;
9825 count += 1;
9826 numchars -= 1;
9830 else if (event.xclient.message_type
9831 == dpyinfo->Xatom_wm_configure_denied)
9834 else if (event.xclient.message_type
9835 == dpyinfo->Xatom_wm_window_moved)
9837 int new_x, new_y;
9838 struct frame *f
9839 = x_window_to_frame (dpyinfo, event.xclient.window);
9841 new_x = event.xclient.data.s[0];
9842 new_y = event.xclient.data.s[1];
9844 if (f)
9846 f->output_data.x->left_pos = new_x;
9847 f->output_data.x->top_pos = new_y;
9850 #ifdef HACK_EDITRES
9851 else if (event.xclient.message_type
9852 == dpyinfo->Xatom_editres)
9854 struct frame *f
9855 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9856 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9857 &event, NULL);
9859 #endif /* HACK_EDITRES */
9860 else if ((event.xclient.message_type
9861 == dpyinfo->Xatom_DONE)
9862 || (event.xclient.message_type
9863 == dpyinfo->Xatom_PAGE))
9865 /* Ghostview job completed. Kill it. We could
9866 reply with "Next" if we received "Page", but we
9867 currently never do because we are interested in
9868 images, only, which should have 1 page. */
9869 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9870 struct frame *f
9871 = x_window_to_frame (dpyinfo, event.xclient.window);
9872 x_kill_gs_process (pixmap, f);
9873 expose_frame (f, 0, 0, 0, 0);
9875 #ifdef USE_TOOLKIT_SCROLL_BARS
9876 /* Scroll bar callbacks send a ClientMessage from which
9877 we construct an input_event. */
9878 else if (event.xclient.message_type
9879 == dpyinfo->Xatom_Scrollbar)
9881 x_scroll_bar_to_input_event (&event, bufp);
9882 ++bufp, ++count, --numchars;
9883 goto out;
9885 #endif /* USE_TOOLKIT_SCROLL_BARS */
9886 else
9887 goto OTHER;
9889 break;
9891 case SelectionNotify:
9892 #ifdef USE_X_TOOLKIT
9893 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9894 goto OTHER;
9895 #endif /* not USE_X_TOOLKIT */
9896 x_handle_selection_notify (&event.xselection);
9897 break;
9899 case SelectionClear: /* Someone has grabbed ownership. */
9900 #ifdef USE_X_TOOLKIT
9901 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9902 goto OTHER;
9903 #endif /* USE_X_TOOLKIT */
9905 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9907 if (numchars == 0)
9908 abort ();
9910 bufp->kind = selection_clear_event;
9911 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9912 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9913 SELECTION_EVENT_TIME (bufp) = eventp->time;
9914 bufp->frame_or_window = Qnil;
9915 bufp->arg = Qnil;
9916 bufp++;
9918 count += 1;
9919 numchars -= 1;
9921 break;
9923 case SelectionRequest: /* Someone wants our selection. */
9924 #ifdef USE_X_TOOLKIT
9925 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9926 goto OTHER;
9927 #endif /* USE_X_TOOLKIT */
9928 if (x_queue_selection_requests)
9929 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9930 &event);
9931 else
9933 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9935 if (numchars == 0)
9936 abort ();
9938 bufp->kind = selection_request_event;
9939 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9940 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9941 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9942 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9943 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9944 SELECTION_EVENT_TIME (bufp) = eventp->time;
9945 bufp->frame_or_window = Qnil;
9946 bufp->arg = Qnil;
9947 bufp++;
9949 count += 1;
9950 numchars -= 1;
9952 break;
9954 case PropertyNotify:
9955 #ifdef USE_X_TOOLKIT
9956 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9957 goto OTHER;
9958 #endif /* not USE_X_TOOLKIT */
9959 x_handle_property_notify (&event.xproperty);
9960 break;
9962 case ReparentNotify:
9963 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9964 if (f)
9966 int x, y;
9967 f->output_data.x->parent_desc = event.xreparent.parent;
9968 x_real_positions (f, &x, &y);
9969 f->output_data.x->left_pos = x;
9970 f->output_data.x->top_pos = y;
9972 break;
9974 case Expose:
9975 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9976 if (f)
9978 if (f->async_visible == 0)
9980 f->async_visible = 1;
9981 f->async_iconified = 0;
9982 f->output_data.x->has_been_visible = 1;
9983 SET_FRAME_GARBAGED (f);
9985 else
9986 expose_frame (x_window_to_frame (dpyinfo,
9987 event.xexpose.window),
9988 event.xexpose.x, event.xexpose.y,
9989 event.xexpose.width, event.xexpose.height);
9991 else
9993 #ifdef USE_TOOLKIT_SCROLL_BARS
9994 /* Dispatch event to the widget. */
9995 goto OTHER;
9996 #else /* not USE_TOOLKIT_SCROLL_BARS */
9997 struct scroll_bar *bar
9998 = x_window_to_scroll_bar (event.xexpose.window);
10000 if (bar)
10001 x_scroll_bar_expose (bar, &event);
10002 #ifdef USE_X_TOOLKIT
10003 else
10004 goto OTHER;
10005 #endif /* USE_X_TOOLKIT */
10006 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10008 break;
10010 case GraphicsExpose: /* This occurs when an XCopyArea's
10011 source area was obscured or not
10012 available.*/
10013 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10014 if (f)
10016 expose_frame (f,
10017 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10018 event.xgraphicsexpose.width,
10019 event.xgraphicsexpose.height);
10021 #ifdef USE_X_TOOLKIT
10022 else
10023 goto OTHER;
10024 #endif /* USE_X_TOOLKIT */
10025 break;
10027 case NoExpose: /* This occurs when an XCopyArea's
10028 source area was completely
10029 available */
10030 break;
10032 case UnmapNotify:
10033 /* Redo the mouse-highlight after the tooltip has gone. */
10034 if (event.xmap.window == tip_window)
10036 tip_window = 0;
10037 redo_mouse_highlight ();
10040 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10041 if (f) /* F may no longer exist if
10042 the frame was deleted. */
10044 /* While a frame is unmapped, display generation is
10045 disabled; you don't want to spend time updating a
10046 display that won't ever be seen. */
10047 f->async_visible = 0;
10048 /* We can't distinguish, from the event, whether the window
10049 has become iconified or invisible. So assume, if it
10050 was previously visible, than now it is iconified.
10051 But x_make_frame_invisible clears both
10052 the visible flag and the iconified flag;
10053 and that way, we know the window is not iconified now. */
10054 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10056 f->async_iconified = 1;
10058 bufp->kind = iconify_event;
10059 XSETFRAME (bufp->frame_or_window, f);
10060 bufp->arg = Qnil;
10061 bufp++;
10062 count++;
10063 numchars--;
10066 goto OTHER;
10068 case MapNotify:
10069 if (event.xmap.window == tip_window)
10070 /* The tooltip has been drawn already. Avoid
10071 the SET_FRAME_GARBAGED below. */
10072 goto OTHER;
10074 /* We use x_top_window_to_frame because map events can
10075 come for sub-windows and they don't mean that the
10076 frame is visible. */
10077 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10078 if (f)
10080 f->async_visible = 1;
10081 f->async_iconified = 0;
10082 f->output_data.x->has_been_visible = 1;
10084 /* wait_reading_process_input will notice this and update
10085 the frame's display structures. */
10086 SET_FRAME_GARBAGED (f);
10088 if (f->iconified)
10090 bufp->kind = deiconify_event;
10091 XSETFRAME (bufp->frame_or_window, f);
10092 bufp->arg = Qnil;
10093 bufp++;
10094 count++;
10095 numchars--;
10097 else if (! NILP (Vframe_list)
10098 && ! NILP (XCDR (Vframe_list)))
10099 /* Force a redisplay sooner or later
10100 to update the frame titles
10101 in case this is the second frame. */
10102 record_asynch_buffer_change ();
10104 goto OTHER;
10106 case KeyPress:
10107 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10109 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10110 if (f == 0)
10112 /* Scroll bars consume key events, but we want
10113 the keys to go to the scroll bar's frame. */
10114 Widget widget = XtWindowToWidget (dpyinfo->display,
10115 event.xkey.window);
10116 if (widget && XmIsScrollBar (widget))
10118 widget = XtParent (widget);
10119 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10122 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10124 if (f != 0)
10126 KeySym keysym, orig_keysym;
10127 /* al%imercury@uunet.uu.net says that making this 81
10128 instead of 80 fixed a bug whereby meta chars made
10129 his Emacs hang.
10131 It seems that some version of XmbLookupString has
10132 a bug of not returning XBufferOverflow in
10133 status_return even if the input is too long to
10134 fit in 81 bytes. So, we must prepare sufficient
10135 bytes for copy_buffer. 513 bytes (256 chars for
10136 two-byte character set) seems to be a faily good
10137 approximation. -- 2000.8.10 handa@etl.go.jp */
10138 unsigned char copy_buffer[513];
10139 unsigned char *copy_bufptr = copy_buffer;
10140 int copy_bufsiz = sizeof (copy_buffer);
10141 int modifiers;
10143 event.xkey.state
10144 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10145 extra_keyboard_modifiers);
10146 modifiers = event.xkey.state;
10148 /* This will have to go some day... */
10150 /* make_lispy_event turns chars into control chars.
10151 Don't do it here because XLookupString is too eager. */
10152 event.xkey.state &= ~ControlMask;
10153 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10154 | dpyinfo->super_mod_mask
10155 | dpyinfo->hyper_mod_mask
10156 | dpyinfo->alt_mod_mask);
10158 /* In case Meta is ComposeCharacter,
10159 clear its status. According to Markus Ehrnsperger
10160 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10161 this enables ComposeCharacter to work whether or
10162 not it is combined with Meta. */
10163 if (modifiers & dpyinfo->meta_mod_mask)
10164 bzero (&compose_status, sizeof (compose_status));
10166 #ifdef HAVE_X_I18N
10167 if (FRAME_XIC (f))
10169 Status status_return;
10171 nbytes = XmbLookupString (FRAME_XIC (f),
10172 &event.xkey, copy_bufptr,
10173 copy_bufsiz, &keysym,
10174 &status_return);
10175 if (status_return == XBufferOverflow)
10177 copy_bufsiz = nbytes + 1;
10178 copy_bufptr = (char *) alloca (copy_bufsiz);
10179 nbytes = XmbLookupString (FRAME_XIC (f),
10180 &event.xkey, copy_bufptr,
10181 copy_bufsiz, &keysym,
10182 &status_return);
10185 if (status_return == XLookupNone)
10186 break;
10187 else if (status_return == XLookupChars)
10189 keysym = NoSymbol;
10190 modifiers = 0;
10192 else if (status_return != XLookupKeySym
10193 && status_return != XLookupBoth)
10194 abort ();
10196 else
10197 nbytes = XLookupString (&event.xkey, copy_bufptr,
10198 copy_bufsiz, &keysym,
10199 &compose_status);
10200 #else
10201 nbytes = XLookupString (&event.xkey, copy_bufptr,
10202 copy_bufsiz, &keysym,
10203 &compose_status);
10204 #endif
10206 orig_keysym = keysym;
10208 if (numchars > 1)
10210 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10211 || keysym == XK_Delete
10212 #ifdef XK_ISO_Left_Tab
10213 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10214 #endif
10215 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10216 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10217 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10218 #ifdef HPUX
10219 /* This recognizes the "extended function keys".
10220 It seems there's no cleaner way.
10221 Test IsModifierKey to avoid handling mode_switch
10222 incorrectly. */
10223 || ((unsigned) (keysym) >= XK_Select
10224 && (unsigned)(keysym) < XK_KP_Space)
10225 #endif
10226 #ifdef XK_dead_circumflex
10227 || orig_keysym == XK_dead_circumflex
10228 #endif
10229 #ifdef XK_dead_grave
10230 || orig_keysym == XK_dead_grave
10231 #endif
10232 #ifdef XK_dead_tilde
10233 || orig_keysym == XK_dead_tilde
10234 #endif
10235 #ifdef XK_dead_diaeresis
10236 || orig_keysym == XK_dead_diaeresis
10237 #endif
10238 #ifdef XK_dead_macron
10239 || orig_keysym == XK_dead_macron
10240 #endif
10241 #ifdef XK_dead_degree
10242 || orig_keysym == XK_dead_degree
10243 #endif
10244 #ifdef XK_dead_acute
10245 || orig_keysym == XK_dead_acute
10246 #endif
10247 #ifdef XK_dead_cedilla
10248 || orig_keysym == XK_dead_cedilla
10249 #endif
10250 #ifdef XK_dead_breve
10251 || orig_keysym == XK_dead_breve
10252 #endif
10253 #ifdef XK_dead_ogonek
10254 || orig_keysym == XK_dead_ogonek
10255 #endif
10256 #ifdef XK_dead_caron
10257 || orig_keysym == XK_dead_caron
10258 #endif
10259 #ifdef XK_dead_doubleacute
10260 || orig_keysym == XK_dead_doubleacute
10261 #endif
10262 #ifdef XK_dead_abovedot
10263 || orig_keysym == XK_dead_abovedot
10264 #endif
10265 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10266 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10267 /* Any "vendor-specific" key is ok. */
10268 || (orig_keysym & (1 << 28)))
10269 && ! (IsModifierKey (orig_keysym)
10270 #ifndef HAVE_X11R5
10271 #ifdef XK_Mode_switch
10272 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10273 #endif
10274 #ifdef XK_Num_Lock
10275 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10276 #endif
10277 #endif /* not HAVE_X11R5 */
10280 if (temp_index == sizeof temp_buffer / sizeof (short))
10281 temp_index = 0;
10282 temp_buffer[temp_index++] = keysym;
10283 bufp->kind = non_ascii_keystroke;
10284 bufp->code = keysym;
10285 XSETFRAME (bufp->frame_or_window, f);
10286 bufp->arg = Qnil;
10287 bufp->modifiers
10288 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10289 modifiers);
10290 bufp->timestamp = event.xkey.time;
10291 bufp++;
10292 count++;
10293 numchars--;
10295 else if (numchars > nbytes)
10297 register int i;
10298 register int c;
10299 int nchars, len;
10301 for (i = 0; i < nbytes; i++)
10303 if (temp_index == (sizeof temp_buffer
10304 / sizeof (short)))
10305 temp_index = 0;
10306 temp_buffer[temp_index++] = copy_bufptr[i];
10309 if (/* If the event is not from XIM, */
10310 event.xkey.keycode != 0
10311 /* or the current locale doesn't request
10312 decoding of the intup data, ... */
10313 || coding.type == coding_type_raw_text
10314 || coding.type == coding_type_no_conversion)
10316 /* ... we can use the input data as is. */
10317 nchars = nbytes;
10319 else
10321 /* We have to decode the input data. */
10322 int require;
10323 unsigned char *p;
10325 require = decoding_buffer_size (&coding, nbytes);
10326 p = (unsigned char *) alloca (require);
10327 coding.mode |= CODING_MODE_LAST_BLOCK;
10328 decode_coding (&coding, copy_bufptr, p,
10329 nbytes, require);
10330 nbytes = coding.produced;
10331 nchars = coding.produced_char;
10332 copy_bufptr = p;
10335 /* Convert the input data to a sequence of
10336 character events. */
10337 for (i = 0; i < nbytes; i += len)
10339 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10340 nbytes - i, len);
10341 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10342 ? ascii_keystroke
10343 : multibyte_char_keystroke);
10344 bufp->code = c;
10345 XSETFRAME (bufp->frame_or_window, f);
10346 bufp->arg = Qnil;
10347 bufp->modifiers
10348 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10349 modifiers);
10350 bufp->timestamp = event.xkey.time;
10351 bufp++;
10354 count += nchars;
10355 numchars -= nchars;
10357 if (keysym == NoSymbol)
10358 break;
10360 else
10361 abort ();
10363 else
10364 abort ();
10366 #ifdef HAVE_X_I18N
10367 /* Don't dispatch this event since XtDispatchEvent calls
10368 XFilterEvent, and two calls in a row may freeze the
10369 client. */
10370 break;
10371 #else
10372 goto OTHER;
10373 #endif
10375 case KeyRelease:
10376 #ifdef HAVE_X_I18N
10377 /* Don't dispatch this event since XtDispatchEvent calls
10378 XFilterEvent, and two calls in a row may freeze the
10379 client. */
10380 break;
10381 #else
10382 goto OTHER;
10383 #endif
10385 /* Here's a possible interpretation of the whole
10386 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10387 you get a FocusIn event, you have to get a FocusOut
10388 event before you relinquish the focus. If you
10389 haven't received a FocusIn event, then a mere
10390 LeaveNotify is enough to free you. */
10392 case EnterNotify:
10394 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10396 if (event.xcrossing.focus)
10398 /* Avoid nasty pop/raise loops. */
10399 if (f && (!(f->auto_raise)
10400 || !(f->auto_lower)
10401 || (event.xcrossing.time - enter_timestamp) > 500))
10403 x_new_focus_frame (dpyinfo, f);
10404 enter_timestamp = event.xcrossing.time;
10407 else if (f == dpyinfo->x_focus_frame)
10408 x_new_focus_frame (dpyinfo, 0);
10410 /* EnterNotify counts as mouse movement,
10411 so update things that depend on mouse position. */
10412 if (f && !f->output_data.x->hourglass_p)
10413 note_mouse_movement (f, &event.xmotion);
10414 goto OTHER;
10417 case FocusIn:
10418 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10419 if (event.xfocus.detail != NotifyPointer)
10420 dpyinfo->x_focus_event_frame = f;
10421 if (f)
10423 x_new_focus_frame (dpyinfo, f);
10425 /* Don't stop displaying the initial startup message
10426 for a switch-frame event we don't need. */
10427 if (GC_NILP (Vterminal_frame)
10428 && GC_CONSP (Vframe_list)
10429 && !GC_NILP (XCDR (Vframe_list)))
10431 bufp->kind = FOCUS_IN_EVENT;
10432 XSETFRAME (bufp->frame_or_window, f);
10433 bufp->arg = Qnil;
10434 ++bufp, ++count, --numchars;
10438 #ifdef HAVE_X_I18N
10439 if (f && FRAME_XIC (f))
10440 XSetICFocus (FRAME_XIC (f));
10441 #endif
10443 goto OTHER;
10445 case LeaveNotify:
10446 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10447 if (f)
10449 if (f == dpyinfo->mouse_face_mouse_frame)
10451 /* If we move outside the frame, then we're
10452 certainly no longer on any text in the frame. */
10453 clear_mouse_face (dpyinfo);
10454 dpyinfo->mouse_face_mouse_frame = 0;
10457 /* Generate a nil HELP_EVENT to cancel a help-echo.
10458 Do it only if there's something to cancel.
10459 Otherwise, the startup message is cleared when
10460 the mouse leaves the frame. */
10461 if (any_help_event_p)
10463 Lisp_Object frame;
10464 int n;
10466 XSETFRAME (frame, f);
10467 help_echo = Qnil;
10468 n = gen_help_event (bufp, numchars,
10469 Qnil, frame, Qnil, Qnil, 0);
10470 bufp += n, count += n, numchars -= n;
10473 if (event.xcrossing.focus)
10474 x_mouse_leave (dpyinfo);
10475 else
10477 if (f == dpyinfo->x_focus_event_frame)
10478 dpyinfo->x_focus_event_frame = 0;
10479 if (f == dpyinfo->x_focus_frame)
10480 x_new_focus_frame (dpyinfo, 0);
10483 goto OTHER;
10485 case FocusOut:
10486 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10487 if (event.xfocus.detail != NotifyPointer
10488 && f == dpyinfo->x_focus_event_frame)
10489 dpyinfo->x_focus_event_frame = 0;
10490 if (f && f == dpyinfo->x_focus_frame)
10491 x_new_focus_frame (dpyinfo, 0);
10493 #ifdef HAVE_X_I18N
10494 if (f && FRAME_XIC (f))
10495 XUnsetICFocus (FRAME_XIC (f));
10496 #endif
10498 goto OTHER;
10500 case MotionNotify:
10502 previous_help_echo = help_echo;
10503 help_echo = help_echo_object = help_echo_window = Qnil;
10504 help_echo_pos = -1;
10506 if (dpyinfo->grabbed && last_mouse_frame
10507 && FRAME_LIVE_P (last_mouse_frame))
10508 f = last_mouse_frame;
10509 else
10510 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10512 if (f)
10513 note_mouse_movement (f, &event.xmotion);
10514 else
10516 #ifndef USE_TOOLKIT_SCROLL_BARS
10517 struct scroll_bar *bar
10518 = x_window_to_scroll_bar (event.xmotion.window);
10520 if (bar)
10521 x_scroll_bar_note_movement (bar, &event);
10522 #endif /* USE_TOOLKIT_SCROLL_BARS */
10524 /* If we move outside the frame, then we're
10525 certainly no longer on any text in the frame. */
10526 clear_mouse_face (dpyinfo);
10529 /* If the contents of the global variable help_echo
10530 has changed, generate a HELP_EVENT. */
10531 if (!NILP (help_echo)
10532 || !NILP (previous_help_echo))
10534 Lisp_Object frame;
10535 int n;
10537 if (f)
10538 XSETFRAME (frame, f);
10539 else
10540 frame = Qnil;
10542 any_help_event_p = 1;
10543 n = gen_help_event (bufp, numchars, help_echo, frame,
10544 help_echo_window, help_echo_object,
10545 help_echo_pos);
10546 bufp += n, count += n, numchars -= n;
10549 goto OTHER;
10552 case ConfigureNotify:
10553 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10554 if (f)
10556 #ifndef USE_X_TOOLKIT
10557 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10558 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10560 /* In the toolkit version, change_frame_size
10561 is called by the code that handles resizing
10562 of the EmacsFrame widget. */
10564 /* Even if the number of character rows and columns has
10565 not changed, the font size may have changed, so we need
10566 to check the pixel dimensions as well. */
10567 if (columns != f->width
10568 || rows != f->height
10569 || event.xconfigure.width != f->output_data.x->pixel_width
10570 || event.xconfigure.height != f->output_data.x->pixel_height)
10572 change_frame_size (f, rows, columns, 0, 1, 0);
10573 SET_FRAME_GARBAGED (f);
10574 cancel_mouse_face (f);
10576 #endif
10578 f->output_data.x->pixel_width = event.xconfigure.width;
10579 f->output_data.x->pixel_height = event.xconfigure.height;
10581 /* What we have now is the position of Emacs's own window.
10582 Convert that to the position of the window manager window. */
10583 x_real_positions (f, &f->output_data.x->left_pos,
10584 &f->output_data.x->top_pos);
10586 #ifdef HAVE_X_I18N
10587 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10588 xic_set_statusarea (f);
10589 #endif
10591 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10593 /* Since the WM decorations come below top_pos now,
10594 we must put them below top_pos in the future. */
10595 f->output_data.x->win_gravity = NorthWestGravity;
10596 x_wm_set_size_hint (f, (long) 0, 0);
10598 #ifdef USE_MOTIF
10599 /* Some window managers pass (0,0) as the location of
10600 the window, and the Motif event handler stores it
10601 in the emacs widget, which messes up Motif menus. */
10602 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10604 event.xconfigure.x = f->output_data.x->widget->core.x;
10605 event.xconfigure.y = f->output_data.x->widget->core.y;
10607 #endif /* USE_MOTIF */
10609 goto OTHER;
10611 case ButtonPress:
10612 case ButtonRelease:
10614 /* If we decide we want to generate an event to be seen
10615 by the rest of Emacs, we put it here. */
10616 struct input_event emacs_event;
10617 int tool_bar_p = 0;
10619 emacs_event.kind = no_event;
10620 bzero (&compose_status, sizeof (compose_status));
10622 if (dpyinfo->grabbed
10623 && last_mouse_frame
10624 && FRAME_LIVE_P (last_mouse_frame))
10625 f = last_mouse_frame;
10626 else
10627 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10629 if (f)
10631 /* Is this in the tool-bar? */
10632 if (WINDOWP (f->tool_bar_window)
10633 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10635 Lisp_Object window;
10636 int p, x, y;
10638 x = event.xbutton.x;
10639 y = event.xbutton.y;
10641 /* Set x and y. */
10642 window = window_from_coordinates (f, x, y, &p, 1);
10643 if (EQ (window, f->tool_bar_window))
10645 x_handle_tool_bar_click (f, &event.xbutton);
10646 tool_bar_p = 1;
10650 if (!tool_bar_p)
10651 if (!dpyinfo->x_focus_frame
10652 || f == dpyinfo->x_focus_frame)
10653 construct_mouse_click (&emacs_event, &event, f);
10655 else
10657 #ifndef USE_TOOLKIT_SCROLL_BARS
10658 struct scroll_bar *bar
10659 = x_window_to_scroll_bar (event.xbutton.window);
10661 if (bar)
10662 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10663 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10666 if (event.type == ButtonPress)
10668 dpyinfo->grabbed |= (1 << event.xbutton.button);
10669 last_mouse_frame = f;
10670 /* Ignore any mouse motion that happened
10671 before this event; any subsequent mouse-movement
10672 Emacs events should reflect only motion after
10673 the ButtonPress. */
10674 if (f != 0)
10675 f->mouse_moved = 0;
10677 if (!tool_bar_p)
10678 last_tool_bar_item = -1;
10680 else
10682 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10685 if (numchars >= 1 && emacs_event.kind != no_event)
10687 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10688 bufp++;
10689 count++;
10690 numchars--;
10693 #ifdef USE_X_TOOLKIT
10694 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10695 /* For a down-event in the menu bar,
10696 don't pass it to Xt right now.
10697 Instead, save it away
10698 and we will pass it to Xt from kbd_buffer_get_event.
10699 That way, we can run some Lisp code first. */
10700 if (f && event.type == ButtonPress
10701 /* Verify the event is really within the menu bar
10702 and not just sent to it due to grabbing. */
10703 && event.xbutton.x >= 0
10704 && event.xbutton.x < f->output_data.x->pixel_width
10705 && event.xbutton.y >= 0
10706 && event.xbutton.y < f->output_data.x->menubar_height
10707 && event.xbutton.same_screen)
10709 SET_SAVED_BUTTON_EVENT;
10710 XSETFRAME (last_mouse_press_frame, f);
10712 else if (event.type == ButtonPress)
10714 last_mouse_press_frame = Qnil;
10715 goto OTHER;
10718 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10719 but I am trying to be cautious. */
10720 else if (event.type == ButtonRelease)
10722 if (!NILP (last_mouse_press_frame))
10724 f = XFRAME (last_mouse_press_frame);
10725 if (f->output_data.x)
10726 SET_SAVED_BUTTON_EVENT;
10728 else
10729 goto OTHER;
10731 #endif /* USE_MOTIF */
10732 else
10733 goto OTHER;
10734 #endif /* USE_X_TOOLKIT */
10736 break;
10738 case CirculateNotify:
10739 goto OTHER;
10741 case CirculateRequest:
10742 goto OTHER;
10744 case VisibilityNotify:
10745 goto OTHER;
10747 case MappingNotify:
10748 /* Someone has changed the keyboard mapping - update the
10749 local cache. */
10750 switch (event.xmapping.request)
10752 case MappingModifier:
10753 x_find_modifier_meanings (dpyinfo);
10754 /* This is meant to fall through. */
10755 case MappingKeyboard:
10756 XRefreshKeyboardMapping (&event.xmapping);
10758 goto OTHER;
10760 default:
10761 OTHER:
10762 #ifdef USE_X_TOOLKIT
10763 BLOCK_INPUT;
10764 XtDispatchEvent (&event);
10765 UNBLOCK_INPUT;
10766 #endif /* USE_X_TOOLKIT */
10767 break;
10772 out:;
10774 /* On some systems, an X bug causes Emacs to get no more events
10775 when the window is destroyed. Detect that. (1994.) */
10776 if (! event_found)
10778 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10779 One XNOOP in 100 loops will make Emacs terminate.
10780 B. Bretthauer, 1994 */
10781 x_noop_count++;
10782 if (x_noop_count >= 100)
10784 x_noop_count=0;
10786 if (next_noop_dpyinfo == 0)
10787 next_noop_dpyinfo = x_display_list;
10789 XNoOp (next_noop_dpyinfo->display);
10791 /* Each time we get here, cycle through the displays now open. */
10792 next_noop_dpyinfo = next_noop_dpyinfo->next;
10796 /* If the focus was just given to an auto-raising frame,
10797 raise it now. */
10798 /* ??? This ought to be able to handle more than one such frame. */
10799 if (pending_autoraise_frame)
10801 x_raise_frame (pending_autoraise_frame);
10802 pending_autoraise_frame = 0;
10805 UNBLOCK_INPUT;
10806 --handling_signal;
10807 return count;
10813 /***********************************************************************
10814 Text Cursor
10815 ***********************************************************************/
10817 /* Note if the text cursor of window W has been overwritten by a
10818 drawing operation that outputs N glyphs starting at HPOS in the
10819 line given by output_cursor.vpos. N < 0 means all the rest of the
10820 line after HPOS has been written. */
10822 static void
10823 note_overwritten_text_cursor (w, hpos, n)
10824 struct window *w;
10825 int hpos, n;
10827 if (updated_area == TEXT_AREA
10828 && output_cursor.vpos == w->phys_cursor.vpos
10829 && hpos <= w->phys_cursor.hpos
10830 && (n < 0
10831 || hpos + n > w->phys_cursor.hpos))
10832 w->phys_cursor_on_p = 0;
10836 /* Set clipping for output in glyph row ROW. W is the window in which
10837 we operate. GC is the graphics context to set clipping in.
10838 WHOLE_LINE_P non-zero means include the areas used for truncation
10839 mark display and alike in the clipping rectangle.
10841 ROW may be a text row or, e.g., a mode line. Text rows must be
10842 clipped to the interior of the window dedicated to text display,
10843 mode lines must be clipped to the whole window. */
10845 static void
10846 x_clip_to_row (w, row, gc, whole_line_p)
10847 struct window *w;
10848 struct glyph_row *row;
10849 GC gc;
10850 int whole_line_p;
10852 struct frame *f = XFRAME (WINDOW_FRAME (w));
10853 XRectangle clip_rect;
10854 int window_x, window_y, window_width, window_height;
10856 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10858 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10859 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10860 clip_rect.y = max (clip_rect.y, window_y);
10861 clip_rect.width = window_width;
10862 clip_rect.height = row->visible_height;
10864 /* If clipping to the whole line, including trunc marks, extend
10865 the rectangle to the left and increase its width. */
10866 if (whole_line_p)
10868 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10869 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10872 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10876 /* Draw a hollow box cursor on window W in glyph row ROW. */
10878 static void
10879 x_draw_hollow_cursor (w, row)
10880 struct window *w;
10881 struct glyph_row *row;
10883 struct frame *f = XFRAME (WINDOW_FRAME (w));
10884 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10885 Display *dpy = FRAME_X_DISPLAY (f);
10886 int x, y, wd, h;
10887 XGCValues xgcv;
10888 struct glyph *cursor_glyph;
10889 GC gc;
10891 /* Compute frame-relative coordinates from window-relative
10892 coordinates. */
10893 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10894 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10895 + row->ascent - w->phys_cursor_ascent);
10896 h = row->height - 1;
10898 /* Get the glyph the cursor is on. If we can't tell because
10899 the current matrix is invalid or such, give up. */
10900 cursor_glyph = get_phys_cursor_glyph (w);
10901 if (cursor_glyph == NULL)
10902 return;
10904 /* Compute the width of the rectangle to draw. If on a stretch
10905 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10906 rectangle as wide as the glyph, but use a canonical character
10907 width instead. */
10908 wd = cursor_glyph->pixel_width - 1;
10909 if (cursor_glyph->type == STRETCH_GLYPH
10910 && !x_stretch_cursor_p)
10911 wd = min (CANON_X_UNIT (f), wd);
10913 /* The foreground of cursor_gc is typically the same as the normal
10914 background color, which can cause the cursor box to be invisible. */
10915 xgcv.foreground = f->output_data.x->cursor_pixel;
10916 if (dpyinfo->scratch_cursor_gc)
10917 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10918 else
10919 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10920 GCForeground, &xgcv);
10921 gc = dpyinfo->scratch_cursor_gc;
10923 /* Set clipping, draw the rectangle, and reset clipping again. */
10924 x_clip_to_row (w, row, gc, 0);
10925 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10926 XSetClipMask (dpy, gc, None);
10930 /* Draw a bar cursor on window W in glyph row ROW.
10932 Implementation note: One would like to draw a bar cursor with an
10933 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10934 Unfortunately, I didn't find a font yet that has this property set.
10935 --gerd. */
10937 static void
10938 x_draw_bar_cursor (w, row, width)
10939 struct window *w;
10940 struct glyph_row *row;
10941 int width;
10943 struct frame *f = XFRAME (w->frame);
10944 struct glyph *cursor_glyph;
10945 GC gc;
10946 int x;
10947 unsigned long mask;
10948 XGCValues xgcv;
10949 Display *dpy;
10950 Window window;
10952 /* If cursor is out of bounds, don't draw garbage. This can happen
10953 in mini-buffer windows when switching between echo area glyphs
10954 and mini-buffer. */
10955 cursor_glyph = get_phys_cursor_glyph (w);
10956 if (cursor_glyph == NULL)
10957 return;
10959 /* If on an image, draw like a normal cursor. That's usually better
10960 visible than drawing a bar, esp. if the image is large so that
10961 the bar might not be in the window. */
10962 if (cursor_glyph->type == IMAGE_GLYPH)
10964 struct glyph_row *row;
10965 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10966 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10968 else
10970 xgcv.background = f->output_data.x->cursor_pixel;
10971 xgcv.foreground = f->output_data.x->cursor_pixel;
10972 xgcv.graphics_exposures = 0;
10973 mask = GCForeground | GCBackground | GCGraphicsExposures;
10974 dpy = FRAME_X_DISPLAY (f);
10975 window = FRAME_X_WINDOW (f);
10976 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10978 if (gc)
10979 XChangeGC (dpy, gc, mask, &xgcv);
10980 else
10982 gc = XCreateGC (dpy, window, mask, &xgcv);
10983 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10986 if (width < 0)
10987 width = f->output_data.x->cursor_width;
10989 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10990 x_clip_to_row (w, row, gc, 0);
10991 XFillRectangle (dpy, window, gc,
10993 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10994 min (cursor_glyph->pixel_width, width),
10995 row->height);
10996 XSetClipMask (dpy, gc, None);
11001 /* Clear the cursor of window W to background color, and mark the
11002 cursor as not shown. This is used when the text where the cursor
11003 is is about to be rewritten. */
11005 static void
11006 x_clear_cursor (w)
11007 struct window *w;
11009 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11010 x_update_window_cursor (w, 0);
11014 /* Draw the cursor glyph of window W in glyph row ROW. See the
11015 comment of x_draw_glyphs for the meaning of HL. */
11017 static void
11018 x_draw_phys_cursor_glyph (w, row, hl)
11019 struct window *w;
11020 struct glyph_row *row;
11021 enum draw_glyphs_face hl;
11023 /* If cursor hpos is out of bounds, don't draw garbage. This can
11024 happen in mini-buffer windows when switching between echo area
11025 glyphs and mini-buffer. */
11026 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11028 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11029 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11030 hl, 0, 0, 0);
11032 /* When we erase the cursor, and ROW is overlapped by other
11033 rows, make sure that these overlapping parts of other rows
11034 are redrawn. */
11035 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11037 if (row > w->current_matrix->rows
11038 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11039 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11041 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11042 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11043 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11049 /* Erase the image of a cursor of window W from the screen. */
11051 static void
11052 x_erase_phys_cursor (w)
11053 struct window *w;
11055 struct frame *f = XFRAME (w->frame);
11056 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11057 int hpos = w->phys_cursor.hpos;
11058 int vpos = w->phys_cursor.vpos;
11059 int mouse_face_here_p = 0;
11060 struct glyph_matrix *active_glyphs = w->current_matrix;
11061 struct glyph_row *cursor_row;
11062 struct glyph *cursor_glyph;
11063 enum draw_glyphs_face hl;
11065 /* No cursor displayed or row invalidated => nothing to do on the
11066 screen. */
11067 if (w->phys_cursor_type == NO_CURSOR)
11068 goto mark_cursor_off;
11070 /* VPOS >= active_glyphs->nrows means that window has been resized.
11071 Don't bother to erase the cursor. */
11072 if (vpos >= active_glyphs->nrows)
11073 goto mark_cursor_off;
11075 /* If row containing cursor is marked invalid, there is nothing we
11076 can do. */
11077 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11078 if (!cursor_row->enabled_p)
11079 goto mark_cursor_off;
11081 /* This can happen when the new row is shorter than the old one.
11082 In this case, either x_draw_glyphs or clear_end_of_line
11083 should have cleared the cursor. Note that we wouldn't be
11084 able to erase the cursor in this case because we don't have a
11085 cursor glyph at hand. */
11086 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11087 goto mark_cursor_off;
11089 /* If the cursor is in the mouse face area, redisplay that when
11090 we clear the cursor. */
11091 if (! NILP (dpyinfo->mouse_face_window)
11092 && w == XWINDOW (dpyinfo->mouse_face_window)
11093 && (vpos > dpyinfo->mouse_face_beg_row
11094 || (vpos == dpyinfo->mouse_face_beg_row
11095 && hpos >= dpyinfo->mouse_face_beg_col))
11096 && (vpos < dpyinfo->mouse_face_end_row
11097 || (vpos == dpyinfo->mouse_face_end_row
11098 && hpos < dpyinfo->mouse_face_end_col))
11099 /* Don't redraw the cursor's spot in mouse face if it is at the
11100 end of a line (on a newline). The cursor appears there, but
11101 mouse highlighting does not. */
11102 && cursor_row->used[TEXT_AREA] > hpos)
11103 mouse_face_here_p = 1;
11105 /* Maybe clear the display under the cursor. */
11106 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11108 int x;
11109 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11111 cursor_glyph = get_phys_cursor_glyph (w);
11112 if (cursor_glyph == NULL)
11113 goto mark_cursor_off;
11115 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11117 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11119 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11120 cursor_row->y)),
11121 cursor_glyph->pixel_width,
11122 cursor_row->visible_height,
11123 False);
11126 /* Erase the cursor by redrawing the character underneath it. */
11127 if (mouse_face_here_p)
11128 hl = DRAW_MOUSE_FACE;
11129 else if (cursor_row->inverse_p)
11130 hl = DRAW_INVERSE_VIDEO;
11131 else
11132 hl = DRAW_NORMAL_TEXT;
11133 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11135 mark_cursor_off:
11136 w->phys_cursor_on_p = 0;
11137 w->phys_cursor_type = NO_CURSOR;
11141 /* Display or clear cursor of window W. If ON is zero, clear the
11142 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11143 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11145 void
11146 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11147 struct window *w;
11148 int on, hpos, vpos, x, y;
11150 struct frame *f = XFRAME (w->frame);
11151 int new_cursor_type;
11152 int new_cursor_width;
11153 struct glyph_matrix *current_glyphs;
11154 struct glyph_row *glyph_row;
11155 struct glyph *glyph;
11157 /* This is pointless on invisible frames, and dangerous on garbaged
11158 windows and frames; in the latter case, the frame or window may
11159 be in the midst of changing its size, and x and y may be off the
11160 window. */
11161 if (! FRAME_VISIBLE_P (f)
11162 || FRAME_GARBAGED_P (f)
11163 || vpos >= w->current_matrix->nrows
11164 || hpos >= w->current_matrix->matrix_w)
11165 return;
11167 /* If cursor is off and we want it off, return quickly. */
11168 if (!on && !w->phys_cursor_on_p)
11169 return;
11171 current_glyphs = w->current_matrix;
11172 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11173 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11175 /* If cursor row is not enabled, we don't really know where to
11176 display the cursor. */
11177 if (!glyph_row->enabled_p)
11179 w->phys_cursor_on_p = 0;
11180 return;
11183 xassert (interrupt_input_blocked);
11185 /* Set new_cursor_type to the cursor we want to be displayed. In a
11186 mini-buffer window, we want the cursor only to appear if we are
11187 reading input from this window. For the selected window, we want
11188 the cursor type given by the frame parameter. If explicitly
11189 marked off, draw no cursor. In all other cases, we want a hollow
11190 box cursor. */
11191 new_cursor_width = -1;
11192 if (cursor_in_echo_area
11193 && FRAME_HAS_MINIBUF_P (f)
11194 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11196 if (w == XWINDOW (echo_area_window))
11197 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11198 else
11199 new_cursor_type = HOLLOW_BOX_CURSOR;
11201 else
11203 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11204 || w != XWINDOW (f->selected_window))
11206 extern int cursor_in_non_selected_windows;
11208 if (MINI_WINDOW_P (w)
11209 || !cursor_in_non_selected_windows
11210 || NILP (XBUFFER (w->buffer)->cursor_type))
11211 new_cursor_type = NO_CURSOR;
11212 else
11213 new_cursor_type = HOLLOW_BOX_CURSOR;
11215 else if (w->cursor_off_p)
11216 new_cursor_type = NO_CURSOR;
11217 else
11219 struct buffer *b = XBUFFER (w->buffer);
11221 if (EQ (b->cursor_type, Qt))
11222 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11223 else
11224 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11225 &new_cursor_width);
11229 /* If cursor is currently being shown and we don't want it to be or
11230 it is in the wrong place, or the cursor type is not what we want,
11231 erase it. */
11232 if (w->phys_cursor_on_p
11233 && (!on
11234 || w->phys_cursor.x != x
11235 || w->phys_cursor.y != y
11236 || new_cursor_type != w->phys_cursor_type))
11237 x_erase_phys_cursor (w);
11239 /* If the cursor is now invisible and we want it to be visible,
11240 display it. */
11241 if (on && !w->phys_cursor_on_p)
11243 w->phys_cursor_ascent = glyph_row->ascent;
11244 w->phys_cursor_height = glyph_row->height;
11246 /* Set phys_cursor_.* before x_draw_.* is called because some
11247 of them may need the information. */
11248 w->phys_cursor.x = x;
11249 w->phys_cursor.y = glyph_row->y;
11250 w->phys_cursor.hpos = hpos;
11251 w->phys_cursor.vpos = vpos;
11252 w->phys_cursor_type = new_cursor_type;
11253 w->phys_cursor_on_p = 1;
11255 switch (new_cursor_type)
11257 case HOLLOW_BOX_CURSOR:
11258 x_draw_hollow_cursor (w, glyph_row);
11259 break;
11261 case FILLED_BOX_CURSOR:
11262 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11263 break;
11265 case BAR_CURSOR:
11266 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11267 break;
11269 case NO_CURSOR:
11270 break;
11272 default:
11273 abort ();
11276 #ifdef HAVE_X_I18N
11277 if (w == XWINDOW (f->selected_window))
11278 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11279 xic_set_preeditarea (w, x, y);
11280 #endif
11283 #ifndef XFlush
11284 if (updating_frame != f)
11285 XFlush (FRAME_X_DISPLAY (f));
11286 #endif
11290 /* Display the cursor on window W, or clear it. X and Y are window
11291 relative pixel coordinates. HPOS and VPOS are glyph matrix
11292 positions. If W is not the selected window, display a hollow
11293 cursor. ON non-zero means display the cursor at X, Y which
11294 correspond to HPOS, VPOS, otherwise it is cleared. */
11296 void
11297 x_display_cursor (w, on, hpos, vpos, x, y)
11298 struct window *w;
11299 int on, hpos, vpos, x, y;
11301 BLOCK_INPUT;
11302 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11303 UNBLOCK_INPUT;
11307 /* Display the cursor on window W, or clear it, according to ON_P.
11308 Don't change the cursor's position. */
11310 void
11311 x_update_cursor (f, on_p)
11312 struct frame *f;
11314 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11318 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11319 in the window tree rooted at W. */
11321 static void
11322 x_update_cursor_in_window_tree (w, on_p)
11323 struct window *w;
11324 int on_p;
11326 while (w)
11328 if (!NILP (w->hchild))
11329 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11330 else if (!NILP (w->vchild))
11331 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11332 else
11333 x_update_window_cursor (w, on_p);
11335 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11340 /* Switch the display of W's cursor on or off, according to the value
11341 of ON. */
11343 static void
11344 x_update_window_cursor (w, on)
11345 struct window *w;
11346 int on;
11348 /* Don't update cursor in windows whose frame is in the process
11349 of being deleted. */
11350 if (w->current_matrix)
11352 BLOCK_INPUT;
11353 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11354 w->phys_cursor.x, w->phys_cursor.y);
11355 UNBLOCK_INPUT;
11362 /* Icons. */
11364 /* Refresh bitmap kitchen sink icon for frame F
11365 when we get an expose event for it. */
11367 void
11368 refreshicon (f)
11369 struct frame *f;
11371 /* Normally, the window manager handles this function. */
11374 /* Make the x-window of frame F use the gnu icon bitmap. */
11377 x_bitmap_icon (f, file)
11378 struct frame *f;
11379 Lisp_Object file;
11381 int bitmap_id;
11383 if (FRAME_X_WINDOW (f) == 0)
11384 return 1;
11386 /* Free up our existing icon bitmap if any. */
11387 if (f->output_data.x->icon_bitmap > 0)
11388 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11389 f->output_data.x->icon_bitmap = 0;
11391 if (STRINGP (file))
11392 bitmap_id = x_create_bitmap_from_file (f, file);
11393 else
11395 /* Create the GNU bitmap if necessary. */
11396 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11397 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11398 = x_create_bitmap_from_data (f, gnu_bits,
11399 gnu_width, gnu_height);
11401 /* The first time we create the GNU bitmap,
11402 this increments the ref-count one extra time.
11403 As a result, the GNU bitmap is never freed.
11404 That way, we don't have to worry about allocating it again. */
11405 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11407 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11410 x_wm_set_icon_pixmap (f, bitmap_id);
11411 f->output_data.x->icon_bitmap = bitmap_id;
11413 return 0;
11417 /* Make the x-window of frame F use a rectangle with text.
11418 Use ICON_NAME as the text. */
11421 x_text_icon (f, icon_name)
11422 struct frame *f;
11423 char *icon_name;
11425 if (FRAME_X_WINDOW (f) == 0)
11426 return 1;
11428 #ifdef HAVE_X11R4
11430 XTextProperty text;
11431 text.value = (unsigned char *) icon_name;
11432 text.encoding = XA_STRING;
11433 text.format = 8;
11434 text.nitems = strlen (icon_name);
11435 #ifdef USE_X_TOOLKIT
11436 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11437 &text);
11438 #else /* not USE_X_TOOLKIT */
11439 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11440 #endif /* not USE_X_TOOLKIT */
11442 #else /* not HAVE_X11R4 */
11443 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11444 #endif /* not HAVE_X11R4 */
11446 if (f->output_data.x->icon_bitmap > 0)
11447 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11448 f->output_data.x->icon_bitmap = 0;
11449 x_wm_set_icon_pixmap (f, 0);
11451 return 0;
11454 #define X_ERROR_MESSAGE_SIZE 200
11456 /* If non-nil, this should be a string.
11457 It means catch X errors and store the error message in this string. */
11459 static Lisp_Object x_error_message_string;
11461 /* An X error handler which stores the error message in
11462 x_error_message_string. This is called from x_error_handler if
11463 x_catch_errors is in effect. */
11465 static void
11466 x_error_catcher (display, error)
11467 Display *display;
11468 XErrorEvent *error;
11470 XGetErrorText (display, error->error_code,
11471 XSTRING (x_error_message_string)->data,
11472 X_ERROR_MESSAGE_SIZE);
11475 /* Begin trapping X errors for display DPY. Actually we trap X errors
11476 for all displays, but DPY should be the display you are actually
11477 operating on.
11479 After calling this function, X protocol errors no longer cause
11480 Emacs to exit; instead, they are recorded in the string
11481 stored in x_error_message_string.
11483 Calling x_check_errors signals an Emacs error if an X error has
11484 occurred since the last call to x_catch_errors or x_check_errors.
11486 Calling x_uncatch_errors resumes the normal error handling. */
11488 void x_check_errors ();
11489 static Lisp_Object x_catch_errors_unwind ();
11492 x_catch_errors (dpy)
11493 Display *dpy;
11495 int count = specpdl_ptr - specpdl;
11497 /* Make sure any errors from previous requests have been dealt with. */
11498 XSync (dpy, False);
11500 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11502 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11503 XSTRING (x_error_message_string)->data[0] = 0;
11505 return count;
11508 /* Unbind the binding that we made to check for X errors. */
11510 static Lisp_Object
11511 x_catch_errors_unwind (old_val)
11512 Lisp_Object old_val;
11514 x_error_message_string = old_val;
11515 return Qnil;
11518 /* If any X protocol errors have arrived since the last call to
11519 x_catch_errors or x_check_errors, signal an Emacs error using
11520 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11522 void
11523 x_check_errors (dpy, format)
11524 Display *dpy;
11525 char *format;
11527 /* Make sure to catch any errors incurred so far. */
11528 XSync (dpy, False);
11530 if (XSTRING (x_error_message_string)->data[0])
11531 error (format, XSTRING (x_error_message_string)->data);
11534 /* Nonzero if we had any X protocol errors
11535 since we did x_catch_errors on DPY. */
11538 x_had_errors_p (dpy)
11539 Display *dpy;
11541 /* Make sure to catch any errors incurred so far. */
11542 XSync (dpy, False);
11544 return XSTRING (x_error_message_string)->data[0] != 0;
11547 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11549 void
11550 x_clear_errors (dpy)
11551 Display *dpy;
11553 XSTRING (x_error_message_string)->data[0] = 0;
11556 /* Stop catching X protocol errors and let them make Emacs die.
11557 DPY should be the display that was passed to x_catch_errors.
11558 COUNT should be the value that was returned by
11559 the corresponding call to x_catch_errors. */
11561 void
11562 x_uncatch_errors (dpy, count)
11563 Display *dpy;
11564 int count;
11566 unbind_to (count, Qnil);
11569 #if 0
11570 static unsigned int x_wire_count;
11571 x_trace_wire ()
11573 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11575 #endif /* ! 0 */
11578 /* Handle SIGPIPE, which can happen when the connection to a server
11579 simply goes away. SIGPIPE is handled by x_connection_signal.
11580 Don't need to do anything, because the write which caused the
11581 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11582 which will do the appropriate cleanup for us. */
11584 static SIGTYPE
11585 x_connection_signal (signalnum) /* If we don't have an argument, */
11586 int signalnum; /* some compilers complain in signal calls. */
11588 #ifdef USG
11589 /* USG systems forget handlers when they are used;
11590 must reestablish each time */
11591 signal (signalnum, x_connection_signal);
11592 #endif /* USG */
11596 /************************************************************************
11597 Handling X errors
11598 ************************************************************************/
11600 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11601 the text of an error message that lead to the connection loss. */
11603 static SIGTYPE
11604 x_connection_closed (dpy, error_message)
11605 Display *dpy;
11606 char *error_message;
11608 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11609 Lisp_Object frame, tail;
11610 int count;
11611 char *msg;
11613 msg = (char *) alloca (strlen (error_message) + 1);
11614 strcpy (msg, error_message);
11615 handling_signal = 0;
11617 /* Prevent being called recursively because of an error condition
11618 below. Otherwise, we might end up with printing ``can't find per
11619 display information'' in the recursive call instead of printing
11620 the original message here. */
11621 count = x_catch_errors (dpy);
11623 /* We have to close the display to inform Xt that it doesn't
11624 exist anymore. If we don't, Xt will continue to wait for
11625 events from the display. As a consequence, a sequence of
11627 M-x make-frame-on-display RET :1 RET
11628 ...kill the new frame, so that we get an IO error...
11629 M-x make-frame-on-display RET :1 RET
11631 will indefinitely wait in Xt for events for display `:1', opened
11632 in the first class to make-frame-on-display.
11634 Closing the display is reported to lead to a bus error on
11635 OpenWindows in certain situations. I suspect that is a bug
11636 in OpenWindows. I don't know how to cicumvent it here. */
11638 #ifdef USE_X_TOOLKIT
11639 /* If DPYINFO is null, this means we didn't open the display
11640 in the first place, so don't try to close it. */
11641 if (dpyinfo)
11642 XtCloseDisplay (dpy);
11643 #endif
11645 /* Indicate that this display is dead. */
11646 if (dpyinfo)
11647 dpyinfo->display = 0;
11649 /* First delete frames whose mini-buffers are on frames
11650 that are on the dead display. */
11651 FOR_EACH_FRAME (tail, frame)
11653 Lisp_Object minibuf_frame;
11654 minibuf_frame
11655 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11656 if (FRAME_X_P (XFRAME (frame))
11657 && FRAME_X_P (XFRAME (minibuf_frame))
11658 && ! EQ (frame, minibuf_frame)
11659 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11660 Fdelete_frame (frame, Qt);
11663 /* Now delete all remaining frames on the dead display.
11664 We are now sure none of these is used as the mini-buffer
11665 for another frame that we need to delete. */
11666 FOR_EACH_FRAME (tail, frame)
11667 if (FRAME_X_P (XFRAME (frame))
11668 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11670 /* Set this to t so that Fdelete_frame won't get confused
11671 trying to find a replacement. */
11672 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11673 Fdelete_frame (frame, Qt);
11676 if (dpyinfo)
11677 x_delete_display (dpyinfo);
11679 x_uncatch_errors (dpy, count);
11681 if (x_display_list == 0)
11683 fprintf (stderr, "%s\n", msg);
11684 shut_down_emacs (0, 0, Qnil);
11685 exit (70);
11688 /* Ordinary stack unwind doesn't deal with these. */
11689 #ifdef SIGIO
11690 sigunblock (sigmask (SIGIO));
11691 #endif
11692 sigunblock (sigmask (SIGALRM));
11693 TOTALLY_UNBLOCK_INPUT;
11695 clear_waiting_for_input ();
11696 error ("%s", msg);
11700 /* This is the usual handler for X protocol errors.
11701 It kills all frames on the display that we got the error for.
11702 If that was the only one, it prints an error message and kills Emacs. */
11704 static void
11705 x_error_quitter (display, error)
11706 Display *display;
11707 XErrorEvent *error;
11709 char buf[256], buf1[356];
11711 /* Note that there is no real way portable across R3/R4 to get the
11712 original error handler. */
11714 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11715 sprintf (buf1, "X protocol error: %s on protocol request %d",
11716 buf, error->request_code);
11717 x_connection_closed (display, buf1);
11721 /* This is the first-level handler for X protocol errors.
11722 It calls x_error_quitter or x_error_catcher. */
11724 static int
11725 x_error_handler (display, error)
11726 Display *display;
11727 XErrorEvent *error;
11729 if (! NILP (x_error_message_string))
11730 x_error_catcher (display, error);
11731 else
11732 x_error_quitter (display, error);
11733 return 0;
11736 /* This is the handler for X IO errors, always.
11737 It kills all frames on the display that we lost touch with.
11738 If that was the only one, it prints an error message and kills Emacs. */
11740 static int
11741 x_io_error_quitter (display)
11742 Display *display;
11744 char buf[256];
11746 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11747 x_connection_closed (display, buf);
11748 return 0;
11751 /* Changing the font of the frame. */
11753 /* Give frame F the font named FONTNAME as its default font, and
11754 return the full name of that font. FONTNAME may be a wildcard
11755 pattern; in that case, we choose some font that fits the pattern.
11756 The return value shows which font we chose. */
11758 Lisp_Object
11759 x_new_font (f, fontname)
11760 struct frame *f;
11761 register char *fontname;
11763 struct font_info *fontp
11764 = FS_LOAD_FONT (f, 0, fontname, -1);
11766 if (!fontp)
11767 return Qnil;
11769 f->output_data.x->font = (XFontStruct *) (fontp->font);
11770 f->output_data.x->baseline_offset = fontp->baseline_offset;
11771 f->output_data.x->fontset = -1;
11773 /* Compute the scroll bar width in character columns. */
11774 if (f->scroll_bar_pixel_width > 0)
11776 int wid = FONT_WIDTH (f->output_data.x->font);
11777 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11779 else
11781 int wid = FONT_WIDTH (f->output_data.x->font);
11782 f->scroll_bar_cols = (14 + wid - 1) / wid;
11785 /* Now make the frame display the given font. */
11786 if (FRAME_X_WINDOW (f) != 0)
11788 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11789 f->output_data.x->font->fid);
11790 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11791 f->output_data.x->font->fid);
11792 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11793 f->output_data.x->font->fid);
11795 frame_update_line_height (f);
11797 /* Don't change the size of a tip frame; there's no point in
11798 doing it because it's done in Fx_show_tip, and it leads to
11799 problems because the tip frame has no widget. */
11800 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11801 x_set_window_size (f, 0, f->width, f->height);
11803 else
11804 /* If we are setting a new frame's font for the first time,
11805 there are no faces yet, so this font's height is the line height. */
11806 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11808 return build_string (fontp->full_name);
11811 /* Give frame F the fontset named FONTSETNAME as its default font, and
11812 return the full name of that fontset. FONTSETNAME may be a wildcard
11813 pattern; in that case, we choose some fontset that fits the pattern.
11814 The return value shows which fontset we chose. */
11816 Lisp_Object
11817 x_new_fontset (f, fontsetname)
11818 struct frame *f;
11819 char *fontsetname;
11821 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11822 Lisp_Object result;
11824 if (fontset < 0)
11825 return Qnil;
11827 if (f->output_data.x->fontset == fontset)
11828 /* This fontset is already set in frame F. There's nothing more
11829 to do. */
11830 return fontset_name (fontset);
11832 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11834 if (!STRINGP (result))
11835 /* Can't load ASCII font. */
11836 return Qnil;
11838 /* Since x_new_font doesn't update any fontset information, do it now. */
11839 f->output_data.x->fontset = fontset;
11841 #ifdef HAVE_X_I18N
11842 if (FRAME_XIC (f)
11843 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11844 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11845 #endif
11847 return build_string (fontsetname);
11851 /***********************************************************************
11852 X Input Methods
11853 ***********************************************************************/
11855 #ifdef HAVE_X_I18N
11857 #ifdef HAVE_X11R6
11859 /* XIM destroy callback function, which is called whenever the
11860 connection to input method XIM dies. CLIENT_DATA contains a
11861 pointer to the x_display_info structure corresponding to XIM. */
11863 static void
11864 xim_destroy_callback (xim, client_data, call_data)
11865 XIM xim;
11866 XPointer client_data;
11867 XPointer call_data;
11869 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11870 Lisp_Object frame, tail;
11872 BLOCK_INPUT;
11874 /* No need to call XDestroyIC.. */
11875 FOR_EACH_FRAME (tail, frame)
11877 struct frame *f = XFRAME (frame);
11878 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11880 FRAME_XIC (f) = NULL;
11881 if (FRAME_XIC_FONTSET (f))
11883 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11884 FRAME_XIC_FONTSET (f) = NULL;
11889 /* No need to call XCloseIM. */
11890 dpyinfo->xim = NULL;
11891 XFree (dpyinfo->xim_styles);
11892 UNBLOCK_INPUT;
11895 #endif /* HAVE_X11R6 */
11897 /* Open the connection to the XIM server on display DPYINFO.
11898 RESOURCE_NAME is the resource name Emacs uses. */
11900 static void
11901 xim_open_dpy (dpyinfo, resource_name)
11902 struct x_display_info *dpyinfo;
11903 char *resource_name;
11905 #ifdef USE_XIM
11906 XIM xim;
11908 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11909 dpyinfo->xim = xim;
11911 if (xim)
11913 #ifdef HAVE_X11R6
11914 XIMCallback destroy;
11915 #endif
11917 /* Get supported styles and XIM values. */
11918 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11920 #ifdef HAVE_X11R6
11921 destroy.callback = xim_destroy_callback;
11922 destroy.client_data = (XPointer)dpyinfo;
11923 /* This isn't prptotyped in OSF 5.0. */
11924 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11925 #endif
11928 #else /* not USE_XIM */
11929 dpyinfo->xim = NULL;
11930 #endif /* not USE_XIM */
11934 #ifdef HAVE_X11R6_XIM
11936 struct xim_inst_t
11938 struct x_display_info *dpyinfo;
11939 char *resource_name;
11942 /* XIM instantiate callback function, which is called whenever an XIM
11943 server is available. DISPLAY is teh display of the XIM.
11944 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11945 when the callback was registered. */
11947 static void
11948 xim_instantiate_callback (display, client_data, call_data)
11949 Display *display;
11950 XPointer client_data;
11951 XPointer call_data;
11953 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11954 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11956 /* We don't support multiple XIM connections. */
11957 if (dpyinfo->xim)
11958 return;
11960 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11962 /* Create XIC for the existing frames on the same display, as long
11963 as they have no XIC. */
11964 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11966 Lisp_Object tail, frame;
11968 BLOCK_INPUT;
11969 FOR_EACH_FRAME (tail, frame)
11971 struct frame *f = XFRAME (frame);
11973 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11974 if (FRAME_XIC (f) == NULL)
11976 create_frame_xic (f);
11977 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11978 xic_set_statusarea (f);
11979 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11981 struct window *w = XWINDOW (f->selected_window);
11982 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11987 UNBLOCK_INPUT;
11991 #endif /* HAVE_X11R6_XIM */
11994 /* Open a connection to the XIM server on display DPYINFO.
11995 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11996 connection only at the first time. On X11R6, open the connection
11997 in the XIM instantiate callback function. */
11999 static void
12000 xim_initialize (dpyinfo, resource_name)
12001 struct x_display_info *dpyinfo;
12002 char *resource_name;
12004 #ifdef USE_XIM
12005 #ifdef HAVE_X11R6_XIM
12006 struct xim_inst_t *xim_inst;
12007 int len;
12009 dpyinfo->xim = NULL;
12010 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12011 xim_inst->dpyinfo = dpyinfo;
12012 len = strlen (resource_name);
12013 xim_inst->resource_name = (char *) xmalloc (len + 1);
12014 bcopy (resource_name, xim_inst->resource_name, len + 1);
12015 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12016 resource_name, EMACS_CLASS,
12017 xim_instantiate_callback,
12018 /* Fixme: This is XPointer in
12019 XFree86 but (XPointer *) on
12020 Tru64, at least. */
12021 (XPointer) xim_inst);
12022 #else /* not HAVE_X11R6_XIM */
12023 dpyinfo->xim = NULL;
12024 xim_open_dpy (dpyinfo, resource_name);
12025 #endif /* not HAVE_X11R6_XIM */
12027 #else /* not USE_XIM */
12028 dpyinfo->xim = NULL;
12029 #endif /* not USE_XIM */
12033 /* Close the connection to the XIM server on display DPYINFO. */
12035 static void
12036 xim_close_dpy (dpyinfo)
12037 struct x_display_info *dpyinfo;
12039 #ifdef USE_XIM
12040 #ifdef HAVE_X11R6_XIM
12041 if (dpyinfo->display)
12042 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12043 NULL, EMACS_CLASS,
12044 xim_instantiate_callback, NULL);
12045 #endif /* not HAVE_X11R6_XIM */
12046 if (dpyinfo->display)
12047 XCloseIM (dpyinfo->xim);
12048 dpyinfo->xim = NULL;
12049 XFree (dpyinfo->xim_styles);
12050 #endif /* USE_XIM */
12053 #endif /* not HAVE_X11R6_XIM */
12057 /* Calculate the absolute position in frame F
12058 from its current recorded position values and gravity. */
12060 void
12061 x_calc_absolute_position (f)
12062 struct frame *f;
12064 Window child;
12065 int win_x = 0, win_y = 0;
12066 int flags = f->output_data.x->size_hint_flags;
12067 int this_window;
12069 /* We have nothing to do if the current position
12070 is already for the top-left corner. */
12071 if (! ((flags & XNegative) || (flags & YNegative)))
12072 return;
12074 #ifdef USE_X_TOOLKIT
12075 this_window = XtWindow (f->output_data.x->widget);
12076 #else
12077 this_window = FRAME_X_WINDOW (f);
12078 #endif
12080 /* Find the position of the outside upper-left corner of
12081 the inner window, with respect to the outer window.
12082 But do this only if we will need the results. */
12083 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12085 int count;
12087 BLOCK_INPUT;
12088 count = x_catch_errors (FRAME_X_DISPLAY (f));
12089 while (1)
12091 x_clear_errors (FRAME_X_DISPLAY (f));
12092 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12094 /* From-window, to-window. */
12095 this_window,
12096 f->output_data.x->parent_desc,
12098 /* From-position, to-position. */
12099 0, 0, &win_x, &win_y,
12101 /* Child of win. */
12102 &child);
12103 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12105 Window newroot, newparent = 0xdeadbeef;
12106 Window *newchildren;
12107 unsigned int nchildren;
12109 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12110 &newparent, &newchildren, &nchildren))
12111 break;
12113 XFree ((char *) newchildren);
12115 f->output_data.x->parent_desc = newparent;
12117 else
12118 break;
12121 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12122 UNBLOCK_INPUT;
12125 /* Treat negative positions as relative to the leftmost bottommost
12126 position that fits on the screen. */
12127 if (flags & XNegative)
12128 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12129 - 2 * f->output_data.x->border_width - win_x
12130 - PIXEL_WIDTH (f)
12131 + f->output_data.x->left_pos);
12134 int height = PIXEL_HEIGHT (f);
12136 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12137 /* Something is fishy here. When using Motif, starting Emacs with
12138 `-g -0-0', the frame appears too low by a few pixels.
12140 This seems to be so because initially, while Emacs is starting,
12141 the column widget's height and the frame's pixel height are
12142 different. The column widget's height is the right one. In
12143 later invocations, when Emacs is up, the frame's pixel height
12144 is right, though.
12146 It's not obvious where the initial small difference comes from.
12147 2000-12-01, gerd. */
12149 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12150 #endif
12152 if (flags & YNegative)
12153 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12154 - 2 * f->output_data.x->border_width
12155 - win_y
12156 - height
12157 + f->output_data.x->top_pos);
12160 /* The left_pos and top_pos
12161 are now relative to the top and left screen edges,
12162 so the flags should correspond. */
12163 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12166 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12167 to really change the position, and 0 when calling from
12168 x_make_frame_visible (in that case, XOFF and YOFF are the current
12169 position values). It is -1 when calling from x_set_frame_parameters,
12170 which means, do adjust for borders but don't change the gravity. */
12172 void
12173 x_set_offset (f, xoff, yoff, change_gravity)
12174 struct frame *f;
12175 register int xoff, yoff;
12176 int change_gravity;
12178 int modified_top, modified_left;
12180 if (change_gravity > 0)
12182 f->output_data.x->top_pos = yoff;
12183 f->output_data.x->left_pos = xoff;
12184 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12185 if (xoff < 0)
12186 f->output_data.x->size_hint_flags |= XNegative;
12187 if (yoff < 0)
12188 f->output_data.x->size_hint_flags |= YNegative;
12189 f->output_data.x->win_gravity = NorthWestGravity;
12191 x_calc_absolute_position (f);
12193 BLOCK_INPUT;
12194 x_wm_set_size_hint (f, (long) 0, 0);
12196 modified_left = f->output_data.x->left_pos;
12197 modified_top = f->output_data.x->top_pos;
12198 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12199 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12200 /* It is a mystery why we need to add the border_width here
12201 when the frame is already visible, but experiment says we do. */
12202 if (change_gravity != 0)
12204 modified_left += f->output_data.x->border_width;
12205 modified_top += f->output_data.x->border_width;
12207 #endif
12209 #ifdef USE_X_TOOLKIT
12210 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12211 modified_left, modified_top);
12212 #else /* not USE_X_TOOLKIT */
12213 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12214 modified_left, modified_top);
12215 #endif /* not USE_X_TOOLKIT */
12216 UNBLOCK_INPUT;
12220 /* Change the size of frame F's X window to COLS/ROWS in the case F
12221 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12222 top-left-corner window gravity for this size change and subsequent
12223 size changes. Otherwise we leave the window gravity unchanged. */
12225 static void
12226 x_set_window_size_1 (f, change_gravity, cols, rows)
12227 struct frame *f;
12228 int change_gravity;
12229 int cols, rows;
12231 int pixelwidth, pixelheight;
12233 check_frame_size (f, &rows, &cols);
12234 f->output_data.x->vertical_scroll_bar_extra
12235 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12237 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12238 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12239 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12240 f->output_data.x->flags_areas_extra
12241 = FRAME_FLAGS_AREA_WIDTH (f);
12242 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12243 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12245 f->output_data.x->win_gravity = NorthWestGravity;
12246 x_wm_set_size_hint (f, (long) 0, 0);
12248 XSync (FRAME_X_DISPLAY (f), False);
12249 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12250 pixelwidth, pixelheight);
12252 /* Now, strictly speaking, we can't be sure that this is accurate,
12253 but the window manager will get around to dealing with the size
12254 change request eventually, and we'll hear how it went when the
12255 ConfigureNotify event gets here.
12257 We could just not bother storing any of this information here,
12258 and let the ConfigureNotify event set everything up, but that
12259 might be kind of confusing to the Lisp code, since size changes
12260 wouldn't be reported in the frame parameters until some random
12261 point in the future when the ConfigureNotify event arrives.
12263 We pass 1 for DELAY since we can't run Lisp code inside of
12264 a BLOCK_INPUT. */
12265 change_frame_size (f, rows, cols, 0, 1, 0);
12266 PIXEL_WIDTH (f) = pixelwidth;
12267 PIXEL_HEIGHT (f) = pixelheight;
12269 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12270 receive in the ConfigureNotify event; if we get what we asked
12271 for, then the event won't cause the screen to become garbaged, so
12272 we have to make sure to do it here. */
12273 SET_FRAME_GARBAGED (f);
12275 XFlush (FRAME_X_DISPLAY (f));
12279 /* Call this to change the size of frame F's x-window.
12280 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12281 for this size change and subsequent size changes.
12282 Otherwise we leave the window gravity unchanged. */
12284 void
12285 x_set_window_size (f, change_gravity, cols, rows)
12286 struct frame *f;
12287 int change_gravity;
12288 int cols, rows;
12290 BLOCK_INPUT;
12292 #ifdef USE_X_TOOLKIT
12294 if (f->output_data.x->widget != NULL)
12296 /* The x and y position of the widget is clobbered by the
12297 call to XtSetValues within EmacsFrameSetCharSize.
12298 This is a real kludge, but I don't understand Xt so I can't
12299 figure out a correct fix. Can anyone else tell me? -- rms. */
12300 int xpos = f->output_data.x->widget->core.x;
12301 int ypos = f->output_data.x->widget->core.y;
12302 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12303 f->output_data.x->widget->core.x = xpos;
12304 f->output_data.x->widget->core.y = ypos;
12306 else
12307 x_set_window_size_1 (f, change_gravity, cols, rows);
12309 #else /* not USE_X_TOOLKIT */
12311 x_set_window_size_1 (f, change_gravity, cols, rows);
12313 #endif /* not USE_X_TOOLKIT */
12315 /* If cursor was outside the new size, mark it as off. */
12316 mark_window_cursors_off (XWINDOW (f->root_window));
12318 /* Clear out any recollection of where the mouse highlighting was,
12319 since it might be in a place that's outside the new frame size.
12320 Actually checking whether it is outside is a pain in the neck,
12321 so don't try--just let the highlighting be done afresh with new size. */
12322 cancel_mouse_face (f);
12324 UNBLOCK_INPUT;
12327 /* Mouse warping. */
12329 void
12330 x_set_mouse_position (f, x, y)
12331 struct frame *f;
12332 int x, y;
12334 int pix_x, pix_y;
12336 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12337 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12339 if (pix_x < 0) pix_x = 0;
12340 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12342 if (pix_y < 0) pix_y = 0;
12343 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12345 BLOCK_INPUT;
12347 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12348 0, 0, 0, 0, pix_x, pix_y);
12349 UNBLOCK_INPUT;
12352 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12354 void
12355 x_set_mouse_pixel_position (f, pix_x, pix_y)
12356 struct frame *f;
12357 int pix_x, pix_y;
12359 BLOCK_INPUT;
12361 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12362 0, 0, 0, 0, pix_x, pix_y);
12363 UNBLOCK_INPUT;
12366 /* focus shifting, raising and lowering. */
12368 void
12369 x_focus_on_frame (f)
12370 struct frame *f;
12372 #if 0 /* This proves to be unpleasant. */
12373 x_raise_frame (f);
12374 #endif
12375 #if 0
12376 /* I don't think that the ICCCM allows programs to do things like this
12377 without the interaction of the window manager. Whatever you end up
12378 doing with this code, do it to x_unfocus_frame too. */
12379 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12380 RevertToPointerRoot, CurrentTime);
12381 #endif /* ! 0 */
12384 void
12385 x_unfocus_frame (f)
12386 struct frame *f;
12388 #if 0
12389 /* Look at the remarks in x_focus_on_frame. */
12390 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12391 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12392 RevertToPointerRoot, CurrentTime);
12393 #endif /* ! 0 */
12396 /* Raise frame F. */
12398 void
12399 x_raise_frame (f)
12400 struct frame *f;
12402 if (f->async_visible)
12404 BLOCK_INPUT;
12405 #ifdef USE_X_TOOLKIT
12406 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12407 #else /* not USE_X_TOOLKIT */
12408 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12409 #endif /* not USE_X_TOOLKIT */
12410 XFlush (FRAME_X_DISPLAY (f));
12411 UNBLOCK_INPUT;
12415 /* Lower frame F. */
12417 void
12418 x_lower_frame (f)
12419 struct frame *f;
12421 if (f->async_visible)
12423 BLOCK_INPUT;
12424 #ifdef USE_X_TOOLKIT
12425 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12426 #else /* not USE_X_TOOLKIT */
12427 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12428 #endif /* not USE_X_TOOLKIT */
12429 XFlush (FRAME_X_DISPLAY (f));
12430 UNBLOCK_INPUT;
12434 static void
12435 XTframe_raise_lower (f, raise_flag)
12436 FRAME_PTR f;
12437 int raise_flag;
12439 if (raise_flag)
12440 x_raise_frame (f);
12441 else
12442 x_lower_frame (f);
12445 /* Change of visibility. */
12447 /* This tries to wait until the frame is really visible.
12448 However, if the window manager asks the user where to position
12449 the frame, this will return before the user finishes doing that.
12450 The frame will not actually be visible at that time,
12451 but it will become visible later when the window manager
12452 finishes with it. */
12454 void
12455 x_make_frame_visible (f)
12456 struct frame *f;
12458 Lisp_Object type;
12459 int original_top, original_left;
12460 int retry_count = 2;
12462 retry:
12464 BLOCK_INPUT;
12466 type = x_icon_type (f);
12467 if (!NILP (type))
12468 x_bitmap_icon (f, type);
12470 if (! FRAME_VISIBLE_P (f))
12472 /* We test FRAME_GARBAGED_P here to make sure we don't
12473 call x_set_offset a second time
12474 if we get to x_make_frame_visible a second time
12475 before the window gets really visible. */
12476 if (! FRAME_ICONIFIED_P (f)
12477 && ! f->output_data.x->asked_for_visible)
12478 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12480 f->output_data.x->asked_for_visible = 1;
12482 if (! EQ (Vx_no_window_manager, Qt))
12483 x_wm_set_window_state (f, NormalState);
12484 #ifdef USE_X_TOOLKIT
12485 /* This was XtPopup, but that did nothing for an iconified frame. */
12486 XtMapWidget (f->output_data.x->widget);
12487 #else /* not USE_X_TOOLKIT */
12488 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12489 #endif /* not USE_X_TOOLKIT */
12490 #if 0 /* This seems to bring back scroll bars in the wrong places
12491 if the window configuration has changed. They seem
12492 to come back ok without this. */
12493 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12494 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12495 #endif
12498 XFlush (FRAME_X_DISPLAY (f));
12500 /* Synchronize to ensure Emacs knows the frame is visible
12501 before we do anything else. We do this loop with input not blocked
12502 so that incoming events are handled. */
12504 Lisp_Object frame;
12505 int count;
12506 /* This must be before UNBLOCK_INPUT
12507 since events that arrive in response to the actions above
12508 will set it when they are handled. */
12509 int previously_visible = f->output_data.x->has_been_visible;
12511 original_left = f->output_data.x->left_pos;
12512 original_top = f->output_data.x->top_pos;
12514 /* This must come after we set COUNT. */
12515 UNBLOCK_INPUT;
12517 /* We unblock here so that arriving X events are processed. */
12519 /* Now move the window back to where it was "supposed to be".
12520 But don't do it if the gravity is negative.
12521 When the gravity is negative, this uses a position
12522 that is 3 pixels too low. Perhaps that's really the border width.
12524 Don't do this if the window has never been visible before,
12525 because the window manager may choose the position
12526 and we don't want to override it. */
12528 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12529 && f->output_data.x->win_gravity == NorthWestGravity
12530 && previously_visible)
12532 Drawable rootw;
12533 int x, y;
12534 unsigned int width, height, border, depth;
12536 BLOCK_INPUT;
12538 /* On some window managers (such as FVWM) moving an existing
12539 window, even to the same place, causes the window manager
12540 to introduce an offset. This can cause the window to move
12541 to an unexpected location. Check the geometry (a little
12542 slow here) and then verify that the window is in the right
12543 place. If the window is not in the right place, move it
12544 there, and take the potential window manager hit. */
12545 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12546 &rootw, &x, &y, &width, &height, &border, &depth);
12548 if (original_left != x || original_top != y)
12549 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12550 original_left, original_top);
12552 UNBLOCK_INPUT;
12555 XSETFRAME (frame, f);
12557 /* Wait until the frame is visible. Process X events until a
12558 MapNotify event has been seen, or until we think we won't get a
12559 MapNotify at all.. */
12560 for (count = input_signal_count + 10;
12561 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12563 /* Force processing of queued events. */
12564 x_sync (f);
12566 /* Machines that do polling rather than SIGIO have been
12567 observed to go into a busy-wait here. So we'll fake an
12568 alarm signal to let the handler know that there's something
12569 to be read. We used to raise a real alarm, but it seems
12570 that the handler isn't always enabled here. This is
12571 probably a bug. */
12572 if (input_polling_used ())
12574 /* It could be confusing if a real alarm arrives while
12575 processing the fake one. Turn it off and let the
12576 handler reset it. */
12577 extern void poll_for_input_1 P_ ((void));
12578 int old_poll_suppress_count = poll_suppress_count;
12579 poll_suppress_count = 1;
12580 poll_for_input_1 ();
12581 poll_suppress_count = old_poll_suppress_count;
12584 /* See if a MapNotify event has been processed. */
12585 FRAME_SAMPLE_VISIBILITY (f);
12588 /* 2000-09-28: In
12590 (let ((f (selected-frame)))
12591 (iconify-frame f)
12592 (raise-frame f))
12594 the frame is not raised with various window managers on
12595 FreeBSD, Linux and Solaris. It turns out that, for some
12596 unknown reason, the call to XtMapWidget is completely ignored.
12597 Mapping the widget a second time works. */
12599 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12600 goto retry;
12604 /* Change from mapped state to withdrawn state. */
12606 /* Make the frame visible (mapped and not iconified). */
12608 void
12609 x_make_frame_invisible (f)
12610 struct frame *f;
12612 Window window;
12614 #ifdef USE_X_TOOLKIT
12615 /* Use the frame's outermost window, not the one we normally draw on. */
12616 window = XtWindow (f->output_data.x->widget);
12617 #else /* not USE_X_TOOLKIT */
12618 window = FRAME_X_WINDOW (f);
12619 #endif /* not USE_X_TOOLKIT */
12621 /* Don't keep the highlight on an invisible frame. */
12622 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12623 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12625 #if 0/* This might add unreliability; I don't trust it -- rms. */
12626 if (! f->async_visible && ! f->async_iconified)
12627 return;
12628 #endif
12630 BLOCK_INPUT;
12632 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12633 that the current position of the window is user-specified, rather than
12634 program-specified, so that when the window is mapped again, it will be
12635 placed at the same location, without forcing the user to position it
12636 by hand again (they have already done that once for this window.) */
12637 x_wm_set_size_hint (f, (long) 0, 1);
12639 #ifdef HAVE_X11R4
12641 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12642 DefaultScreen (FRAME_X_DISPLAY (f))))
12644 UNBLOCK_INPUT_RESIGNAL;
12645 error ("Can't notify window manager of window withdrawal");
12647 #else /* ! defined (HAVE_X11R4) */
12649 /* Tell the window manager what we're going to do. */
12650 if (! EQ (Vx_no_window_manager, Qt))
12652 XEvent unmap;
12654 unmap.xunmap.type = UnmapNotify;
12655 unmap.xunmap.window = window;
12656 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12657 unmap.xunmap.from_configure = False;
12658 if (! XSendEvent (FRAME_X_DISPLAY (f),
12659 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12660 False,
12661 SubstructureRedirectMaskSubstructureNotifyMask,
12662 &unmap))
12664 UNBLOCK_INPUT_RESIGNAL;
12665 error ("Can't notify window manager of withdrawal");
12669 /* Unmap the window ourselves. Cheeky! */
12670 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12671 #endif /* ! defined (HAVE_X11R4) */
12673 /* We can't distinguish this from iconification
12674 just by the event that we get from the server.
12675 So we can't win using the usual strategy of letting
12676 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12677 and synchronize with the server to make sure we agree. */
12678 f->visible = 0;
12679 FRAME_ICONIFIED_P (f) = 0;
12680 f->async_visible = 0;
12681 f->async_iconified = 0;
12683 x_sync (f);
12685 UNBLOCK_INPUT;
12688 /* Change window state from mapped to iconified. */
12690 void
12691 x_iconify_frame (f)
12692 struct frame *f;
12694 int result;
12695 Lisp_Object type;
12697 /* Don't keep the highlight on an invisible frame. */
12698 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12699 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12701 if (f->async_iconified)
12702 return;
12704 BLOCK_INPUT;
12706 FRAME_SAMPLE_VISIBILITY (f);
12708 type = x_icon_type (f);
12709 if (!NILP (type))
12710 x_bitmap_icon (f, type);
12712 #ifdef USE_X_TOOLKIT
12714 if (! FRAME_VISIBLE_P (f))
12716 if (! EQ (Vx_no_window_manager, Qt))
12717 x_wm_set_window_state (f, IconicState);
12718 /* This was XtPopup, but that did nothing for an iconified frame. */
12719 XtMapWidget (f->output_data.x->widget);
12720 /* The server won't give us any event to indicate
12721 that an invisible frame was changed to an icon,
12722 so we have to record it here. */
12723 f->iconified = 1;
12724 f->visible = 1;
12725 f->async_iconified = 1;
12726 f->async_visible = 0;
12727 UNBLOCK_INPUT;
12728 return;
12731 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12732 XtWindow (f->output_data.x->widget),
12733 DefaultScreen (FRAME_X_DISPLAY (f)));
12734 UNBLOCK_INPUT;
12736 if (!result)
12737 error ("Can't notify window manager of iconification");
12739 f->async_iconified = 1;
12740 f->async_visible = 0;
12743 BLOCK_INPUT;
12744 XFlush (FRAME_X_DISPLAY (f));
12745 UNBLOCK_INPUT;
12746 #else /* not USE_X_TOOLKIT */
12748 /* Make sure the X server knows where the window should be positioned,
12749 in case the user deiconifies with the window manager. */
12750 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12751 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12753 /* Since we don't know which revision of X we're running, we'll use both
12754 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12756 /* X11R4: send a ClientMessage to the window manager using the
12757 WM_CHANGE_STATE type. */
12759 XEvent message;
12761 message.xclient.window = FRAME_X_WINDOW (f);
12762 message.xclient.type = ClientMessage;
12763 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12764 message.xclient.format = 32;
12765 message.xclient.data.l[0] = IconicState;
12767 if (! XSendEvent (FRAME_X_DISPLAY (f),
12768 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12769 False,
12770 SubstructureRedirectMask | SubstructureNotifyMask,
12771 &message))
12773 UNBLOCK_INPUT_RESIGNAL;
12774 error ("Can't notify window manager of iconification");
12778 /* X11R3: set the initial_state field of the window manager hints to
12779 IconicState. */
12780 x_wm_set_window_state (f, IconicState);
12782 if (!FRAME_VISIBLE_P (f))
12784 /* If the frame was withdrawn, before, we must map it. */
12785 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12788 f->async_iconified = 1;
12789 f->async_visible = 0;
12791 XFlush (FRAME_X_DISPLAY (f));
12792 UNBLOCK_INPUT;
12793 #endif /* not USE_X_TOOLKIT */
12797 /* Free X resources of frame F. */
12799 void
12800 x_free_frame_resources (f)
12801 struct frame *f;
12803 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12805 BLOCK_INPUT;
12807 /* If a display connection is dead, don't try sending more
12808 commands to the X server. */
12809 if (dpyinfo->display)
12811 if (f->output_data.x->icon_desc)
12812 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12814 #ifdef HAVE_X_I18N
12815 if (FRAME_XIC (f))
12816 free_frame_xic (f);
12817 #endif
12819 if (FRAME_X_WINDOW (f))
12820 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12822 #ifdef USE_X_TOOLKIT
12823 if (f->output_data.x->widget)
12824 XtDestroyWidget (f->output_data.x->widget);
12825 free_frame_menubar (f);
12826 #endif /* USE_X_TOOLKIT */
12828 unload_color (f, f->output_data.x->foreground_pixel);
12829 unload_color (f, f->output_data.x->background_pixel);
12830 unload_color (f, f->output_data.x->cursor_pixel);
12831 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12832 unload_color (f, f->output_data.x->border_pixel);
12833 unload_color (f, f->output_data.x->mouse_pixel);
12835 if (f->output_data.x->scroll_bar_background_pixel != -1)
12836 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12837 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12838 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12839 if (f->output_data.x->white_relief.allocated_p)
12840 unload_color (f, f->output_data.x->white_relief.pixel);
12841 if (f->output_data.x->black_relief.allocated_p)
12842 unload_color (f, f->output_data.x->black_relief.pixel);
12844 if (FRAME_FACE_CACHE (f))
12845 free_frame_faces (f);
12847 x_free_gcs (f);
12848 XFlush (FRAME_X_DISPLAY (f));
12851 if (f->output_data.x->saved_menu_event)
12852 xfree (f->output_data.x->saved_menu_event);
12854 xfree (f->output_data.x);
12855 f->output_data.x = NULL;
12857 if (f == dpyinfo->x_focus_frame)
12858 dpyinfo->x_focus_frame = 0;
12859 if (f == dpyinfo->x_focus_event_frame)
12860 dpyinfo->x_focus_event_frame = 0;
12861 if (f == dpyinfo->x_highlight_frame)
12862 dpyinfo->x_highlight_frame = 0;
12864 if (f == dpyinfo->mouse_face_mouse_frame)
12866 dpyinfo->mouse_face_beg_row
12867 = dpyinfo->mouse_face_beg_col = -1;
12868 dpyinfo->mouse_face_end_row
12869 = dpyinfo->mouse_face_end_col = -1;
12870 dpyinfo->mouse_face_window = Qnil;
12871 dpyinfo->mouse_face_deferred_gc = 0;
12872 dpyinfo->mouse_face_mouse_frame = 0;
12875 UNBLOCK_INPUT;
12879 /* Destroy the X window of frame F. */
12881 void
12882 x_destroy_window (f)
12883 struct frame *f;
12885 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12887 /* If a display connection is dead, don't try sending more
12888 commands to the X server. */
12889 if (dpyinfo->display != 0)
12890 x_free_frame_resources (f);
12892 dpyinfo->reference_count--;
12896 /* Setting window manager hints. */
12898 /* Set the normal size hints for the window manager, for frame F.
12899 FLAGS is the flags word to use--or 0 meaning preserve the flags
12900 that the window now has.
12901 If USER_POSITION is nonzero, we set the USPosition
12902 flag (this is useful when FLAGS is 0). */
12904 void
12905 x_wm_set_size_hint (f, flags, user_position)
12906 struct frame *f;
12907 long flags;
12908 int user_position;
12910 XSizeHints size_hints;
12912 #ifdef USE_X_TOOLKIT
12913 Arg al[2];
12914 int ac = 0;
12915 Dimension widget_width, widget_height;
12916 Window window = XtWindow (f->output_data.x->widget);
12917 #else /* not USE_X_TOOLKIT */
12918 Window window = FRAME_X_WINDOW (f);
12919 #endif /* not USE_X_TOOLKIT */
12921 /* Setting PMaxSize caused various problems. */
12922 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12924 size_hints.x = f->output_data.x->left_pos;
12925 size_hints.y = f->output_data.x->top_pos;
12927 #ifdef USE_X_TOOLKIT
12928 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12929 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12930 XtGetValues (f->output_data.x->widget, al, ac);
12931 size_hints.height = widget_height;
12932 size_hints.width = widget_width;
12933 #else /* not USE_X_TOOLKIT */
12934 size_hints.height = PIXEL_HEIGHT (f);
12935 size_hints.width = PIXEL_WIDTH (f);
12936 #endif /* not USE_X_TOOLKIT */
12938 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12939 size_hints.height_inc = f->output_data.x->line_height;
12940 size_hints.max_width
12941 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12942 size_hints.max_height
12943 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12945 /* Calculate the base and minimum sizes.
12947 (When we use the X toolkit, we don't do it here.
12948 Instead we copy the values that the widgets are using, below.) */
12949 #ifndef USE_X_TOOLKIT
12951 int base_width, base_height;
12952 int min_rows = 0, min_cols = 0;
12954 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12955 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12957 check_frame_size (f, &min_rows, &min_cols);
12959 /* The window manager uses the base width hints to calculate the
12960 current number of rows and columns in the frame while
12961 resizing; min_width and min_height aren't useful for this
12962 purpose, since they might not give the dimensions for a
12963 zero-row, zero-column frame.
12965 We use the base_width and base_height members if we have
12966 them; otherwise, we set the min_width and min_height members
12967 to the size for a zero x zero frame. */
12969 #ifdef HAVE_X11R4
12970 size_hints.flags |= PBaseSize;
12971 size_hints.base_width = base_width;
12972 size_hints.base_height = base_height;
12973 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12974 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12975 #else
12976 size_hints.min_width = base_width;
12977 size_hints.min_height = base_height;
12978 #endif
12981 /* If we don't need the old flags, we don't need the old hint at all. */
12982 if (flags)
12984 size_hints.flags |= flags;
12985 goto no_read;
12987 #endif /* not USE_X_TOOLKIT */
12990 XSizeHints hints; /* Sometimes I hate X Windows... */
12991 long supplied_return;
12992 int value;
12994 #ifdef HAVE_X11R4
12995 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12996 &supplied_return);
12997 #else
12998 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12999 #endif
13001 #ifdef USE_X_TOOLKIT
13002 size_hints.base_height = hints.base_height;
13003 size_hints.base_width = hints.base_width;
13004 size_hints.min_height = hints.min_height;
13005 size_hints.min_width = hints.min_width;
13006 #endif
13008 if (flags)
13009 size_hints.flags |= flags;
13010 else
13012 if (value == 0)
13013 hints.flags = 0;
13014 if (hints.flags & PSize)
13015 size_hints.flags |= PSize;
13016 if (hints.flags & PPosition)
13017 size_hints.flags |= PPosition;
13018 if (hints.flags & USPosition)
13019 size_hints.flags |= USPosition;
13020 if (hints.flags & USSize)
13021 size_hints.flags |= USSize;
13025 #ifndef USE_X_TOOLKIT
13026 no_read:
13027 #endif
13029 #ifdef PWinGravity
13030 size_hints.win_gravity = f->output_data.x->win_gravity;
13031 size_hints.flags |= PWinGravity;
13033 if (user_position)
13035 size_hints.flags &= ~ PPosition;
13036 size_hints.flags |= USPosition;
13038 #endif /* PWinGravity */
13040 #ifdef HAVE_X11R4
13041 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13042 #else
13043 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13044 #endif
13047 /* Used for IconicState or NormalState */
13049 void
13050 x_wm_set_window_state (f, state)
13051 struct frame *f;
13052 int state;
13054 #ifdef USE_X_TOOLKIT
13055 Arg al[1];
13057 XtSetArg (al[0], XtNinitialState, state);
13058 XtSetValues (f->output_data.x->widget, al, 1);
13059 #else /* not USE_X_TOOLKIT */
13060 Window window = FRAME_X_WINDOW (f);
13062 f->output_data.x->wm_hints.flags |= StateHint;
13063 f->output_data.x->wm_hints.initial_state = state;
13065 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13066 #endif /* not USE_X_TOOLKIT */
13069 void
13070 x_wm_set_icon_pixmap (f, pixmap_id)
13071 struct frame *f;
13072 int pixmap_id;
13074 Pixmap icon_pixmap;
13076 #ifndef USE_X_TOOLKIT
13077 Window window = FRAME_X_WINDOW (f);
13078 #endif
13080 if (pixmap_id > 0)
13082 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13083 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13085 else
13087 /* It seems there is no way to turn off use of an icon pixmap.
13088 The following line does it, only if no icon has yet been created,
13089 for some window managers. But with mwm it crashes.
13090 Some people say it should clear the IconPixmapHint bit in this case,
13091 but that doesn't work, and the X consortium said it isn't the
13092 right thing at all. Since there is no way to win,
13093 best to explicitly give up. */
13094 #if 0
13095 f->output_data.x->wm_hints.icon_pixmap = None;
13096 #else
13097 return;
13098 #endif
13101 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13104 Arg al[1];
13105 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13106 XtSetValues (f->output_data.x->widget, al, 1);
13109 #else /* not USE_X_TOOLKIT */
13111 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13112 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13114 #endif /* not USE_X_TOOLKIT */
13117 void
13118 x_wm_set_icon_position (f, icon_x, icon_y)
13119 struct frame *f;
13120 int icon_x, icon_y;
13122 #ifdef USE_X_TOOLKIT
13123 Window window = XtWindow (f->output_data.x->widget);
13124 #else
13125 Window window = FRAME_X_WINDOW (f);
13126 #endif
13128 f->output_data.x->wm_hints.flags |= IconPositionHint;
13129 f->output_data.x->wm_hints.icon_x = icon_x;
13130 f->output_data.x->wm_hints.icon_y = icon_y;
13132 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13136 /***********************************************************************
13137 Fonts
13138 ***********************************************************************/
13140 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13142 struct font_info *
13143 x_get_font_info (f, font_idx)
13144 FRAME_PTR f;
13145 int font_idx;
13147 return (FRAME_X_FONT_TABLE (f) + font_idx);
13151 /* Return a list of names of available fonts matching PATTERN on frame F.
13153 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13154 to be listed.
13156 SIZE < 0 means include scalable fonts.
13158 Frame F null means we have not yet created any frame on X, and
13159 consult the first display in x_display_list. MAXNAMES sets a limit
13160 on how many fonts to match. */
13162 Lisp_Object
13163 x_list_fonts (f, pattern, size, maxnames)
13164 struct frame *f;
13165 Lisp_Object pattern;
13166 int size;
13167 int maxnames;
13169 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13170 Lisp_Object tem, second_best;
13171 struct x_display_info *dpyinfo
13172 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13173 Display *dpy = dpyinfo->display;
13174 int try_XLoadQueryFont = 0;
13175 int count;
13176 int allow_scalable_fonts_p = 0;
13178 if (size < 0)
13180 allow_scalable_fonts_p = 1;
13181 size = 0;
13184 patterns = Fassoc (pattern, Valternate_fontname_alist);
13185 if (NILP (patterns))
13186 patterns = Fcons (pattern, Qnil);
13188 if (maxnames == 1 && !size)
13189 /* We can return any single font matching PATTERN. */
13190 try_XLoadQueryFont = 1;
13192 for (; CONSP (patterns); patterns = XCDR (patterns))
13194 int num_fonts;
13195 char **names = NULL;
13197 pattern = XCAR (patterns);
13198 /* See if we cached the result for this particular query.
13199 The cache is an alist of the form:
13200 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13201 tem = XCDR (dpyinfo->name_list_element);
13202 key = Fcons (Fcons (pattern, make_number (maxnames)),
13203 allow_scalable_fonts_p ? Qt : Qnil);
13204 list = Fassoc (key, tem);
13205 if (!NILP (list))
13207 list = Fcdr_safe (list);
13208 /* We have a cashed list. Don't have to get the list again. */
13209 goto label_cached;
13212 /* At first, put PATTERN in the cache. */
13214 BLOCK_INPUT;
13215 count = x_catch_errors (dpy);
13217 if (try_XLoadQueryFont)
13219 XFontStruct *font;
13220 unsigned long value;
13222 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13223 if (x_had_errors_p (dpy))
13225 /* This error is perhaps due to insufficient memory on X
13226 server. Let's just ignore it. */
13227 font = NULL;
13228 x_clear_errors (dpy);
13231 if (font
13232 && XGetFontProperty (font, XA_FONT, &value))
13234 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13235 int len = strlen (name);
13236 char *tmp;
13238 /* If DXPC (a Differential X Protocol Compressor)
13239 Ver.3.7 is running, XGetAtomName will return null
13240 string. We must avoid such a name. */
13241 if (len == 0)
13242 try_XLoadQueryFont = 0;
13243 else
13245 num_fonts = 1;
13246 names = (char **) alloca (sizeof (char *));
13247 /* Some systems only allow alloca assigned to a
13248 simple var. */
13249 tmp = (char *) alloca (len + 1); names[0] = tmp;
13250 bcopy (name, names[0], len + 1);
13251 XFree (name);
13254 else
13255 try_XLoadQueryFont = 0;
13257 if (font)
13258 XFreeFont (dpy, font);
13261 if (!try_XLoadQueryFont)
13263 /* We try at least 10 fonts because XListFonts will return
13264 auto-scaled fonts at the head. */
13265 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13266 &num_fonts);
13267 if (x_had_errors_p (dpy))
13269 /* This error is perhaps due to insufficient memory on X
13270 server. Let's just ignore it. */
13271 names = NULL;
13272 x_clear_errors (dpy);
13276 x_uncatch_errors (dpy, count);
13277 UNBLOCK_INPUT;
13279 if (names)
13281 int i;
13283 /* Make a list of all the fonts we got back.
13284 Store that in the font cache for the display. */
13285 for (i = 0; i < num_fonts; i++)
13287 int width = 0;
13288 char *p = names[i];
13289 int average_width = -1, dashes = 0;
13291 /* Count the number of dashes in NAMES[I]. If there are
13292 14 dashes, and the field value following 12th dash
13293 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13294 is usually too ugly to be used for editing. Let's
13295 ignore it. */
13296 while (*p)
13297 if (*p++ == '-')
13299 dashes++;
13300 if (dashes == 7) /* PIXEL_SIZE field */
13301 width = atoi (p);
13302 else if (dashes == 12) /* AVERAGE_WIDTH field */
13303 average_width = atoi (p);
13306 if (allow_scalable_fonts_p
13307 || dashes < 14 || average_width != 0)
13309 tem = build_string (names[i]);
13310 if (NILP (Fassoc (tem, list)))
13312 if (STRINGP (Vx_pixel_size_width_font_regexp)
13313 && ((fast_c_string_match_ignore_case
13314 (Vx_pixel_size_width_font_regexp, names[i]))
13315 >= 0))
13316 /* We can set the value of PIXEL_SIZE to the
13317 width of this font. */
13318 list = Fcons (Fcons (tem, make_number (width)), list);
13319 else
13320 /* For the moment, width is not known. */
13321 list = Fcons (Fcons (tem, Qnil), list);
13325 if (!try_XLoadQueryFont)
13326 XFreeFontNames (names);
13329 /* Now store the result in the cache. */
13330 XCDR (dpyinfo->name_list_element)
13331 = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
13333 label_cached:
13334 if (NILP (list)) continue; /* Try the remaining alternatives. */
13336 newlist = second_best = Qnil;
13337 /* Make a list of the fonts that have the right width. */
13338 for (; CONSP (list); list = XCDR (list))
13340 int found_size;
13342 tem = XCAR (list);
13344 if (!CONSP (tem) || NILP (XCAR (tem)))
13345 continue;
13346 if (!size)
13348 newlist = Fcons (XCAR (tem), newlist);
13349 continue;
13352 if (!INTEGERP (XCDR (tem)))
13354 /* Since we have not yet known the size of this font, we
13355 must try slow function call XLoadQueryFont. */
13356 XFontStruct *thisinfo;
13358 BLOCK_INPUT;
13359 count = x_catch_errors (dpy);
13360 thisinfo = XLoadQueryFont (dpy,
13361 XSTRING (XCAR (tem))->data);
13362 if (x_had_errors_p (dpy))
13364 /* This error is perhaps due to insufficient memory on X
13365 server. Let's just ignore it. */
13366 thisinfo = NULL;
13367 x_clear_errors (dpy);
13369 x_uncatch_errors (dpy, count);
13370 UNBLOCK_INPUT;
13372 if (thisinfo)
13374 XCDR (tem)
13375 = (thisinfo->min_bounds.width == 0
13376 ? make_number (0)
13377 : make_number (thisinfo->max_bounds.width));
13378 XFreeFont (dpy, thisinfo);
13380 else
13381 /* For unknown reason, the previous call of XListFont had
13382 returned a font which can't be opened. Record the size
13383 as 0 not to try to open it again. */
13384 XCDR (tem) = make_number (0);
13387 found_size = XINT (XCDR (tem));
13388 if (found_size == size)
13389 newlist = Fcons (XCAR (tem), newlist);
13390 else if (found_size > 0)
13392 if (NILP (second_best))
13393 second_best = tem;
13394 else if (found_size < size)
13396 if (XINT (XCDR (second_best)) > size
13397 || XINT (XCDR (second_best)) < found_size)
13398 second_best = tem;
13400 else
13402 if (XINT (XCDR (second_best)) > size
13403 && XINT (XCDR (second_best)) > found_size)
13404 second_best = tem;
13408 if (!NILP (newlist))
13409 break;
13410 else if (!NILP (second_best))
13412 newlist = Fcons (XCAR (second_best), Qnil);
13413 break;
13417 return newlist;
13421 #if GLYPH_DEBUG
13423 /* Check that FONT is valid on frame F. It is if it can be found in F's
13424 font table. */
13426 static void
13427 x_check_font (f, font)
13428 struct frame *f;
13429 XFontStruct *font;
13431 int i;
13432 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13434 xassert (font != NULL);
13436 for (i = 0; i < dpyinfo->n_fonts; i++)
13437 if (dpyinfo->font_table[i].name
13438 && font == dpyinfo->font_table[i].font)
13439 break;
13441 xassert (i < dpyinfo->n_fonts);
13444 #endif /* GLYPH_DEBUG != 0 */
13446 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13447 Note: There are (broken) X fonts out there with invalid XFontStruct
13448 min_bounds contents. For example, handa@etl.go.jp reports that
13449 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13450 have font->min_bounds.width == 0. */
13452 static INLINE void
13453 x_font_min_bounds (font, w, h)
13454 XFontStruct *font;
13455 int *w, *h;
13457 *h = FONT_HEIGHT (font);
13458 *w = font->min_bounds.width;
13460 /* Try to handle the case where FONT->min_bounds has invalid
13461 contents. Since the only font known to have invalid min_bounds
13462 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13463 if (*w <= 0)
13464 *w = font->max_bounds.width;
13468 /* Compute the smallest character width and smallest font height over
13469 all fonts available on frame F. Set the members smallest_char_width
13470 and smallest_font_height in F's x_display_info structure to
13471 the values computed. Value is non-zero if smallest_font_height or
13472 smallest_char_width become smaller than they were before. */
13474 static int
13475 x_compute_min_glyph_bounds (f)
13476 struct frame *f;
13478 int i;
13479 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13480 XFontStruct *font;
13481 int old_width = dpyinfo->smallest_char_width;
13482 int old_height = dpyinfo->smallest_font_height;
13484 dpyinfo->smallest_font_height = 100000;
13485 dpyinfo->smallest_char_width = 100000;
13487 for (i = 0; i < dpyinfo->n_fonts; ++i)
13488 if (dpyinfo->font_table[i].name)
13490 struct font_info *fontp = dpyinfo->font_table + i;
13491 int w, h;
13493 font = (XFontStruct *) fontp->font;
13494 xassert (font != (XFontStruct *) ~0);
13495 x_font_min_bounds (font, &w, &h);
13497 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13498 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13501 xassert (dpyinfo->smallest_char_width > 0
13502 && dpyinfo->smallest_font_height > 0);
13504 return (dpyinfo->n_fonts == 1
13505 || dpyinfo->smallest_char_width < old_width
13506 || dpyinfo->smallest_font_height < old_height);
13510 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13511 pointer to the structure font_info while allocating it dynamically.
13512 If SIZE is 0, load any size of font.
13513 If loading is failed, return NULL. */
13515 struct font_info *
13516 x_load_font (f, fontname, size)
13517 struct frame *f;
13518 register char *fontname;
13519 int size;
13521 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13522 Lisp_Object font_names;
13523 int count;
13525 /* Get a list of all the fonts that match this name. Once we
13526 have a list of matching fonts, we compare them against the fonts
13527 we already have by comparing names. */
13528 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13530 if (!NILP (font_names))
13532 Lisp_Object tail;
13533 int i;
13535 for (i = 0; i < dpyinfo->n_fonts; i++)
13536 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13537 if (dpyinfo->font_table[i].name
13538 && (!strcmp (dpyinfo->font_table[i].name,
13539 XSTRING (XCAR (tail))->data)
13540 || !strcmp (dpyinfo->font_table[i].full_name,
13541 XSTRING (XCAR (tail))->data)))
13542 return (dpyinfo->font_table + i);
13545 /* Load the font and add it to the table. */
13547 char *full_name;
13548 XFontStruct *font;
13549 struct font_info *fontp;
13550 unsigned long value;
13551 int i;
13553 /* If we have found fonts by x_list_font, load one of them. If
13554 not, we still try to load a font by the name given as FONTNAME
13555 because XListFonts (called in x_list_font) of some X server has
13556 a bug of not finding a font even if the font surely exists and
13557 is loadable by XLoadQueryFont. */
13558 if (size > 0 && !NILP (font_names))
13559 fontname = (char *) XSTRING (XCAR (font_names))->data;
13561 BLOCK_INPUT;
13562 count = x_catch_errors (FRAME_X_DISPLAY (f));
13563 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13564 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13566 /* This error is perhaps due to insufficient memory on X
13567 server. Let's just ignore it. */
13568 font = NULL;
13569 x_clear_errors (FRAME_X_DISPLAY (f));
13571 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13572 UNBLOCK_INPUT;
13573 if (!font)
13574 return NULL;
13576 /* Find a free slot in the font table. */
13577 for (i = 0; i < dpyinfo->n_fonts; ++i)
13578 if (dpyinfo->font_table[i].name == NULL)
13579 break;
13581 /* If no free slot found, maybe enlarge the font table. */
13582 if (i == dpyinfo->n_fonts
13583 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13585 int sz;
13586 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13587 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13588 dpyinfo->font_table
13589 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13592 fontp = dpyinfo->font_table + i;
13593 if (i == dpyinfo->n_fonts)
13594 ++dpyinfo->n_fonts;
13596 /* Now fill in the slots of *FONTP. */
13597 BLOCK_INPUT;
13598 fontp->font = font;
13599 fontp->font_idx = i;
13600 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13601 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13603 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13604 full_name = 0;
13605 if (XGetFontProperty (font, XA_FONT, &value))
13607 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13608 char *p = name;
13609 int dashes = 0;
13611 /* Count the number of dashes in the "full name".
13612 If it is too few, this isn't really the font's full name,
13613 so don't use it.
13614 In X11R4, the fonts did not come with their canonical names
13615 stored in them. */
13616 while (*p)
13618 if (*p == '-')
13619 dashes++;
13620 p++;
13623 if (dashes >= 13)
13625 full_name = (char *) xmalloc (p - name + 1);
13626 bcopy (name, full_name, p - name + 1);
13629 XFree (name);
13632 if (full_name != 0)
13633 fontp->full_name = full_name;
13634 else
13635 fontp->full_name = fontp->name;
13637 fontp->size = font->max_bounds.width;
13638 fontp->height = FONT_HEIGHT (font);
13640 if (NILP (font_names))
13642 /* We come here because of a bug of XListFonts mentioned at
13643 the head of this block. Let's store this information in
13644 the cache for x_list_fonts. */
13645 Lisp_Object lispy_name = build_string (fontname);
13646 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13647 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13648 Qnil);
13650 XCDR (dpyinfo->name_list_element)
13651 = Fcons (Fcons (key,
13652 Fcons (Fcons (lispy_full_name,
13653 make_number (fontp->size)),
13654 Qnil)),
13655 XCDR (dpyinfo->name_list_element));
13656 if (full_name)
13658 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13659 Qnil);
13660 XCDR (dpyinfo->name_list_element)
13661 = Fcons (Fcons (key,
13662 Fcons (Fcons (lispy_full_name,
13663 make_number (fontp->size)),
13664 Qnil)),
13665 XCDR (dpyinfo->name_list_element));
13669 /* The slot `encoding' specifies how to map a character
13670 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13671 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13672 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13673 2:0xA020..0xFF7F). For the moment, we don't know which charset
13674 uses this font. So, we set information in fontp->encoding[1]
13675 which is never used by any charset. If mapping can't be
13676 decided, set FONT_ENCODING_NOT_DECIDED. */
13677 fontp->encoding[1]
13678 = (font->max_byte1 == 0
13679 /* 1-byte font */
13680 ? (font->min_char_or_byte2 < 0x80
13681 ? (font->max_char_or_byte2 < 0x80
13682 ? 0 /* 0x20..0x7F */
13683 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13684 : 1) /* 0xA0..0xFF */
13685 /* 2-byte font */
13686 : (font->min_byte1 < 0x80
13687 ? (font->max_byte1 < 0x80
13688 ? (font->min_char_or_byte2 < 0x80
13689 ? (font->max_char_or_byte2 < 0x80
13690 ? 0 /* 0x2020..0x7F7F */
13691 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13692 : 3) /* 0x20A0..0x7FFF */
13693 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13694 : (font->min_char_or_byte2 < 0x80
13695 ? (font->max_char_or_byte2 < 0x80
13696 ? 2 /* 0xA020..0xFF7F */
13697 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13698 : 1))); /* 0xA0A0..0xFFFF */
13700 fontp->baseline_offset
13701 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13702 ? (long) value : 0);
13703 fontp->relative_compose
13704 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13705 ? (long) value : 0);
13706 fontp->default_ascent
13707 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13708 ? (long) value : 0);
13710 /* Set global flag fonts_changed_p to non-zero if the font loaded
13711 has a character with a smaller width than any other character
13712 before, or if the font loaded has a smalle>r height than any
13713 other font loaded before. If this happens, it will make a
13714 glyph matrix reallocation necessary. */
13715 fonts_changed_p = x_compute_min_glyph_bounds (f);
13716 UNBLOCK_INPUT;
13717 return fontp;
13722 /* Return a pointer to struct font_info of a font named FONTNAME for
13723 frame F. If no such font is loaded, return NULL. */
13725 struct font_info *
13726 x_query_font (f, fontname)
13727 struct frame *f;
13728 register char *fontname;
13730 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13731 int i;
13733 for (i = 0; i < dpyinfo->n_fonts; i++)
13734 if (dpyinfo->font_table[i].name
13735 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13736 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13737 return (dpyinfo->font_table + i);
13738 return NULL;
13742 /* Find a CCL program for a font specified by FONTP, and set the member
13743 `encoder' of the structure. */
13745 void
13746 x_find_ccl_program (fontp)
13747 struct font_info *fontp;
13749 Lisp_Object list, elt;
13751 elt = Qnil;
13752 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13754 elt = XCAR (list);
13755 if (CONSP (elt)
13756 && STRINGP (XCAR (elt))
13757 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13758 >= 0)
13759 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13760 >= 0)))
13761 break;
13764 if (! NILP (list))
13766 struct ccl_program *ccl
13767 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13769 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13770 xfree (ccl);
13771 else
13772 fontp->font_encoder = ccl;
13778 /***********************************************************************
13779 Initialization
13780 ***********************************************************************/
13782 #ifdef USE_X_TOOLKIT
13783 static XrmOptionDescRec emacs_options[] = {
13784 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13785 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13787 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13788 XrmoptionSepArg, NULL},
13789 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13791 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13792 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13793 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13794 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13795 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13796 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13797 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13799 #endif /* USE_X_TOOLKIT */
13801 static int x_initialized;
13803 #ifdef MULTI_KBOARD
13804 /* Test whether two display-name strings agree up to the dot that separates
13805 the screen number from the server number. */
13806 static int
13807 same_x_server (name1, name2)
13808 char *name1, *name2;
13810 int seen_colon = 0;
13811 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13812 int system_name_length = strlen (system_name);
13813 int length_until_period = 0;
13815 while (system_name[length_until_period] != 0
13816 && system_name[length_until_period] != '.')
13817 length_until_period++;
13819 /* Treat `unix' like an empty host name. */
13820 if (! strncmp (name1, "unix:", 5))
13821 name1 += 4;
13822 if (! strncmp (name2, "unix:", 5))
13823 name2 += 4;
13824 /* Treat this host's name like an empty host name. */
13825 if (! strncmp (name1, system_name, system_name_length)
13826 && name1[system_name_length] == ':')
13827 name1 += system_name_length;
13828 if (! strncmp (name2, system_name, system_name_length)
13829 && name2[system_name_length] == ':')
13830 name2 += system_name_length;
13831 /* Treat this host's domainless name like an empty host name. */
13832 if (! strncmp (name1, system_name, length_until_period)
13833 && name1[length_until_period] == ':')
13834 name1 += length_until_period;
13835 if (! strncmp (name2, system_name, length_until_period)
13836 && name2[length_until_period] == ':')
13837 name2 += length_until_period;
13839 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13841 if (*name1 == ':')
13842 seen_colon++;
13843 if (seen_colon && *name1 == '.')
13844 return 1;
13846 return (seen_colon
13847 && (*name1 == '.' || *name1 == '\0')
13848 && (*name2 == '.' || *name2 == '\0'));
13850 #endif
13852 struct x_display_info *
13853 x_term_init (display_name, xrm_option, resource_name)
13854 Lisp_Object display_name;
13855 char *xrm_option;
13856 char *resource_name;
13858 int connection;
13859 Display *dpy;
13860 struct x_display_info *dpyinfo;
13861 XrmDatabase xrdb;
13863 BLOCK_INPUT;
13865 if (!x_initialized)
13867 x_initialize ();
13868 x_initialized = 1;
13871 #ifdef USE_X_TOOLKIT
13872 /* weiner@footloose.sps.mot.com reports that this causes
13873 errors with X11R5:
13874 X protocol error: BadAtom (invalid Atom parameter)
13875 on protocol request 18skiloaf.
13876 So let's not use it until R6. */
13877 #ifdef HAVE_X11XTR6
13878 XtSetLanguageProc (NULL, NULL, NULL);
13879 #endif
13882 int argc = 0;
13883 char *argv[3];
13885 argv[0] = "";
13886 argc = 1;
13887 if (xrm_option)
13889 argv[argc++] = "-xrm";
13890 argv[argc++] = xrm_option;
13892 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13893 resource_name, EMACS_CLASS,
13894 emacs_options, XtNumber (emacs_options),
13895 &argc, argv);
13897 #ifdef HAVE_X11XTR6
13898 /* I think this is to compensate for XtSetLanguageProc. */
13899 fixup_locale ();
13900 #endif
13903 #else /* not USE_X_TOOLKIT */
13904 #ifdef HAVE_X11R5
13905 XSetLocaleModifiers ("");
13906 #endif
13907 dpy = XOpenDisplay (XSTRING (display_name)->data);
13908 #endif /* not USE_X_TOOLKIT */
13910 /* Detect failure. */
13911 if (dpy == 0)
13913 UNBLOCK_INPUT;
13914 return 0;
13917 /* We have definitely succeeded. Record the new connection. */
13919 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13920 bzero (dpyinfo, sizeof *dpyinfo);
13922 #ifdef MULTI_KBOARD
13924 struct x_display_info *share;
13925 Lisp_Object tail;
13927 for (share = x_display_list, tail = x_display_name_list; share;
13928 share = share->next, tail = XCDR (tail))
13929 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13930 XSTRING (display_name)->data))
13931 break;
13932 if (share)
13933 dpyinfo->kboard = share->kboard;
13934 else
13936 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13937 init_kboard (dpyinfo->kboard);
13938 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13940 char *vendor = ServerVendor (dpy);
13941 UNBLOCK_INPUT;
13942 dpyinfo->kboard->Vsystem_key_alist
13943 = call1 (Qvendor_specific_keysyms,
13944 build_string (vendor ? vendor : ""));
13945 BLOCK_INPUT;
13948 dpyinfo->kboard->next_kboard = all_kboards;
13949 all_kboards = dpyinfo->kboard;
13950 /* Don't let the initial kboard remain current longer than necessary.
13951 That would cause problems if a file loaded on startup tries to
13952 prompt in the mini-buffer. */
13953 if (current_kboard == initial_kboard)
13954 current_kboard = dpyinfo->kboard;
13956 dpyinfo->kboard->reference_count++;
13958 #endif
13960 /* Put this display on the chain. */
13961 dpyinfo->next = x_display_list;
13962 x_display_list = dpyinfo;
13964 /* Put it on x_display_name_list as well, to keep them parallel. */
13965 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13966 x_display_name_list);
13967 dpyinfo->name_list_element = XCAR (x_display_name_list);
13969 dpyinfo->display = dpy;
13971 #if 0
13972 XSetAfterFunction (x_current_display, x_trace_wire);
13973 #endif /* ! 0 */
13975 dpyinfo->x_id_name
13976 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13977 + STRING_BYTES (XSTRING (Vsystem_name))
13978 + 2);
13979 sprintf (dpyinfo->x_id_name, "%s@%s",
13980 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13982 /* Figure out which modifier bits mean what. */
13983 x_find_modifier_meanings (dpyinfo);
13985 /* Get the scroll bar cursor. */
13986 dpyinfo->vertical_scroll_bar_cursor
13987 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13989 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13990 resource_name, EMACS_CLASS);
13991 #ifdef HAVE_XRMSETDATABASE
13992 XrmSetDatabase (dpyinfo->display, xrdb);
13993 #else
13994 dpyinfo->display->db = xrdb;
13995 #endif
13996 /* Put the rdb where we can find it in a way that works on
13997 all versions. */
13998 dpyinfo->xrdb = xrdb;
14000 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14001 DefaultScreen (dpyinfo->display));
14002 select_visual (dpyinfo);
14003 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14004 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14005 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14006 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14007 dpyinfo->grabbed = 0;
14008 dpyinfo->reference_count = 0;
14009 dpyinfo->icon_bitmap_id = -1;
14010 dpyinfo->font_table = NULL;
14011 dpyinfo->n_fonts = 0;
14012 dpyinfo->font_table_size = 0;
14013 dpyinfo->bitmaps = 0;
14014 dpyinfo->bitmaps_size = 0;
14015 dpyinfo->bitmaps_last = 0;
14016 dpyinfo->scratch_cursor_gc = 0;
14017 dpyinfo->mouse_face_mouse_frame = 0;
14018 dpyinfo->mouse_face_deferred_gc = 0;
14019 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14020 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14021 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14022 dpyinfo->mouse_face_window = Qnil;
14023 dpyinfo->mouse_face_overlay = Qnil;
14024 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14025 dpyinfo->mouse_face_defer = 0;
14026 dpyinfo->x_focus_frame = 0;
14027 dpyinfo->x_focus_event_frame = 0;
14028 dpyinfo->x_highlight_frame = 0;
14029 dpyinfo->image_cache = make_image_cache ();
14031 /* See if a private colormap is requested. */
14032 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14034 if (dpyinfo->visual->class == PseudoColor)
14036 Lisp_Object value;
14037 value = display_x_get_resource (dpyinfo,
14038 build_string ("privateColormap"),
14039 build_string ("PrivateColormap"),
14040 Qnil, Qnil);
14041 if (STRINGP (value)
14042 && (!strcmp (XSTRING (value)->data, "true")
14043 || !strcmp (XSTRING (value)->data, "on")))
14044 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14047 else
14048 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14049 dpyinfo->visual, AllocNone);
14052 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14053 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14054 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14055 dpyinfo->resy = pixels * 25.4 / mm;
14056 pixels = DisplayWidth (dpyinfo->display, screen_number);
14057 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14058 dpyinfo->resx = pixels * 25.4 / mm;
14061 dpyinfo->Xatom_wm_protocols
14062 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14063 dpyinfo->Xatom_wm_take_focus
14064 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14065 dpyinfo->Xatom_wm_save_yourself
14066 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14067 dpyinfo->Xatom_wm_delete_window
14068 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14069 dpyinfo->Xatom_wm_change_state
14070 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14071 dpyinfo->Xatom_wm_configure_denied
14072 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14073 dpyinfo->Xatom_wm_window_moved
14074 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14075 dpyinfo->Xatom_editres
14076 = XInternAtom (dpyinfo->display, "Editres", False);
14077 dpyinfo->Xatom_CLIPBOARD
14078 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14079 dpyinfo->Xatom_TIMESTAMP
14080 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14081 dpyinfo->Xatom_TEXT
14082 = XInternAtom (dpyinfo->display, "TEXT", False);
14083 dpyinfo->Xatom_COMPOUND_TEXT
14084 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14085 dpyinfo->Xatom_DELETE
14086 = XInternAtom (dpyinfo->display, "DELETE", False);
14087 dpyinfo->Xatom_MULTIPLE
14088 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14089 dpyinfo->Xatom_INCR
14090 = XInternAtom (dpyinfo->display, "INCR", False);
14091 dpyinfo->Xatom_EMACS_TMP
14092 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14093 dpyinfo->Xatom_TARGETS
14094 = XInternAtom (dpyinfo->display, "TARGETS", False);
14095 dpyinfo->Xatom_NULL
14096 = XInternAtom (dpyinfo->display, "NULL", False);
14097 dpyinfo->Xatom_ATOM_PAIR
14098 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14099 /* For properties of font. */
14100 dpyinfo->Xatom_PIXEL_SIZE
14101 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14102 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14103 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14104 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14105 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14106 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14107 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14109 /* Ghostscript support. */
14110 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14111 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14113 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14114 False);
14116 dpyinfo->cut_buffers_initialized = 0;
14118 connection = ConnectionNumber (dpyinfo->display);
14119 dpyinfo->connection = connection;
14122 char null_bits[1];
14124 null_bits[0] = 0x00;
14126 dpyinfo->null_pixel
14127 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14128 null_bits, 1, 1, (long) 0, (long) 0,
14133 extern int gray_bitmap_width, gray_bitmap_height;
14134 extern char *gray_bitmap_bits;
14135 dpyinfo->gray
14136 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14137 gray_bitmap_bits,
14138 gray_bitmap_width, gray_bitmap_height,
14139 (unsigned long) 1, (unsigned long) 0, 1);
14142 #ifdef HAVE_X_I18N
14143 xim_initialize (dpyinfo, resource_name);
14144 #endif
14146 #ifdef subprocesses
14147 /* This is only needed for distinguishing keyboard and process input. */
14148 if (connection != 0)
14149 add_keyboard_wait_descriptor (connection);
14150 #endif
14152 #ifndef F_SETOWN_BUG
14153 #ifdef F_SETOWN
14154 #ifdef F_SETOWN_SOCK_NEG
14155 /* stdin is a socket here */
14156 fcntl (connection, F_SETOWN, -getpid ());
14157 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14158 fcntl (connection, F_SETOWN, getpid ());
14159 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14160 #endif /* ! defined (F_SETOWN) */
14161 #endif /* F_SETOWN_BUG */
14163 #ifdef SIGIO
14164 if (interrupt_input)
14165 init_sigio (connection);
14166 #endif /* ! defined (SIGIO) */
14168 #ifdef USE_LUCID
14169 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14170 /* Make sure that we have a valid font for dialog boxes
14171 so that Xt does not crash. */
14173 Display *dpy = dpyinfo->display;
14174 XrmValue d, fr, to;
14175 Font font;
14176 int count;
14178 d.addr = (XPointer)&dpy;
14179 d.size = sizeof (Display *);
14180 fr.addr = XtDefaultFont;
14181 fr.size = sizeof (XtDefaultFont);
14182 to.size = sizeof (Font *);
14183 to.addr = (XPointer)&font;
14184 count = x_catch_errors (dpy);
14185 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14186 abort ();
14187 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14188 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14189 x_uncatch_errors (dpy, count);
14191 #endif
14192 #endif
14194 /* See if we should run in synchronous mode. This is useful
14195 for debugging X code. */
14197 Lisp_Object value;
14198 value = display_x_get_resource (dpyinfo,
14199 build_string ("synchronous"),
14200 build_string ("Synchronous"),
14201 Qnil, Qnil);
14202 if (STRINGP (value)
14203 && (!strcmp (XSTRING (value)->data, "true")
14204 || !strcmp (XSTRING (value)->data, "on")))
14205 XSynchronize (dpyinfo->display, True);
14208 UNBLOCK_INPUT;
14210 return dpyinfo;
14213 /* Get rid of display DPYINFO, assuming all frames are already gone,
14214 and without sending any more commands to the X server. */
14216 void
14217 x_delete_display (dpyinfo)
14218 struct x_display_info *dpyinfo;
14220 delete_keyboard_wait_descriptor (dpyinfo->connection);
14222 /* Discard this display from x_display_name_list and x_display_list.
14223 We can't use Fdelq because that can quit. */
14224 if (! NILP (x_display_name_list)
14225 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14226 x_display_name_list = XCDR (x_display_name_list);
14227 else
14229 Lisp_Object tail;
14231 tail = x_display_name_list;
14232 while (CONSP (tail) && CONSP (XCDR (tail)))
14234 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14236 XCDR (tail) = XCDR (XCDR (tail));
14237 break;
14239 tail = XCDR (tail);
14243 if (next_noop_dpyinfo == dpyinfo)
14244 next_noop_dpyinfo = dpyinfo->next;
14246 if (x_display_list == dpyinfo)
14247 x_display_list = dpyinfo->next;
14248 else
14250 struct x_display_info *tail;
14252 for (tail = x_display_list; tail; tail = tail->next)
14253 if (tail->next == dpyinfo)
14254 tail->next = tail->next->next;
14257 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14258 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14259 XrmDestroyDatabase (dpyinfo->xrdb);
14260 #endif
14261 #endif
14262 #ifdef MULTI_KBOARD
14263 if (--dpyinfo->kboard->reference_count == 0)
14264 delete_kboard (dpyinfo->kboard);
14265 #endif
14266 #ifdef HAVE_X_I18N
14267 if (dpyinfo->xim)
14268 xim_close_dpy (dpyinfo);
14269 #endif
14271 xfree (dpyinfo->font_table);
14272 xfree (dpyinfo->x_id_name);
14273 xfree (dpyinfo->color_cells);
14274 xfree (dpyinfo);
14278 /* Set up use of X before we make the first connection. */
14280 static struct redisplay_interface x_redisplay_interface =
14282 x_produce_glyphs,
14283 x_write_glyphs,
14284 x_insert_glyphs,
14285 x_clear_end_of_line,
14286 x_scroll_run,
14287 x_after_update_window_line,
14288 x_update_window_begin,
14289 x_update_window_end,
14290 XTcursor_to,
14291 x_flush,
14292 x_clear_mouse_face,
14293 x_get_glyph_overhangs,
14294 x_fix_overlapping_area
14297 void
14298 x_initialize ()
14300 rif = &x_redisplay_interface;
14302 clear_frame_hook = x_clear_frame;
14303 ins_del_lines_hook = x_ins_del_lines;
14304 change_line_highlight_hook = x_change_line_highlight;
14305 delete_glyphs_hook = x_delete_glyphs;
14306 ring_bell_hook = XTring_bell;
14307 reset_terminal_modes_hook = XTreset_terminal_modes;
14308 set_terminal_modes_hook = XTset_terminal_modes;
14309 update_begin_hook = x_update_begin;
14310 update_end_hook = x_update_end;
14311 set_terminal_window_hook = XTset_terminal_window;
14312 read_socket_hook = XTread_socket;
14313 frame_up_to_date_hook = XTframe_up_to_date;
14314 reassert_line_highlight_hook = XTreassert_line_highlight;
14315 mouse_position_hook = XTmouse_position;
14316 frame_rehighlight_hook = XTframe_rehighlight;
14317 frame_raise_lower_hook = XTframe_raise_lower;
14318 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14319 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14320 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14321 judge_scroll_bars_hook = XTjudge_scroll_bars;
14322 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14324 scroll_region_ok = 1; /* we'll scroll partial frames */
14325 char_ins_del_ok = 1;
14326 line_ins_del_ok = 1; /* we'll just blt 'em */
14327 fast_clear_end_of_line = 1; /* X does this well */
14328 memory_below_frame = 0; /* we don't remember what scrolls
14329 off the bottom */
14330 baud_rate = 19200;
14332 x_noop_count = 0;
14333 last_tool_bar_item = -1;
14334 any_help_event_p = 0;
14336 /* Try to use interrupt input; if we can't, then start polling. */
14337 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14339 #ifdef USE_X_TOOLKIT
14340 XtToolkitInitialize ();
14342 Xt_app_con = XtCreateApplicationContext ();
14344 /* Register a converter from strings to pixels, which uses
14345 Emacs' color allocation infrastructure. */
14346 XtAppSetTypeConverter (Xt_app_con,
14347 XtRString, XtRPixel, cvt_string_to_pixel,
14348 cvt_string_to_pixel_args,
14349 XtNumber (cvt_string_to_pixel_args),
14350 XtCacheByDisplay, cvt_pixel_dtor);
14352 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14354 /* Install an asynchronous timer that processes Xt timeout events
14355 every 0.1s. This is necessary because some widget sets use
14356 timeouts internally, for example the LessTif menu bar, or the
14357 Xaw3d scroll bar. When Xt timouts aren't processed, these
14358 widgets don't behave normally. */
14360 EMACS_TIME interval;
14361 EMACS_SET_SECS_USECS (interval, 0, 100000);
14362 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14364 #endif
14366 #ifdef USE_TOOLKIT_SCROLL_BARS
14367 xaw3d_arrow_scroll = False;
14368 xaw3d_pick_top = True;
14369 #endif
14371 /* Note that there is no real way portable across R3/R4 to get the
14372 original error handler. */
14373 XSetErrorHandler (x_error_handler);
14374 XSetIOErrorHandler (x_io_error_quitter);
14376 /* Disable Window Change signals; they are handled by X events. */
14377 #ifdef SIGWINCH
14378 signal (SIGWINCH, SIG_DFL);
14379 #endif /* ! defined (SIGWINCH) */
14381 signal (SIGPIPE, x_connection_signal);
14385 void
14386 syms_of_xterm ()
14388 staticpro (&x_error_message_string);
14389 x_error_message_string = Qnil;
14391 staticpro (&x_display_name_list);
14392 x_display_name_list = Qnil;
14394 staticpro (&last_mouse_scroll_bar);
14395 last_mouse_scroll_bar = Qnil;
14397 staticpro (&Qvendor_specific_keysyms);
14398 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14400 staticpro (&last_mouse_press_frame);
14401 last_mouse_press_frame = Qnil;
14403 help_echo = Qnil;
14404 staticpro (&help_echo);
14405 help_echo_object = Qnil;
14406 staticpro (&help_echo_object);
14407 help_echo_window = Qnil;
14408 staticpro (&help_echo_window);
14409 previous_help_echo = Qnil;
14410 staticpro (&previous_help_echo);
14411 help_echo_pos = -1;
14413 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14414 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
14415 For example, if a block cursor is over a tab, it will be drawn as\n\
14416 wide as that tab on the display.");
14417 x_stretch_cursor_p = 0;
14419 DEFVAR_BOOL ("x-use-underline-position-properties",
14420 &x_use_underline_position_properties,
14421 "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
14422 Nil means ignore them. If you encounter fonts with bogus\n\
14423 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
14424 to 4.1, set this to nil.");
14425 x_use_underline_position_properties = 1;
14427 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14428 "What X toolkit scroll bars Emacs uses.\n\
14429 A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
14430 Otherwise, value is a symbol describing the X toolkit.");
14431 #ifdef USE_TOOLKIT_SCROLL_BARS
14432 #ifdef USE_MOTIF
14433 Vx_toolkit_scroll_bars = intern ("motif");
14434 #elif defined HAVE_XAW3D
14435 Vx_toolkit_scroll_bars = intern ("xaw3d");
14436 #else
14437 Vx_toolkit_scroll_bars = intern ("xaw");
14438 #endif
14439 #else
14440 Vx_toolkit_scroll_bars = Qnil;
14441 #endif
14443 staticpro (&last_mouse_motion_frame);
14444 last_mouse_motion_frame = Qnil;
14447 #endif /* not HAVE_X_WINDOWS */