*** empty log message ***
[emacs.git] / src / xterm.c
blob9201cf1cd13d407acf24de8abbc9d9e405a69451
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 int 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 if (!s->background_filled_p)
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 if (expose_window (w, r) == 0)
5868 break;
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 int
5995 expose_window (w, fr)
5996 struct window *w;
5997 XRectangle *fr;
5999 struct frame *f = XFRAME (w->frame);
6000 XRectangle wr, r;
6002 /* If window is not yet fully initialized, do nothing. This can
6003 happen when toolkit scroll bars are used and a window is split.
6004 Reconfiguring the scroll bar will generate an expose for a newly
6005 created window. */
6006 if (w->current_matrix == NULL)
6007 return 1;
6009 /* When we're currently updating the window, display and current
6010 matrix usually don't agree. Arrange for a thorough display
6011 later. */
6012 if (w == updated_window)
6014 SET_FRAME_GARBAGED (f);
6015 return 0;
6018 /* Frame-relative pixel rectangle of W. */
6019 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6020 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6021 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6022 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6024 if (x_intersect_rectangles (fr, &wr, &r))
6026 int yb = window_text_bottom_y (w);
6027 struct glyph_row *row;
6028 int cursor_cleared_p;
6030 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6031 r.x, r.y, r.width, r.height));
6033 /* Convert to window coordinates. */
6034 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6035 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6037 /* Turn off the cursor. */
6038 if (!w->pseudo_window_p
6039 && x_phys_cursor_in_rect_p (w, &r))
6041 x_clear_cursor (w);
6042 cursor_cleared_p = 1;
6044 else
6045 cursor_cleared_p = 0;
6047 /* Find the first row intersecting the rectangle R. */
6048 for (row = w->current_matrix->rows;
6049 row->enabled_p;
6050 ++row)
6052 int y0 = row->y;
6053 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6055 if ((y0 >= r.y && y0 < r.y + r.height)
6056 || (y1 > r.y && y1 < r.y + r.height)
6057 || (r.y >= y0 && r.y < y1)
6058 || (r.y + r.height > y0 && r.y + r.height < y1))
6059 expose_line (w, row, &r);
6061 if (y1 >= yb)
6062 break;
6065 /* Display the mode line if there is one. */
6066 if (WINDOW_WANTS_MODELINE_P (w)
6067 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6068 row->enabled_p)
6069 && row->y < r.y + r.height)
6070 expose_line (w, row, &r);
6072 if (!w->pseudo_window_p)
6074 /* Draw border between windows. */
6075 x_draw_vertical_border (w);
6077 /* Turn the cursor on again. */
6078 if (cursor_cleared_p)
6079 x_update_window_cursor (w, 1);
6083 return 1;
6087 /* Determine the intersection of two rectangles R1 and R2. Return
6088 the intersection in *RESULT. Value is non-zero if RESULT is not
6089 empty. */
6091 static int
6092 x_intersect_rectangles (r1, r2, result)
6093 XRectangle *r1, *r2, *result;
6095 XRectangle *left, *right;
6096 XRectangle *upper, *lower;
6097 int intersection_p = 0;
6099 /* Rearrange so that R1 is the left-most rectangle. */
6100 if (r1->x < r2->x)
6101 left = r1, right = r2;
6102 else
6103 left = r2, right = r1;
6105 /* X0 of the intersection is right.x0, if this is inside R1,
6106 otherwise there is no intersection. */
6107 if (right->x <= left->x + left->width)
6109 result->x = right->x;
6111 /* The right end of the intersection is the minimum of the
6112 the right ends of left and right. */
6113 result->width = (min (left->x + left->width, right->x + right->width)
6114 - result->x);
6116 /* Same game for Y. */
6117 if (r1->y < r2->y)
6118 upper = r1, lower = r2;
6119 else
6120 upper = r2, lower = r1;
6122 /* The upper end of the intersection is lower.y0, if this is inside
6123 of upper. Otherwise, there is no intersection. */
6124 if (lower->y <= upper->y + upper->height)
6126 result->y = lower->y;
6128 /* The lower end of the intersection is the minimum of the lower
6129 ends of upper and lower. */
6130 result->height = (min (lower->y + lower->height,
6131 upper->y + upper->height)
6132 - result->y);
6133 intersection_p = 1;
6137 return intersection_p;
6144 static void
6145 frame_highlight (f)
6146 struct frame *f;
6148 /* We used to only do this if Vx_no_window_manager was non-nil, but
6149 the ICCCM (section 4.1.6) says that the window's border pixmap
6150 and border pixel are window attributes which are "private to the
6151 client", so we can always change it to whatever we want. */
6152 BLOCK_INPUT;
6153 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6154 f->output_data.x->border_pixel);
6155 UNBLOCK_INPUT;
6156 x_update_cursor (f, 1);
6159 static void
6160 frame_unhighlight (f)
6161 struct frame *f;
6163 /* We used to only do this if Vx_no_window_manager was non-nil, but
6164 the ICCCM (section 4.1.6) says that the window's border pixmap
6165 and border pixel are window attributes which are "private to the
6166 client", so we can always change it to whatever we want. */
6167 BLOCK_INPUT;
6168 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6169 f->output_data.x->border_tile);
6170 UNBLOCK_INPUT;
6171 x_update_cursor (f, 1);
6174 /* The focus has changed. Update the frames as necessary to reflect
6175 the new situation. Note that we can't change the selected frame
6176 here, because the Lisp code we are interrupting might become confused.
6177 Each event gets marked with the frame in which it occurred, so the
6178 Lisp code can tell when the switch took place by examining the events. */
6180 static void
6181 x_new_focus_frame (dpyinfo, frame)
6182 struct x_display_info *dpyinfo;
6183 struct frame *frame;
6185 struct frame *old_focus = dpyinfo->x_focus_frame;
6187 if (frame != dpyinfo->x_focus_frame)
6189 /* Set this before calling other routines, so that they see
6190 the correct value of x_focus_frame. */
6191 dpyinfo->x_focus_frame = frame;
6193 if (old_focus && old_focus->auto_lower)
6194 x_lower_frame (old_focus);
6196 #if 0
6197 selected_frame = frame;
6198 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6199 selected_frame);
6200 Fselect_window (selected_frame->selected_window);
6201 choose_minibuf_frame ();
6202 #endif /* ! 0 */
6204 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6205 pending_autoraise_frame = dpyinfo->x_focus_frame;
6206 else
6207 pending_autoraise_frame = 0;
6210 x_frame_rehighlight (dpyinfo);
6213 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6215 void
6216 x_mouse_leave (dpyinfo)
6217 struct x_display_info *dpyinfo;
6219 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6222 /* The focus has changed, or we have redirected a frame's focus to
6223 another frame (this happens when a frame uses a surrogate
6224 mini-buffer frame). Shift the highlight as appropriate.
6226 The FRAME argument doesn't necessarily have anything to do with which
6227 frame is being highlighted or un-highlighted; we only use it to find
6228 the appropriate X display info. */
6230 static void
6231 XTframe_rehighlight (frame)
6232 struct frame *frame;
6234 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6237 static void
6238 x_frame_rehighlight (dpyinfo)
6239 struct x_display_info *dpyinfo;
6241 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6243 if (dpyinfo->x_focus_frame)
6245 dpyinfo->x_highlight_frame
6246 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6247 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6248 : dpyinfo->x_focus_frame);
6249 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6251 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6252 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6255 else
6256 dpyinfo->x_highlight_frame = 0;
6258 if (dpyinfo->x_highlight_frame != old_highlight)
6260 if (old_highlight)
6261 frame_unhighlight (old_highlight);
6262 if (dpyinfo->x_highlight_frame)
6263 frame_highlight (dpyinfo->x_highlight_frame);
6269 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6271 /* Initialize mode_switch_bit and modifier_meaning. */
6272 static void
6273 x_find_modifier_meanings (dpyinfo)
6274 struct x_display_info *dpyinfo;
6276 int min_code, max_code;
6277 KeySym *syms;
6278 int syms_per_code;
6279 XModifierKeymap *mods;
6281 dpyinfo->meta_mod_mask = 0;
6282 dpyinfo->shift_lock_mask = 0;
6283 dpyinfo->alt_mod_mask = 0;
6284 dpyinfo->super_mod_mask = 0;
6285 dpyinfo->hyper_mod_mask = 0;
6287 #ifdef HAVE_X11R4
6288 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6289 #else
6290 min_code = dpyinfo->display->min_keycode;
6291 max_code = dpyinfo->display->max_keycode;
6292 #endif
6294 syms = XGetKeyboardMapping (dpyinfo->display,
6295 min_code, max_code - min_code + 1,
6296 &syms_per_code);
6297 mods = XGetModifierMapping (dpyinfo->display);
6299 /* Scan the modifier table to see which modifier bits the Meta and
6300 Alt keysyms are on. */
6302 int row, col; /* The row and column in the modifier table. */
6304 for (row = 3; row < 8; row++)
6305 for (col = 0; col < mods->max_keypermod; col++)
6307 KeyCode code
6308 = mods->modifiermap[(row * mods->max_keypermod) + col];
6310 /* Zeroes are used for filler. Skip them. */
6311 if (code == 0)
6312 continue;
6314 /* Are any of this keycode's keysyms a meta key? */
6316 int code_col;
6318 for (code_col = 0; code_col < syms_per_code; code_col++)
6320 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6322 switch (sym)
6324 case XK_Meta_L:
6325 case XK_Meta_R:
6326 dpyinfo->meta_mod_mask |= (1 << row);
6327 break;
6329 case XK_Alt_L:
6330 case XK_Alt_R:
6331 dpyinfo->alt_mod_mask |= (1 << row);
6332 break;
6334 case XK_Hyper_L:
6335 case XK_Hyper_R:
6336 dpyinfo->hyper_mod_mask |= (1 << row);
6337 break;
6339 case XK_Super_L:
6340 case XK_Super_R:
6341 dpyinfo->super_mod_mask |= (1 << row);
6342 break;
6344 case XK_Shift_Lock:
6345 /* Ignore this if it's not on the lock modifier. */
6346 if ((1 << row) == LockMask)
6347 dpyinfo->shift_lock_mask = LockMask;
6348 break;
6355 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6356 if (! dpyinfo->meta_mod_mask)
6358 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6359 dpyinfo->alt_mod_mask = 0;
6362 /* If some keys are both alt and meta,
6363 make them just meta, not alt. */
6364 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6366 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6369 XFree ((char *) syms);
6370 XFreeModifiermap (mods);
6373 /* Convert between the modifier bits X uses and the modifier bits
6374 Emacs uses. */
6376 static unsigned int
6377 x_x_to_emacs_modifiers (dpyinfo, state)
6378 struct x_display_info *dpyinfo;
6379 unsigned int state;
6381 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6382 | ((state & ControlMask) ? ctrl_modifier : 0)
6383 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6384 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6385 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6386 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6389 static unsigned int
6390 x_emacs_to_x_modifiers (dpyinfo, state)
6391 struct x_display_info *dpyinfo;
6392 unsigned int state;
6394 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6395 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6396 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6397 | ((state & shift_modifier) ? ShiftMask : 0)
6398 | ((state & ctrl_modifier) ? ControlMask : 0)
6399 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6402 /* Convert a keysym to its name. */
6404 char *
6405 x_get_keysym_name (keysym)
6406 KeySym keysym;
6408 char *value;
6410 BLOCK_INPUT;
6411 value = XKeysymToString (keysym);
6412 UNBLOCK_INPUT;
6414 return value;
6419 /* Mouse clicks and mouse movement. Rah. */
6421 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6422 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6423 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6424 not force the value into range. */
6426 void
6427 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6428 FRAME_PTR f;
6429 register int pix_x, pix_y;
6430 register int *x, *y;
6431 XRectangle *bounds;
6432 int noclip;
6434 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6435 even for negative values. */
6436 if (pix_x < 0)
6437 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6438 if (pix_y < 0)
6439 pix_y -= (f)->output_data.x->line_height - 1;
6441 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6442 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6444 if (bounds)
6446 bounds->width = FONT_WIDTH (f->output_data.x->font);
6447 bounds->height = f->output_data.x->line_height;
6448 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6449 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6452 if (!noclip)
6454 if (pix_x < 0)
6455 pix_x = 0;
6456 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6457 pix_x = FRAME_WINDOW_WIDTH (f);
6459 if (pix_y < 0)
6460 pix_y = 0;
6461 else if (pix_y > f->height)
6462 pix_y = f->height;
6465 *x = pix_x;
6466 *y = pix_y;
6470 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6471 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6472 can't tell the positions because W's display is not up to date,
6473 return 0. */
6476 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6477 struct window *w;
6478 int hpos, vpos;
6479 int *frame_x, *frame_y;
6481 int success_p;
6483 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6484 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6486 if (display_completed)
6488 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6489 struct glyph *glyph = row->glyphs[TEXT_AREA];
6490 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6492 *frame_y = row->y;
6493 *frame_x = row->x;
6494 while (glyph < end)
6496 *frame_x += glyph->pixel_width;
6497 ++glyph;
6500 success_p = 1;
6502 else
6504 *frame_y = *frame_x = 0;
6505 success_p = 0;
6508 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6509 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6510 return success_p;
6514 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6516 If the event is a button press, then note that we have grabbed
6517 the mouse. */
6519 static Lisp_Object
6520 construct_mouse_click (result, event, f)
6521 struct input_event *result;
6522 XButtonEvent *event;
6523 struct frame *f;
6525 /* Make the event type no_event; we'll change that when we decide
6526 otherwise. */
6527 result->kind = mouse_click;
6528 result->code = event->button - Button1;
6529 result->timestamp = event->time;
6530 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6531 event->state)
6532 | (event->type == ButtonRelease
6533 ? up_modifier
6534 : down_modifier));
6536 XSETINT (result->x, event->x);
6537 XSETINT (result->y, event->y);
6538 XSETFRAME (result->frame_or_window, f);
6539 result->arg = Qnil;
6540 return Qnil;
6544 /* Function to report a mouse movement to the mainstream Emacs code.
6545 The input handler calls this.
6547 We have received a mouse movement event, which is given in *event.
6548 If the mouse is over a different glyph than it was last time, tell
6549 the mainstream emacs code by setting mouse_moved. If not, ask for
6550 another motion event, so we can check again the next time it moves. */
6552 static XMotionEvent last_mouse_motion_event;
6553 static Lisp_Object last_mouse_motion_frame;
6555 static void
6556 note_mouse_movement (frame, event)
6557 FRAME_PTR frame;
6558 XMotionEvent *event;
6560 last_mouse_movement_time = event->time;
6561 last_mouse_motion_event = *event;
6562 XSETFRAME (last_mouse_motion_frame, frame);
6564 if (event->window != FRAME_X_WINDOW (frame))
6566 frame->mouse_moved = 1;
6567 last_mouse_scroll_bar = Qnil;
6568 note_mouse_highlight (frame, -1, -1);
6571 /* Has the mouse moved off the glyph it was on at the last sighting? */
6572 else if (event->x < last_mouse_glyph.x
6573 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6574 || event->y < last_mouse_glyph.y
6575 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6577 frame->mouse_moved = 1;
6578 last_mouse_scroll_bar = Qnil;
6579 note_mouse_highlight (frame, event->x, event->y);
6583 /* This is used for debugging, to turn off note_mouse_highlight. */
6585 int disable_mouse_highlight;
6589 /************************************************************************
6590 Mouse Face
6591 ************************************************************************/
6593 /* Find the glyph under window-relative coordinates X/Y in window W.
6594 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6595 strings. Return in *HPOS and *VPOS the row and column number of
6596 the glyph found. Return in *AREA the glyph area containing X.
6597 Value is a pointer to the glyph found or null if X/Y is not on
6598 text, or we can't tell because W's current matrix is not up to
6599 date. */
6601 static struct glyph *
6602 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6603 struct window *w;
6604 int x, y;
6605 int *hpos, *vpos, *area;
6606 int buffer_only_p;
6608 struct glyph *glyph, *end;
6609 struct glyph_row *row = NULL;
6610 int x0, i, left_area_width;
6612 /* Find row containing Y. Give up if some row is not enabled. */
6613 for (i = 0; i < w->current_matrix->nrows; ++i)
6615 row = MATRIX_ROW (w->current_matrix, i);
6616 if (!row->enabled_p)
6617 return NULL;
6618 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6619 break;
6622 *vpos = i;
6623 *hpos = 0;
6625 /* Give up if Y is not in the window. */
6626 if (i == w->current_matrix->nrows)
6627 return NULL;
6629 /* Get the glyph area containing X. */
6630 if (w->pseudo_window_p)
6632 *area = TEXT_AREA;
6633 x0 = 0;
6635 else
6637 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6638 if (x < left_area_width)
6640 *area = LEFT_MARGIN_AREA;
6641 x0 = 0;
6643 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6645 *area = TEXT_AREA;
6646 x0 = row->x + left_area_width;
6648 else
6650 *area = RIGHT_MARGIN_AREA;
6651 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6655 /* Find glyph containing X. */
6656 glyph = row->glyphs[*area];
6657 end = glyph + row->used[*area];
6658 while (glyph < end)
6660 if (x < x0 + glyph->pixel_width)
6662 if (w->pseudo_window_p)
6663 break;
6664 else if (!buffer_only_p || BUFFERP (glyph->object))
6665 break;
6668 x0 += glyph->pixel_width;
6669 ++glyph;
6672 if (glyph == end)
6673 return NULL;
6675 *hpos = glyph - row->glyphs[*area];
6676 return glyph;
6680 /* Convert frame-relative x/y to coordinates relative to window W.
6681 Takes pseudo-windows into account. */
6683 static void
6684 frame_to_window_pixel_xy (w, x, y)
6685 struct window *w;
6686 int *x, *y;
6688 if (w->pseudo_window_p)
6690 /* A pseudo-window is always full-width, and starts at the
6691 left edge of the frame, plus a frame border. */
6692 struct frame *f = XFRAME (w->frame);
6693 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6694 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6696 else
6698 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6699 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6704 /* Take proper action when mouse has moved to the mode or header line of
6705 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6706 mode line. X is relative to the start of the text display area of
6707 W, so the width of bitmap areas and scroll bars must be subtracted
6708 to get a position relative to the start of the mode line. */
6710 static void
6711 note_mode_line_highlight (w, x, mode_line_p)
6712 struct window *w;
6713 int x, mode_line_p;
6715 struct frame *f = XFRAME (w->frame);
6716 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6717 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6718 struct glyph_row *row;
6720 if (mode_line_p)
6721 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6722 else
6723 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6725 if (row->enabled_p)
6727 struct glyph *glyph, *end;
6728 Lisp_Object help, map;
6729 int x0;
6731 /* Find the glyph under X. */
6732 glyph = row->glyphs[TEXT_AREA];
6733 end = glyph + row->used[TEXT_AREA];
6734 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6735 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6737 while (glyph < end
6738 && x >= x0 + glyph->pixel_width)
6740 x0 += glyph->pixel_width;
6741 ++glyph;
6744 if (glyph < end
6745 && STRINGP (glyph->object)
6746 && XSTRING (glyph->object)->intervals
6747 && glyph->charpos >= 0
6748 && glyph->charpos < XSTRING (glyph->object)->size)
6750 /* If we're on a string with `help-echo' text property,
6751 arrange for the help to be displayed. This is done by
6752 setting the global variable help_echo to the help string. */
6753 help = Fget_text_property (make_number (glyph->charpos),
6754 Qhelp_echo, glyph->object);
6755 if (!NILP (help))
6757 help_echo = help;
6758 XSETWINDOW (help_echo_window, w);
6759 help_echo_object = glyph->object;
6760 help_echo_pos = glyph->charpos;
6763 /* Change the mouse pointer according to what is under X/Y. */
6764 map = Fget_text_property (make_number (glyph->charpos),
6765 Qlocal_map, glyph->object);
6766 if (KEYMAPP (map))
6767 cursor = f->output_data.x->nontext_cursor;
6768 else
6770 map = Fget_text_property (make_number (glyph->charpos),
6771 Qkeymap, glyph->object);
6772 if (KEYMAPP (map))
6773 cursor = f->output_data.x->nontext_cursor;
6778 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6782 /* Take proper action when the mouse has moved to position X, Y on
6783 frame F as regards highlighting characters that have mouse-face
6784 properties. Also de-highlighting chars where the mouse was before.
6785 X and Y can be negative or out of range. */
6787 static void
6788 note_mouse_highlight (f, x, y)
6789 struct frame *f;
6790 int x, y;
6792 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6793 int portion;
6794 Lisp_Object window;
6795 struct window *w;
6796 Cursor cursor = None;
6797 struct buffer *b;
6799 /* When a menu is active, don't highlight because this looks odd. */
6800 #ifdef USE_X_TOOLKIT
6801 if (popup_activated ())
6802 return;
6803 #endif
6805 if (disable_mouse_highlight
6806 || !f->glyphs_initialized_p)
6807 return;
6809 dpyinfo->mouse_face_mouse_x = x;
6810 dpyinfo->mouse_face_mouse_y = y;
6811 dpyinfo->mouse_face_mouse_frame = f;
6813 if (dpyinfo->mouse_face_defer)
6814 return;
6816 if (gc_in_progress)
6818 dpyinfo->mouse_face_deferred_gc = 1;
6819 return;
6822 /* Which window is that in? */
6823 window = window_from_coordinates (f, x, y, &portion, 1);
6825 /* If we were displaying active text in another window, clear that. */
6826 if (! EQ (window, dpyinfo->mouse_face_window))
6827 clear_mouse_face (dpyinfo);
6829 /* Not on a window -> return. */
6830 if (!WINDOWP (window))
6831 return;
6833 /* Convert to window-relative pixel coordinates. */
6834 w = XWINDOW (window);
6835 frame_to_window_pixel_xy (w, &x, &y);
6837 /* Handle tool-bar window differently since it doesn't display a
6838 buffer. */
6839 if (EQ (window, f->tool_bar_window))
6841 note_tool_bar_highlight (f, x, y);
6842 return;
6845 /* Mouse is on the mode or header line? */
6846 if (portion == 1 || portion == 3)
6848 note_mode_line_highlight (w, x, portion == 1);
6849 return;
6852 if (portion == 2)
6853 cursor = f->output_data.x->horizontal_drag_cursor;
6854 else
6855 cursor = f->output_data.x->text_cursor;
6857 /* Are we in a window whose display is up to date?
6858 And verify the buffer's text has not changed. */
6859 b = XBUFFER (w->buffer);
6860 if (/* Within text portion of the window. */
6861 portion == 0
6862 && EQ (w->window_end_valid, w->buffer)
6863 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6864 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6866 int hpos, vpos, pos, i, area;
6867 struct glyph *glyph;
6868 Lisp_Object object;
6869 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6870 Lisp_Object *overlay_vec = NULL;
6871 int len, noverlays;
6872 struct buffer *obuf;
6873 int obegv, ozv, same_region;
6875 /* Find the glyph under X/Y. */
6876 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6878 /* Clear mouse face if X/Y not over text. */
6879 if (glyph == NULL
6880 || area != TEXT_AREA
6881 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6883 clear_mouse_face (dpyinfo);
6884 return;
6887 pos = glyph->charpos;
6888 object = glyph->object;
6889 if (!STRINGP (object) && !BUFFERP (object))
6890 return;
6892 /* If we get an out-of-range value, return now; avoid an error. */
6893 if (BUFFERP (object) && pos > BUF_Z (b))
6894 return;
6896 /* Make the window's buffer temporarily current for
6897 overlays_at and compute_char_face. */
6898 obuf = current_buffer;
6899 current_buffer = b;
6900 obegv = BEGV;
6901 ozv = ZV;
6902 BEGV = BEG;
6903 ZV = Z;
6905 /* Is this char mouse-active or does it have help-echo? */
6906 position = make_number (pos);
6908 if (BUFFERP (object))
6910 /* Put all the overlays we want in a vector in overlay_vec.
6911 Store the length in len. If there are more than 10, make
6912 enough space for all, and try again. */
6913 len = 10;
6914 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6915 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6916 if (noverlays > len)
6918 len = noverlays;
6919 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6920 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6923 /* Sort overlays into increasing priority order. */
6924 noverlays = sort_overlays (overlay_vec, noverlays, w);
6926 else
6927 noverlays = 0;
6929 same_region = (EQ (window, dpyinfo->mouse_face_window)
6930 && vpos >= dpyinfo->mouse_face_beg_row
6931 && vpos <= dpyinfo->mouse_face_end_row
6932 && (vpos > dpyinfo->mouse_face_beg_row
6933 || hpos >= dpyinfo->mouse_face_beg_col)
6934 && (vpos < dpyinfo->mouse_face_end_row
6935 || hpos < dpyinfo->mouse_face_end_col
6936 || dpyinfo->mouse_face_past_end));
6938 if (same_region)
6939 cursor = None;
6941 /* Check mouse-face highlighting. */
6942 if (! same_region
6943 /* If there exists an overlay with mouse-face overlapping
6944 the one we are currently highlighting, we have to
6945 check if we enter the overlapping overlay, and then
6946 highlight only that. */
6947 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6948 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6950 /* Clear the display of the old active region, if any. */
6951 clear_mouse_face (dpyinfo);
6952 cursor = None;
6954 /* Find the highest priority overlay that has a mouse-face
6955 property. */
6956 overlay = Qnil;
6957 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6959 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6960 if (!NILP (mouse_face))
6961 overlay = overlay_vec[i];
6963 dpyinfo->mouse_face_overlay = overlay;
6965 /* If no overlay applies, get a text property. */
6966 if (NILP (overlay))
6967 mouse_face = Fget_text_property (position, Qmouse_face, object);
6969 /* Handle the overlay case. */
6970 if (!NILP (overlay))
6972 /* Find the range of text around this char that
6973 should be active. */
6974 Lisp_Object before, after;
6975 int ignore;
6977 before = Foverlay_start (overlay);
6978 after = Foverlay_end (overlay);
6979 /* Record this as the current active region. */
6980 fast_find_position (w, XFASTINT (before),
6981 &dpyinfo->mouse_face_beg_col,
6982 &dpyinfo->mouse_face_beg_row,
6983 &dpyinfo->mouse_face_beg_x,
6984 &dpyinfo->mouse_face_beg_y);
6985 dpyinfo->mouse_face_past_end
6986 = !fast_find_position (w, XFASTINT (after),
6987 &dpyinfo->mouse_face_end_col,
6988 &dpyinfo->mouse_face_end_row,
6989 &dpyinfo->mouse_face_end_x,
6990 &dpyinfo->mouse_face_end_y);
6991 dpyinfo->mouse_face_window = window;
6992 dpyinfo->mouse_face_face_id
6993 = face_at_buffer_position (w, pos, 0, 0,
6994 &ignore, pos + 1, 1);
6996 /* Display it as active. */
6997 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6999 /* Handle the text property case. */
7000 else if (!NILP (mouse_face) && BUFFERP (object))
7002 /* Find the range of text around this char that
7003 should be active. */
7004 Lisp_Object before, after, beginning, end;
7005 int ignore;
7007 beginning = Fmarker_position (w->start);
7008 end = make_number (BUF_Z (XBUFFER (object))
7009 - XFASTINT (w->window_end_pos));
7010 before
7011 = Fprevious_single_property_change (make_number (pos + 1),
7012 Qmouse_face,
7013 object, beginning);
7014 after
7015 = Fnext_single_property_change (position, Qmouse_face,
7016 object, end);
7018 /* Record this as the current active region. */
7019 fast_find_position (w, XFASTINT (before),
7020 &dpyinfo->mouse_face_beg_col,
7021 &dpyinfo->mouse_face_beg_row,
7022 &dpyinfo->mouse_face_beg_x,
7023 &dpyinfo->mouse_face_beg_y);
7024 dpyinfo->mouse_face_past_end
7025 = !fast_find_position (w, XFASTINT (after),
7026 &dpyinfo->mouse_face_end_col,
7027 &dpyinfo->mouse_face_end_row,
7028 &dpyinfo->mouse_face_end_x,
7029 &dpyinfo->mouse_face_end_y);
7030 dpyinfo->mouse_face_window = window;
7032 if (BUFFERP (object))
7033 dpyinfo->mouse_face_face_id
7034 = face_at_buffer_position (w, pos, 0, 0,
7035 &ignore, pos + 1, 1);
7037 /* Display it as active. */
7038 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7040 else if (!NILP (mouse_face) && STRINGP (object))
7042 Lisp_Object b, e;
7043 int ignore;
7045 b = Fprevious_single_property_change (make_number (pos + 1),
7046 Qmouse_face,
7047 object, Qnil);
7048 e = Fnext_single_property_change (position, Qmouse_face,
7049 object, Qnil);
7050 if (NILP (b))
7051 b = make_number (0);
7052 if (NILP (e))
7053 e = make_number (XSTRING (object)->size - 1);
7054 fast_find_string_pos (w, XINT (b), object,
7055 &dpyinfo->mouse_face_beg_col,
7056 &dpyinfo->mouse_face_beg_row,
7057 &dpyinfo->mouse_face_beg_x,
7058 &dpyinfo->mouse_face_beg_y, 0);
7059 fast_find_string_pos (w, XINT (e), object,
7060 &dpyinfo->mouse_face_end_col,
7061 &dpyinfo->mouse_face_end_row,
7062 &dpyinfo->mouse_face_end_x,
7063 &dpyinfo->mouse_face_end_y, 1);
7064 dpyinfo->mouse_face_past_end = 0;
7065 dpyinfo->mouse_face_window = window;
7066 dpyinfo->mouse_face_face_id
7067 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7068 glyph->face_id, 1);
7069 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7073 /* Look for a `help-echo' property. */
7075 Lisp_Object help, overlay;
7077 /* Check overlays first. */
7078 help = overlay = Qnil;
7079 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7081 overlay = overlay_vec[i];
7082 help = Foverlay_get (overlay, Qhelp_echo);
7085 if (!NILP (help))
7087 help_echo = help;
7088 help_echo_window = window;
7089 help_echo_object = overlay;
7090 help_echo_pos = pos;
7092 else
7094 Lisp_Object object = glyph->object;
7095 int charpos = glyph->charpos;
7097 /* Try text properties. */
7098 if (STRINGP (object)
7099 && charpos >= 0
7100 && charpos < XSTRING (object)->size)
7102 help = Fget_text_property (make_number (charpos),
7103 Qhelp_echo, object);
7104 if (NILP (help))
7106 /* If the string itself doesn't specify a help-echo,
7107 see if the buffer text ``under'' it does. */
7108 struct glyph_row *r
7109 = MATRIX_ROW (w->current_matrix, vpos);
7110 int start = MATRIX_ROW_START_CHARPOS (r);
7111 int pos = string_buffer_position (w, object, start);
7112 if (pos > 0)
7114 help = Fget_text_property (make_number (pos),
7115 Qhelp_echo, w->buffer);
7116 if (!NILP (help))
7118 charpos = pos;
7119 object = w->buffer;
7124 else if (BUFFERP (object)
7125 && charpos >= BEGV
7126 && charpos < ZV)
7127 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7128 object);
7130 if (!NILP (help))
7132 help_echo = help;
7133 help_echo_window = window;
7134 help_echo_object = object;
7135 help_echo_pos = charpos;
7140 BEGV = obegv;
7141 ZV = ozv;
7142 current_buffer = obuf;
7145 if (cursor != None)
7146 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7149 static void
7150 redo_mouse_highlight ()
7152 if (!NILP (last_mouse_motion_frame)
7153 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7154 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7155 last_mouse_motion_event.x,
7156 last_mouse_motion_event.y);
7161 /***********************************************************************
7162 Tool-bars
7163 ***********************************************************************/
7165 static int x_tool_bar_item P_ ((struct frame *, int, int,
7166 struct glyph **, int *, int *, int *));
7168 /* Tool-bar item index of the item on which a mouse button was pressed
7169 or -1. */
7171 static int last_tool_bar_item;
7174 /* Get information about the tool-bar item at position X/Y on frame F.
7175 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7176 the current matrix of the tool-bar window of F, or NULL if not
7177 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7178 item in F->tool_bar_items. Value is
7180 -1 if X/Y is not on a tool-bar item
7181 0 if X/Y is on the same item that was highlighted before.
7182 1 otherwise. */
7184 static int
7185 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7186 struct frame *f;
7187 int x, y;
7188 struct glyph **glyph;
7189 int *hpos, *vpos, *prop_idx;
7191 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7192 struct window *w = XWINDOW (f->tool_bar_window);
7193 int area;
7195 /* Find the glyph under X/Y. */
7196 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7197 if (*glyph == NULL)
7198 return -1;
7200 /* Get the start of this tool-bar item's properties in
7201 f->tool_bar_items. */
7202 if (!tool_bar_item_info (f, *glyph, prop_idx))
7203 return -1;
7205 /* Is mouse on the highlighted item? */
7206 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7207 && *vpos >= dpyinfo->mouse_face_beg_row
7208 && *vpos <= dpyinfo->mouse_face_end_row
7209 && (*vpos > dpyinfo->mouse_face_beg_row
7210 || *hpos >= dpyinfo->mouse_face_beg_col)
7211 && (*vpos < dpyinfo->mouse_face_end_row
7212 || *hpos < dpyinfo->mouse_face_end_col
7213 || dpyinfo->mouse_face_past_end))
7214 return 0;
7216 return 1;
7220 /* Handle mouse button event on the tool-bar of frame F, at
7221 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7222 or ButtonRelase. */
7224 static void
7225 x_handle_tool_bar_click (f, button_event)
7226 struct frame *f;
7227 XButtonEvent *button_event;
7229 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7230 struct window *w = XWINDOW (f->tool_bar_window);
7231 int hpos, vpos, prop_idx;
7232 struct glyph *glyph;
7233 Lisp_Object enabled_p;
7234 int x = button_event->x;
7235 int y = button_event->y;
7237 /* If not on the highlighted tool-bar item, return. */
7238 frame_to_window_pixel_xy (w, &x, &y);
7239 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7240 return;
7242 /* If item is disabled, do nothing. */
7243 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7244 if (NILP (enabled_p))
7245 return;
7247 if (button_event->type == ButtonPress)
7249 /* Show item in pressed state. */
7250 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7251 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7252 last_tool_bar_item = prop_idx;
7254 else
7256 Lisp_Object key, frame;
7257 struct input_event event;
7259 /* Show item in released state. */
7260 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7261 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7263 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7265 XSETFRAME (frame, f);
7266 event.kind = TOOL_BAR_EVENT;
7267 event.frame_or_window = frame;
7268 event.arg = frame;
7269 kbd_buffer_store_event (&event);
7271 event.kind = TOOL_BAR_EVENT;
7272 event.frame_or_window = frame;
7273 event.arg = key;
7274 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7275 button_event->state);
7276 kbd_buffer_store_event (&event);
7277 last_tool_bar_item = -1;
7282 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7283 tool-bar window-relative coordinates X/Y. Called from
7284 note_mouse_highlight. */
7286 static void
7287 note_tool_bar_highlight (f, x, y)
7288 struct frame *f;
7289 int x, y;
7291 Lisp_Object window = f->tool_bar_window;
7292 struct window *w = XWINDOW (window);
7293 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7294 int hpos, vpos;
7295 struct glyph *glyph;
7296 struct glyph_row *row;
7297 int i;
7298 Lisp_Object enabled_p;
7299 int prop_idx;
7300 enum draw_glyphs_face draw;
7301 int mouse_down_p, rc;
7303 /* Function note_mouse_highlight is called with negative x(y
7304 values when mouse moves outside of the frame. */
7305 if (x <= 0 || y <= 0)
7307 clear_mouse_face (dpyinfo);
7308 return;
7311 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7312 if (rc < 0)
7314 /* Not on tool-bar item. */
7315 clear_mouse_face (dpyinfo);
7316 return;
7318 else if (rc == 0)
7319 goto set_help_echo;
7321 clear_mouse_face (dpyinfo);
7323 /* Mouse is down, but on different tool-bar item? */
7324 mouse_down_p = (dpyinfo->grabbed
7325 && f == last_mouse_frame
7326 && FRAME_LIVE_P (f));
7327 if (mouse_down_p
7328 && last_tool_bar_item != prop_idx)
7329 return;
7331 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7332 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7334 /* If tool-bar item is not enabled, don't highlight it. */
7335 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7336 if (!NILP (enabled_p))
7338 /* Compute the x-position of the glyph. In front and past the
7339 image is a space. We include this is the highlighted area. */
7340 row = MATRIX_ROW (w->current_matrix, vpos);
7341 for (i = x = 0; i < hpos; ++i)
7342 x += row->glyphs[TEXT_AREA][i].pixel_width;
7344 /* Record this as the current active region. */
7345 dpyinfo->mouse_face_beg_col = hpos;
7346 dpyinfo->mouse_face_beg_row = vpos;
7347 dpyinfo->mouse_face_beg_x = x;
7348 dpyinfo->mouse_face_beg_y = row->y;
7349 dpyinfo->mouse_face_past_end = 0;
7351 dpyinfo->mouse_face_end_col = hpos + 1;
7352 dpyinfo->mouse_face_end_row = vpos;
7353 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7354 dpyinfo->mouse_face_end_y = row->y;
7355 dpyinfo->mouse_face_window = window;
7356 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7358 /* Display it as active. */
7359 show_mouse_face (dpyinfo, draw);
7360 dpyinfo->mouse_face_image_state = draw;
7363 set_help_echo:
7365 /* Set help_echo to a help string.to display for this tool-bar item.
7366 XTread_socket does the rest. */
7367 help_echo_object = help_echo_window = Qnil;
7368 help_echo_pos = -1;
7369 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7370 if (NILP (help_echo))
7371 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7376 /* Find the glyph matrix position of buffer position POS in window W.
7377 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7378 current glyphs must be up to date. If POS is above window start
7379 return (0, 0, 0, 0). If POS is after end of W, return end of
7380 last line in W. */
7382 static int
7383 fast_find_position (w, pos, hpos, vpos, x, y)
7384 struct window *w;
7385 int pos;
7386 int *hpos, *vpos, *x, *y;
7388 int i;
7389 int lastcol;
7390 int maybe_next_line_p = 0;
7391 int line_start_position;
7392 int yb = window_text_bottom_y (w);
7393 struct glyph_row *row, *best_row;
7394 int row_vpos, best_row_vpos;
7395 int current_x;
7397 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7398 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7400 while (row->y < yb)
7402 if (row->used[TEXT_AREA])
7403 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7404 else
7405 line_start_position = 0;
7407 if (line_start_position > pos)
7408 break;
7409 /* If the position sought is the end of the buffer,
7410 don't include the blank lines at the bottom of the window. */
7411 else if (line_start_position == pos
7412 && pos == BUF_ZV (XBUFFER (w->buffer)))
7414 maybe_next_line_p = 1;
7415 break;
7417 else if (line_start_position > 0)
7419 best_row = row;
7420 best_row_vpos = row_vpos;
7423 if (row->y + row->height >= yb)
7424 break;
7426 ++row;
7427 ++row_vpos;
7430 /* Find the right column within BEST_ROW. */
7431 lastcol = 0;
7432 current_x = best_row->x;
7433 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7435 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7436 int charpos;
7438 charpos = glyph->charpos;
7439 if (charpos == pos)
7441 *hpos = i;
7442 *vpos = best_row_vpos;
7443 *x = current_x;
7444 *y = best_row->y;
7445 return 1;
7447 else if (charpos > pos)
7448 break;
7449 else if (charpos > 0)
7450 lastcol = i;
7452 current_x += glyph->pixel_width;
7455 /* If we're looking for the end of the buffer,
7456 and we didn't find it in the line we scanned,
7457 use the start of the following line. */
7458 if (maybe_next_line_p)
7460 ++best_row;
7461 ++best_row_vpos;
7462 lastcol = 0;
7463 current_x = best_row->x;
7466 *vpos = best_row_vpos;
7467 *hpos = lastcol + 1;
7468 *x = current_x;
7469 *y = best_row->y;
7470 return 0;
7474 /* Find the position of the the glyph for position POS in OBJECT in
7475 window W's current matrix, and return in *X/*Y the pixel
7476 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7478 RIGHT_P non-zero means return the position of the right edge of the
7479 glyph, RIGHT_P zero means return the left edge position.
7481 If no glyph for POS exists in the matrix, return the position of
7482 the glyph with the next smaller position that is in the matrix, if
7483 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7484 exists in the matrix, return the position of the glyph with the
7485 next larger position in OBJECT.
7487 Value is non-zero if a glyph was found. */
7489 static int
7490 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7491 struct window *w;
7492 int pos;
7493 Lisp_Object object;
7494 int *hpos, *vpos, *x, *y;
7495 int right_p;
7497 int yb = window_text_bottom_y (w);
7498 struct glyph_row *r;
7499 struct glyph *best_glyph = NULL;
7500 struct glyph_row *best_row = NULL;
7501 int best_x = 0;
7503 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7504 r->enabled_p && r->y < yb;
7505 ++r)
7507 struct glyph *g = r->glyphs[TEXT_AREA];
7508 struct glyph *e = g + r->used[TEXT_AREA];
7509 int gx;
7511 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7512 if (EQ (g->object, object))
7514 if (g->charpos == pos)
7516 best_glyph = g;
7517 best_x = gx;
7518 best_row = r;
7519 goto found;
7521 else if (best_glyph == NULL
7522 || ((abs (g->charpos - pos)
7523 < abs (best_glyph->charpos - pos))
7524 && (right_p
7525 ? g->charpos < pos
7526 : g->charpos > pos)))
7528 best_glyph = g;
7529 best_x = gx;
7530 best_row = r;
7535 found:
7537 if (best_glyph)
7539 *x = best_x;
7540 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7542 if (right_p)
7544 *x += best_glyph->pixel_width;
7545 ++*hpos;
7548 *y = best_row->y;
7549 *vpos = best_row - w->current_matrix->rows;
7552 return best_glyph != NULL;
7556 /* Display the active region described by mouse_face_*
7557 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7559 static void
7560 show_mouse_face (dpyinfo, draw)
7561 struct x_display_info *dpyinfo;
7562 enum draw_glyphs_face draw;
7564 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7565 struct frame *f = XFRAME (WINDOW_FRAME (w));
7566 int i;
7567 int cursor_off_p = 0;
7568 struct cursor_pos saved_cursor;
7570 saved_cursor = output_cursor;
7572 /* If window is in the process of being destroyed, don't bother
7573 to do anything. */
7574 if (w->current_matrix == NULL)
7575 goto set_x_cursor;
7577 /* Recognize when we are called to operate on rows that don't exist
7578 anymore. This can happen when a window is split. */
7579 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7580 goto set_x_cursor;
7582 set_output_cursor (&w->phys_cursor);
7584 /* Note that mouse_face_beg_row etc. are window relative. */
7585 for (i = dpyinfo->mouse_face_beg_row;
7586 i <= dpyinfo->mouse_face_end_row;
7587 i++)
7589 int start_hpos, end_hpos, start_x;
7590 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7592 /* Don't do anything if row doesn't have valid contents. */
7593 if (!row->enabled_p)
7594 continue;
7596 /* For all but the first row, the highlight starts at column 0. */
7597 if (i == dpyinfo->mouse_face_beg_row)
7599 start_hpos = dpyinfo->mouse_face_beg_col;
7600 start_x = dpyinfo->mouse_face_beg_x;
7602 else
7604 start_hpos = 0;
7605 start_x = 0;
7608 if (i == dpyinfo->mouse_face_end_row)
7609 end_hpos = dpyinfo->mouse_face_end_col;
7610 else
7611 end_hpos = row->used[TEXT_AREA];
7613 /* If the cursor's in the text we are about to rewrite, turn the
7614 cursor off. */
7615 if (!w->pseudo_window_p
7616 && i == output_cursor.vpos
7617 && output_cursor.hpos >= start_hpos - 1
7618 && output_cursor.hpos <= end_hpos)
7620 x_update_window_cursor (w, 0);
7621 cursor_off_p = 1;
7624 if (end_hpos > start_hpos)
7626 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7627 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7628 start_hpos, end_hpos, draw, NULL, NULL, 0);
7632 /* If we turned the cursor off, turn it back on. */
7633 if (cursor_off_p)
7634 x_display_cursor (w, 1,
7635 output_cursor.hpos, output_cursor.vpos,
7636 output_cursor.x, output_cursor.y);
7638 output_cursor = saved_cursor;
7640 set_x_cursor:
7642 /* Change the mouse cursor. */
7643 if (draw == DRAW_NORMAL_TEXT)
7644 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7645 f->output_data.x->text_cursor);
7646 else if (draw == DRAW_MOUSE_FACE)
7647 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7648 f->output_data.x->cross_cursor);
7649 else
7650 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7651 f->output_data.x->nontext_cursor);
7654 /* Clear out the mouse-highlighted active region.
7655 Redraw it un-highlighted first. */
7657 void
7658 clear_mouse_face (dpyinfo)
7659 struct x_display_info *dpyinfo;
7661 #if 0 /* This prevents redrawing tool bar items when changing from one
7662 to another while a tooltip is open, so don't do it. */
7663 if (!NILP (tip_frame))
7664 return;
7665 #endif
7667 if (! NILP (dpyinfo->mouse_face_window))
7668 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7670 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7671 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7672 dpyinfo->mouse_face_window = Qnil;
7676 /* Clear any mouse-face on window W. This function is part of the
7677 redisplay interface, and is called from try_window_id and similar
7678 functions to ensure the mouse-highlight is off. */
7680 static void
7681 x_clear_mouse_face (w)
7682 struct window *w;
7684 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7685 Lisp_Object window;
7687 BLOCK_INPUT;
7688 XSETWINDOW (window, w);
7689 if (EQ (window, dpyinfo->mouse_face_window))
7690 clear_mouse_face (dpyinfo);
7691 UNBLOCK_INPUT;
7695 /* Just discard the mouse face information for frame F, if any.
7696 This is used when the size of F is changed. */
7698 void
7699 cancel_mouse_face (f)
7700 FRAME_PTR f;
7702 Lisp_Object window;
7703 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7705 window = dpyinfo->mouse_face_window;
7706 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7708 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7709 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7710 dpyinfo->mouse_face_window = Qnil;
7715 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7718 /* Try to determine frame pixel position and size of the glyph under
7719 frame pixel coordinates X/Y on frame F . Return the position and
7720 size in *RECT. Value is non-zero if we could compute these
7721 values. */
7723 static int
7724 glyph_rect (f, x, y, rect)
7725 struct frame *f;
7726 int x, y;
7727 XRectangle *rect;
7729 Lisp_Object window;
7730 int part, found = 0;
7732 window = window_from_coordinates (f, x, y, &part, 0);
7733 if (!NILP (window))
7735 struct window *w = XWINDOW (window);
7736 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7737 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7738 int area;
7740 frame_to_window_pixel_xy (w, &x, &y);
7742 for (; !found && r < end && r->enabled_p; ++r)
7743 if (r->y >= y)
7745 struct glyph *g = r->glyphs[TEXT_AREA];
7746 struct glyph *end = g + r->used[TEXT_AREA];
7747 int gx;
7749 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7750 if (gx >= x)
7752 rect->width = g->pixel_width;
7753 rect->height = r->height;
7754 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7755 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7756 found = 1;
7761 return found;
7765 /* Return the current position of the mouse.
7766 *FP should be a frame which indicates which display to ask about.
7768 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7769 and *PART to the frame, window, and scroll bar part that the mouse
7770 is over. Set *X and *Y to the portion and whole of the mouse's
7771 position on the scroll bar.
7773 If the mouse movement started elsewhere, set *FP to the frame the
7774 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7775 the mouse is over.
7777 Set *TIME to the server time-stamp for the time at which the mouse
7778 was at this position.
7780 Don't store anything if we don't have a valid set of values to report.
7782 This clears the mouse_moved flag, so we can wait for the next mouse
7783 movement. */
7785 static void
7786 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7787 FRAME_PTR *fp;
7788 int insist;
7789 Lisp_Object *bar_window;
7790 enum scroll_bar_part *part;
7791 Lisp_Object *x, *y;
7792 unsigned long *time;
7794 FRAME_PTR f1;
7796 BLOCK_INPUT;
7798 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7799 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7800 else
7802 Window root;
7803 int root_x, root_y;
7805 Window dummy_window;
7806 int dummy;
7808 Lisp_Object frame, tail;
7810 /* Clear the mouse-moved flag for every frame on this display. */
7811 FOR_EACH_FRAME (tail, frame)
7812 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7813 XFRAME (frame)->mouse_moved = 0;
7815 last_mouse_scroll_bar = Qnil;
7817 /* Figure out which root window we're on. */
7818 XQueryPointer (FRAME_X_DISPLAY (*fp),
7819 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7821 /* The root window which contains the pointer. */
7822 &root,
7824 /* Trash which we can't trust if the pointer is on
7825 a different screen. */
7826 &dummy_window,
7828 /* The position on that root window. */
7829 &root_x, &root_y,
7831 /* More trash we can't trust. */
7832 &dummy, &dummy,
7834 /* Modifier keys and pointer buttons, about which
7835 we don't care. */
7836 (unsigned int *) &dummy);
7838 /* Now we have a position on the root; find the innermost window
7839 containing the pointer. */
7841 Window win, child;
7842 int win_x, win_y;
7843 int parent_x = 0, parent_y = 0;
7844 int count;
7846 win = root;
7848 /* XTranslateCoordinates can get errors if the window
7849 structure is changing at the same time this function
7850 is running. So at least we must not crash from them. */
7852 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7854 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7855 && FRAME_LIVE_P (last_mouse_frame))
7857 /* If mouse was grabbed on a frame, give coords for that frame
7858 even if the mouse is now outside it. */
7859 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7861 /* From-window, to-window. */
7862 root, FRAME_X_WINDOW (last_mouse_frame),
7864 /* From-position, to-position. */
7865 root_x, root_y, &win_x, &win_y,
7867 /* Child of win. */
7868 &child);
7869 f1 = last_mouse_frame;
7871 else
7873 while (1)
7875 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7877 /* From-window, to-window. */
7878 root, win,
7880 /* From-position, to-position. */
7881 root_x, root_y, &win_x, &win_y,
7883 /* Child of win. */
7884 &child);
7886 if (child == None || child == win)
7887 break;
7889 win = child;
7890 parent_x = win_x;
7891 parent_y = win_y;
7894 /* Now we know that:
7895 win is the innermost window containing the pointer
7896 (XTC says it has no child containing the pointer),
7897 win_x and win_y are the pointer's position in it
7898 (XTC did this the last time through), and
7899 parent_x and parent_y are the pointer's position in win's parent.
7900 (They are what win_x and win_y were when win was child.
7901 If win is the root window, it has no parent, and
7902 parent_{x,y} are invalid, but that's okay, because we'll
7903 never use them in that case.) */
7905 /* Is win one of our frames? */
7906 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7908 #ifdef USE_X_TOOLKIT
7909 /* If we end up with the menu bar window, say it's not
7910 on the frame. */
7911 if (f1 != NULL
7912 && f1->output_data.x->menubar_widget
7913 && win == XtWindow (f1->output_data.x->menubar_widget))
7914 f1 = NULL;
7915 #endif /* USE_X_TOOLKIT */
7918 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7919 f1 = 0;
7921 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7923 /* If not, is it one of our scroll bars? */
7924 if (! f1)
7926 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7928 if (bar)
7930 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7931 win_x = parent_x;
7932 win_y = parent_y;
7936 if (f1 == 0 && insist > 0)
7937 f1 = SELECTED_FRAME ();
7939 if (f1)
7941 /* Ok, we found a frame. Store all the values.
7942 last_mouse_glyph is a rectangle used to reduce the
7943 generation of mouse events. To not miss any motion
7944 events, we must divide the frame into rectangles of the
7945 size of the smallest character that could be displayed
7946 on it, i.e. into the same rectangles that matrices on
7947 the frame are divided into. */
7949 int width, height, gx, gy;
7950 XRectangle rect;
7952 if (glyph_rect (f1, win_x, win_y, &rect))
7953 last_mouse_glyph = rect;
7954 else
7956 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7957 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7958 gx = win_x;
7959 gy = win_y;
7961 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7962 round down even for negative values. */
7963 if (gx < 0)
7964 gx -= width - 1;
7965 if (gy < 0)
7966 gy -= height - 1;
7967 gx = (gx + width - 1) / width * width;
7968 gy = (gy + height - 1) / height * height;
7970 last_mouse_glyph.width = width;
7971 last_mouse_glyph.height = height;
7972 last_mouse_glyph.x = gx;
7973 last_mouse_glyph.y = gy;
7976 *bar_window = Qnil;
7977 *part = 0;
7978 *fp = f1;
7979 XSETINT (*x, win_x);
7980 XSETINT (*y, win_y);
7981 *time = last_mouse_movement_time;
7986 UNBLOCK_INPUT;
7990 #ifdef USE_X_TOOLKIT
7992 /* Atimer callback function for TIMER. Called every 0.1s to process
7993 Xt timeouts, if needed. We must avoid calling XtAppPending as
7994 much as possible because that function does an implicit XFlush
7995 that slows us down. */
7997 static void
7998 x_process_timeouts (timer)
7999 struct atimer *timer;
8001 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8003 BLOCK_INPUT;
8004 while (XtAppPending (Xt_app_con) & XtIMTimer)
8005 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8006 UNBLOCK_INPUT;
8010 #endif /* USE_X_TOOLKIT */
8013 /* Scroll bar support. */
8015 /* Given an X window ID, find the struct scroll_bar which manages it.
8016 This can be called in GC, so we have to make sure to strip off mark
8017 bits. */
8019 static struct scroll_bar *
8020 x_window_to_scroll_bar (window_id)
8021 Window window_id;
8023 Lisp_Object tail;
8025 for (tail = Vframe_list;
8026 XGCTYPE (tail) == Lisp_Cons;
8027 tail = XCDR (tail))
8029 Lisp_Object frame, bar, condemned;
8031 frame = XCAR (tail);
8032 /* All elements of Vframe_list should be frames. */
8033 if (! GC_FRAMEP (frame))
8034 abort ();
8036 /* Scan this frame's scroll bar list for a scroll bar with the
8037 right window ID. */
8038 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8039 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8040 /* This trick allows us to search both the ordinary and
8041 condemned scroll bar lists with one loop. */
8042 ! GC_NILP (bar) || (bar = condemned,
8043 condemned = Qnil,
8044 ! GC_NILP (bar));
8045 bar = XSCROLL_BAR (bar)->next)
8046 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8047 return XSCROLL_BAR (bar);
8050 return 0;
8054 #if defined USE_X_TOOLKIT && defined USE_LUCID
8056 /* Return the Lucid menu bar WINDOW is part of. Return null
8057 if WINDOW is not part of a menu bar. */
8059 static Widget
8060 x_window_to_menu_bar (window)
8061 Window window;
8063 Lisp_Object tail;
8065 for (tail = Vframe_list;
8066 XGCTYPE (tail) == Lisp_Cons;
8067 tail = XCDR (tail))
8069 Lisp_Object frame = XCAR (tail);
8070 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8072 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8073 return menu_bar;
8076 return NULL;
8079 #endif /* USE_X_TOOLKIT && USE_LUCID */
8082 /************************************************************************
8083 Toolkit scroll bars
8084 ************************************************************************/
8086 #ifdef USE_TOOLKIT_SCROLL_BARS
8088 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8089 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8090 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8091 struct scroll_bar *));
8092 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8093 int, int, int));
8096 /* Id of action hook installed for scroll bars. */
8098 static XtActionHookId action_hook_id;
8100 /* Lisp window being scrolled. Set when starting to interact with
8101 a toolkit scroll bar, reset to nil when ending the interaction. */
8103 static Lisp_Object window_being_scrolled;
8105 /* Last scroll bar part sent in xm_scroll_callback. */
8107 static int last_scroll_bar_part;
8109 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8110 that movements of 1/20 of the screen size are mapped to up/down. */
8112 static Boolean xaw3d_arrow_scroll;
8114 /* Whether the drag scrolling maintains the mouse at the top of the
8115 thumb. If not, resizing the thumb needs to be done more carefully
8116 to avoid jerkyness. */
8118 static Boolean xaw3d_pick_top;
8121 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8122 bars are used.. The hook is responsible for detecting when
8123 the user ends an interaction with the scroll bar, and generates
8124 a `end-scroll' scroll_bar_click' event if so. */
8126 static void
8127 xt_action_hook (widget, client_data, action_name, event, params,
8128 num_params)
8129 Widget widget;
8130 XtPointer client_data;
8131 String action_name;
8132 XEvent *event;
8133 String *params;
8134 Cardinal *num_params;
8136 int scroll_bar_p;
8137 char *end_action;
8139 #ifdef USE_MOTIF
8140 scroll_bar_p = XmIsScrollBar (widget);
8141 end_action = "Release";
8142 #else /* !USE_MOTIF i.e. use Xaw */
8143 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8144 end_action = "EndScroll";
8145 #endif /* USE_MOTIF */
8147 if (scroll_bar_p
8148 && strcmp (action_name, end_action) == 0
8149 && WINDOWP (window_being_scrolled))
8151 struct window *w;
8153 x_send_scroll_bar_event (window_being_scrolled,
8154 scroll_bar_end_scroll, 0, 0);
8155 w = XWINDOW (window_being_scrolled);
8156 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8157 window_being_scrolled = Qnil;
8158 last_scroll_bar_part = -1;
8160 /* Xt timeouts no longer needed. */
8161 toolkit_scroll_bar_interaction = 0;
8165 /* A vector of windows used for communication between
8166 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8168 static struct window **scroll_bar_windows;
8169 static int scroll_bar_windows_size;
8172 /* Send a client message with message type Xatom_Scrollbar for a
8173 scroll action to the frame of WINDOW. PART is a value identifying
8174 the part of the scroll bar that was clicked on. PORTION is the
8175 amount to scroll of a whole of WHOLE. */
8177 static void
8178 x_send_scroll_bar_event (window, part, portion, whole)
8179 Lisp_Object window;
8180 int part, portion, whole;
8182 XEvent event;
8183 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8184 struct window *w = XWINDOW (window);
8185 struct frame *f = XFRAME (w->frame);
8186 int i;
8188 BLOCK_INPUT;
8190 /* Construct a ClientMessage event to send to the frame. */
8191 ev->type = ClientMessage;
8192 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8193 ev->display = FRAME_X_DISPLAY (f);
8194 ev->window = FRAME_X_WINDOW (f);
8195 ev->format = 32;
8197 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8198 not enough to store a pointer or Lisp_Object on a 64 bit system.
8199 So, store the window in scroll_bar_windows and pass the index
8200 into that array in the event. */
8201 for (i = 0; i < scroll_bar_windows_size; ++i)
8202 if (scroll_bar_windows[i] == NULL)
8203 break;
8205 if (i == scroll_bar_windows_size)
8207 int new_size = max (10, 2 * scroll_bar_windows_size);
8208 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8209 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8211 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8212 nbytes);
8213 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8214 scroll_bar_windows_size = new_size;
8217 scroll_bar_windows[i] = w;
8218 ev->data.l[0] = (long) i;
8219 ev->data.l[1] = (long) part;
8220 ev->data.l[2] = (long) 0;
8221 ev->data.l[3] = (long) portion;
8222 ev->data.l[4] = (long) whole;
8224 /* Make Xt timeouts work while the scroll bar is active. */
8225 toolkit_scroll_bar_interaction = 1;
8227 /* Setting the event mask to zero means that the message will
8228 be sent to the client that created the window, and if that
8229 window no longer exists, no event will be sent. */
8230 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8231 UNBLOCK_INPUT;
8235 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8236 in *IEVENT. */
8238 static void
8239 x_scroll_bar_to_input_event (event, ievent)
8240 XEvent *event;
8241 struct input_event *ievent;
8243 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8244 Lisp_Object window;
8245 struct frame *f;
8246 struct window *w;
8248 w = scroll_bar_windows[ev->data.l[0]];
8249 scroll_bar_windows[ev->data.l[0]] = NULL;
8251 XSETWINDOW (window, w);
8252 f = XFRAME (w->frame);
8254 ievent->kind = scroll_bar_click;
8255 ievent->frame_or_window = window;
8256 ievent->arg = Qnil;
8257 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8258 ievent->part = ev->data.l[1];
8259 ievent->code = ev->data.l[2];
8260 ievent->x = make_number ((int) ev->data.l[3]);
8261 ievent->y = make_number ((int) ev->data.l[4]);
8262 ievent->modifiers = 0;
8266 #ifdef USE_MOTIF
8268 /* Minimum and maximum values used for Motif scroll bars. */
8270 #define XM_SB_MIN 1
8271 #define XM_SB_MAX 10000000
8272 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8275 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8276 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8277 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8279 static void
8280 xm_scroll_callback (widget, client_data, call_data)
8281 Widget widget;
8282 XtPointer client_data, call_data;
8284 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8285 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8286 double percent;
8287 int part = -1, whole = 0, portion = 0;
8289 switch (cs->reason)
8291 case XmCR_DECREMENT:
8292 bar->dragging = Qnil;
8293 part = scroll_bar_up_arrow;
8294 break;
8296 case XmCR_INCREMENT:
8297 bar->dragging = Qnil;
8298 part = scroll_bar_down_arrow;
8299 break;
8301 case XmCR_PAGE_DECREMENT:
8302 bar->dragging = Qnil;
8303 part = scroll_bar_above_handle;
8304 break;
8306 case XmCR_PAGE_INCREMENT:
8307 bar->dragging = Qnil;
8308 part = scroll_bar_below_handle;
8309 break;
8311 case XmCR_TO_TOP:
8312 bar->dragging = Qnil;
8313 part = scroll_bar_to_top;
8314 break;
8316 case XmCR_TO_BOTTOM:
8317 bar->dragging = Qnil;
8318 part = scroll_bar_to_bottom;
8319 break;
8321 case XmCR_DRAG:
8323 int slider_size;
8324 int dragging_down_p = (INTEGERP (bar->dragging)
8325 && XINT (bar->dragging) <= cs->value);
8327 /* Get the slider size. */
8328 BLOCK_INPUT;
8329 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8330 UNBLOCK_INPUT;
8332 /* At the max position of the scroll bar, do a line-wise
8333 movement. Without doing anything, we would be called with
8334 the same cs->value again and again. If we want to make
8335 sure that we can reach the end of the buffer, we have to do
8336 something.
8338 Implementation note: setting bar->dragging always to
8339 cs->value gives a smoother movement at the max position.
8340 Setting it to nil when doing line-wise movement gives
8341 a better slider behavior. */
8343 if (cs->value + slider_size == XM_SB_MAX
8344 || (dragging_down_p
8345 && last_scroll_bar_part == scroll_bar_down_arrow))
8347 part = scroll_bar_down_arrow;
8348 bar->dragging = Qnil;
8350 else
8352 whole = XM_SB_RANGE;
8353 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8354 part = scroll_bar_handle;
8355 bar->dragging = make_number (cs->value);
8358 break;
8360 case XmCR_VALUE_CHANGED:
8361 break;
8364 if (part >= 0)
8366 window_being_scrolled = bar->window;
8367 last_scroll_bar_part = part;
8368 x_send_scroll_bar_event (bar->window, part, portion, whole);
8373 #else /* !USE_MOTIF, i.e. Xaw. */
8376 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8377 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8378 scroll bar struct. CALL_DATA is a pointer to a float saying where
8379 the thumb is. */
8381 static void
8382 xaw_jump_callback (widget, client_data, call_data)
8383 Widget widget;
8384 XtPointer client_data, call_data;
8386 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8387 float top = *(float *) call_data;
8388 float shown;
8389 int whole, portion, height;
8390 int part;
8392 /* Get the size of the thumb, a value between 0 and 1. */
8393 BLOCK_INPUT;
8394 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8395 UNBLOCK_INPUT;
8397 whole = 10000000;
8398 portion = shown < 1 ? top * whole : 0;
8400 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8401 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8402 the bottom, so we force the scrolling whenever we see that we're
8403 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8404 we try to ensure that we always stay two pixels away from the
8405 bottom). */
8406 part = scroll_bar_down_arrow;
8407 else
8408 part = scroll_bar_handle;
8410 window_being_scrolled = bar->window;
8411 bar->dragging = make_number (portion);
8412 last_scroll_bar_part = part;
8413 x_send_scroll_bar_event (bar->window, part, portion, whole);
8417 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8418 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8419 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8420 the scroll bar. CALL_DATA is an integer specifying the action that
8421 has taken place. It's magnitude is in the range 0..height of the
8422 scroll bar. Negative values mean scroll towards buffer start.
8423 Values < height of scroll bar mean line-wise movement. */
8425 static void
8426 xaw_scroll_callback (widget, client_data, call_data)
8427 Widget widget;
8428 XtPointer client_data, call_data;
8430 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8431 int position = (int) call_data;
8432 Dimension height;
8433 int part;
8435 /* Get the height of the scroll bar. */
8436 BLOCK_INPUT;
8437 XtVaGetValues (widget, XtNheight, &height, NULL);
8438 UNBLOCK_INPUT;
8440 if (abs (position) >= height)
8441 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8443 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8444 it maps line-movement to call_data = max(5, height/20). */
8445 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8446 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8447 else
8448 part = scroll_bar_move_ratio;
8450 window_being_scrolled = bar->window;
8451 bar->dragging = Qnil;
8452 last_scroll_bar_part = part;
8453 x_send_scroll_bar_event (bar->window, part, position, height);
8457 #endif /* not USE_MOTIF */
8460 /* Create the widget for scroll bar BAR on frame F. Record the widget
8461 and X window of the scroll bar in BAR. */
8463 static void
8464 x_create_toolkit_scroll_bar (f, bar)
8465 struct frame *f;
8466 struct scroll_bar *bar;
8468 Window xwindow;
8469 Widget widget;
8470 Arg av[20];
8471 int ac = 0;
8472 char *scroll_bar_name = "verticalScrollBar";
8473 unsigned long pixel;
8475 BLOCK_INPUT;
8477 #ifdef USE_MOTIF
8478 /* Set resources. Create the widget. */
8479 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8480 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8481 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8482 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8483 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8484 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8485 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8487 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8488 if (pixel != -1)
8490 XtSetArg (av[ac], XmNforeground, pixel);
8491 ++ac;
8494 pixel = f->output_data.x->scroll_bar_background_pixel;
8495 if (pixel != -1)
8497 XtSetArg (av[ac], XmNbackground, pixel);
8498 ++ac;
8501 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8502 scroll_bar_name, av, ac);
8504 /* Add one callback for everything that can happen. */
8505 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8506 (XtPointer) bar);
8507 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8508 (XtPointer) bar);
8509 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8510 (XtPointer) bar);
8511 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8512 (XtPointer) bar);
8513 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8514 (XtPointer) bar);
8515 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8516 (XtPointer) bar);
8517 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8518 (XtPointer) bar);
8520 /* Realize the widget. Only after that is the X window created. */
8521 XtRealizeWidget (widget);
8523 /* Set the cursor to an arrow. I didn't find a resource to do that.
8524 And I'm wondering why it hasn't an arrow cursor by default. */
8525 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8526 f->output_data.x->nontext_cursor);
8528 #else /* !USE_MOTIF i.e. use Xaw */
8530 /* Set resources. Create the widget. The background of the
8531 Xaw3d scroll bar widget is a little bit light for my taste.
8532 We don't alter it here to let users change it according
8533 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8534 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8535 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8536 /* For smoother scrolling with Xaw3d -sm */
8537 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8538 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8540 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8541 if (pixel != -1)
8543 XtSetArg (av[ac], XtNforeground, pixel);
8544 ++ac;
8547 pixel = f->output_data.x->scroll_bar_background_pixel;
8548 if (pixel != -1)
8550 XtSetArg (av[ac], XtNbackground, pixel);
8551 ++ac;
8554 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8555 f->output_data.x->edit_widget, av, ac);
8558 char *initial = "";
8559 char *val = initial;
8560 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8561 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8562 if (val == initial)
8563 { /* ARROW_SCROLL */
8564 xaw3d_arrow_scroll = True;
8565 /* Isn't that just a personal preference ? -sm */
8566 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8570 /* Define callbacks. */
8571 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8572 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8573 (XtPointer) bar);
8575 /* Realize the widget. Only after that is the X window created. */
8576 XtRealizeWidget (widget);
8578 #endif /* !USE_MOTIF */
8580 /* Install an action hook that let's us detect when the user
8581 finishes interacting with a scroll bar. */
8582 if (action_hook_id == 0)
8583 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8585 /* Remember X window and widget in the scroll bar vector. */
8586 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8587 xwindow = XtWindow (widget);
8588 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8590 UNBLOCK_INPUT;
8594 /* Set the thumb size and position of scroll bar BAR. We are currently
8595 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8597 static void
8598 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8599 struct scroll_bar *bar;
8600 int portion, position, whole;
8602 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8603 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8604 float top, shown;
8606 if (whole == 0)
8607 top = 0, shown = 1;
8608 else
8610 top = (float) position / whole;
8611 shown = (float) portion / whole;
8614 BLOCK_INPUT;
8616 #ifdef USE_MOTIF
8618 int size, value;
8619 XmScrollBarWidget sb;
8621 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8622 is the scroll bar's maximum and MIN is the scroll bar's minimum
8623 value. */
8624 size = shown * XM_SB_RANGE;
8625 size = min (size, XM_SB_RANGE);
8626 size = max (size, 1);
8628 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8629 value = top * XM_SB_RANGE;
8630 value = min (value, XM_SB_MAX - size);
8631 value = max (value, XM_SB_MIN);
8633 if (NILP (bar->dragging))
8634 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8635 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8636 /* This has the negative side effect that the slider value is
8637 not what it would be if we scrolled here using line-wise or
8638 page-wise movement. */
8639 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8640 else
8642 /* If currently dragging, only update the slider size.
8643 This reduces flicker effects. */
8644 int old_value, old_size, increment, page_increment;
8646 XmScrollBarGetValues (widget, &old_value, &old_size,
8647 &increment, &page_increment);
8648 XmScrollBarSetValues (widget, old_value,
8649 min (size, XM_SB_RANGE - old_value),
8650 0, 0, False);
8653 #else /* !USE_MOTIF i.e. use Xaw */
8655 float old_top, old_shown;
8656 Dimension height;
8657 XtVaGetValues (widget,
8658 XtNtopOfThumb, &old_top,
8659 XtNshown, &old_shown,
8660 XtNheight, &height,
8661 NULL);
8663 /* Massage the top+shown values. */
8664 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8665 top = max (0, min (1, top));
8666 else
8667 top = old_top;
8668 /* Keep two pixels available for moving the thumb down. */
8669 shown = max (0, min (1 - top - (2.0 / height), shown));
8671 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8672 check that your system's configuration file contains a define
8673 for `NARROWPROTO'. See s/freebsd.h for an example. */
8674 if (top != old_top || shown != old_shown)
8676 if (NILP (bar->dragging))
8677 XawScrollbarSetThumb (widget, top, shown);
8678 else
8680 #ifdef HAVE_XAW3D
8681 ScrollbarWidget sb = (ScrollbarWidget) widget;
8682 int scroll_mode = 0;
8684 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8685 if (xaw3d_arrow_scroll)
8687 /* Xaw3d stupidly ignores resize requests while dragging
8688 so we have to make it believe it's not in dragging mode. */
8689 scroll_mode = sb->scrollbar.scroll_mode;
8690 if (scroll_mode == 2)
8691 sb->scrollbar.scroll_mode = 0;
8693 #endif
8694 /* Try to make the scrolling a tad smoother. */
8695 if (!xaw3d_pick_top)
8696 shown = min (shown, old_shown);
8698 XawScrollbarSetThumb (widget, top, shown);
8700 #ifdef HAVE_XAW3D
8701 if (xaw3d_arrow_scroll && scroll_mode == 2)
8702 sb->scrollbar.scroll_mode = scroll_mode;
8703 #endif
8707 #endif /* !USE_MOTIF */
8709 UNBLOCK_INPUT;
8712 #endif /* USE_TOOLKIT_SCROLL_BARS */
8716 /************************************************************************
8717 Scroll bars, general
8718 ************************************************************************/
8720 /* Create a scroll bar and return the scroll bar vector for it. W is
8721 the Emacs window on which to create the scroll bar. TOP, LEFT,
8722 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8723 scroll bar. */
8725 static struct scroll_bar *
8726 x_scroll_bar_create (w, top, left, width, height)
8727 struct window *w;
8728 int top, left, width, height;
8730 struct frame *f = XFRAME (w->frame);
8731 struct scroll_bar *bar
8732 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8734 BLOCK_INPUT;
8736 #ifdef USE_TOOLKIT_SCROLL_BARS
8737 x_create_toolkit_scroll_bar (f, bar);
8738 #else /* not USE_TOOLKIT_SCROLL_BARS */
8740 XSetWindowAttributes a;
8741 unsigned long mask;
8742 Window window;
8744 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8745 if (a.background_pixel == -1)
8746 a.background_pixel = f->output_data.x->background_pixel;
8748 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8749 | ButtonMotionMask | PointerMotionHintMask
8750 | ExposureMask);
8751 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8753 mask = (CWBackPixel | CWEventMask | CWCursor);
8755 /* Clear the area of W that will serve as a scroll bar. This is
8756 for the case that a window has been split horizontally. In
8757 this case, no clear_frame is generated to reduce flickering. */
8758 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8759 left, top, width,
8760 window_box_height (w), False);
8762 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8763 /* Position and size of scroll bar. */
8764 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8765 top,
8766 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8767 height,
8768 /* Border width, depth, class, and visual. */
8770 CopyFromParent,
8771 CopyFromParent,
8772 CopyFromParent,
8773 /* Attributes. */
8774 mask, &a);
8775 SET_SCROLL_BAR_X_WINDOW (bar, window);
8777 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8779 XSETWINDOW (bar->window, w);
8780 XSETINT (bar->top, top);
8781 XSETINT (bar->left, left);
8782 XSETINT (bar->width, width);
8783 XSETINT (bar->height, height);
8784 XSETINT (bar->start, 0);
8785 XSETINT (bar->end, 0);
8786 bar->dragging = Qnil;
8788 /* Add bar to its frame's list of scroll bars. */
8789 bar->next = FRAME_SCROLL_BARS (f);
8790 bar->prev = Qnil;
8791 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8792 if (!NILP (bar->next))
8793 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8795 /* Map the window/widget. */
8796 #ifdef USE_TOOLKIT_SCROLL_BARS
8798 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8799 XtConfigureWidget (scroll_bar,
8800 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8801 top,
8802 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8803 max (height, 1), 0);
8804 XtMapWidget (scroll_bar);
8806 #else /* not USE_TOOLKIT_SCROLL_BARS */
8807 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8808 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8810 UNBLOCK_INPUT;
8811 return bar;
8815 /* Draw BAR's handle in the proper position.
8817 If the handle is already drawn from START to END, don't bother
8818 redrawing it, unless REBUILD is non-zero; in that case, always
8819 redraw it. (REBUILD is handy for drawing the handle after expose
8820 events.)
8822 Normally, we want to constrain the start and end of the handle to
8823 fit inside its rectangle, but if the user is dragging the scroll
8824 bar handle, we want to let them drag it down all the way, so that
8825 the bar's top is as far down as it goes; otherwise, there's no way
8826 to move to the very end of the buffer. */
8828 #ifndef USE_TOOLKIT_SCROLL_BARS
8830 static void
8831 x_scroll_bar_set_handle (bar, start, end, rebuild)
8832 struct scroll_bar *bar;
8833 int start, end;
8834 int rebuild;
8836 int dragging = ! NILP (bar->dragging);
8837 Window w = SCROLL_BAR_X_WINDOW (bar);
8838 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8839 GC gc = f->output_data.x->normal_gc;
8841 /* If the display is already accurate, do nothing. */
8842 if (! rebuild
8843 && start == XINT (bar->start)
8844 && end == XINT (bar->end))
8845 return;
8847 BLOCK_INPUT;
8850 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8851 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8852 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8854 /* Make sure the values are reasonable, and try to preserve
8855 the distance between start and end. */
8857 int length = end - start;
8859 if (start < 0)
8860 start = 0;
8861 else if (start > top_range)
8862 start = top_range;
8863 end = start + length;
8865 if (end < start)
8866 end = start;
8867 else if (end > top_range && ! dragging)
8868 end = top_range;
8871 /* Store the adjusted setting in the scroll bar. */
8872 XSETINT (bar->start, start);
8873 XSETINT (bar->end, end);
8875 /* Clip the end position, just for display. */
8876 if (end > top_range)
8877 end = top_range;
8879 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8880 below top positions, to make sure the handle is always at least
8881 that many pixels tall. */
8882 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8884 /* Draw the empty space above the handle. Note that we can't clear
8885 zero-height areas; that means "clear to end of window." */
8886 if (0 < start)
8887 x_clear_area (FRAME_X_DISPLAY (f), w,
8888 /* x, y, width, height, and exposures. */
8889 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8890 VERTICAL_SCROLL_BAR_TOP_BORDER,
8891 inside_width, start,
8892 False);
8894 /* Change to proper foreground color if one is specified. */
8895 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8896 XSetForeground (FRAME_X_DISPLAY (f), gc,
8897 f->output_data.x->scroll_bar_foreground_pixel);
8899 /* Draw the handle itself. */
8900 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8901 /* x, y, width, height */
8902 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8903 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8904 inside_width, end - start);
8906 /* Restore the foreground color of the GC if we changed it above. */
8907 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8908 XSetForeground (FRAME_X_DISPLAY (f), gc,
8909 f->output_data.x->foreground_pixel);
8911 /* Draw the empty space below the handle. Note that we can't
8912 clear zero-height areas; that means "clear to end of window." */
8913 if (end < inside_height)
8914 x_clear_area (FRAME_X_DISPLAY (f), w,
8915 /* x, y, width, height, and exposures. */
8916 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8917 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8918 inside_width, inside_height - end,
8919 False);
8923 UNBLOCK_INPUT;
8926 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8928 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8929 nil. */
8931 static void
8932 x_scroll_bar_remove (bar)
8933 struct scroll_bar *bar;
8935 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8936 BLOCK_INPUT;
8938 #ifdef USE_TOOLKIT_SCROLL_BARS
8939 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8940 #else
8941 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8942 #endif
8944 /* Disassociate this scroll bar from its window. */
8945 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8947 UNBLOCK_INPUT;
8951 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8952 that we are displaying PORTION characters out of a total of WHOLE
8953 characters, starting at POSITION. If WINDOW has no scroll bar,
8954 create one. */
8956 static void
8957 XTset_vertical_scroll_bar (w, portion, whole, position)
8958 struct window *w;
8959 int portion, whole, position;
8961 struct frame *f = XFRAME (w->frame);
8962 struct scroll_bar *bar;
8963 int top, height, left, sb_left, width, sb_width;
8964 int window_x, window_y, window_width, window_height;
8966 /* Get window dimensions. */
8967 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8968 top = window_y;
8969 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8970 height = window_height;
8972 /* Compute the left edge of the scroll bar area. */
8973 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8974 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8975 else
8976 left = XFASTINT (w->left);
8977 left *= CANON_X_UNIT (f);
8978 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8980 /* Compute the width of the scroll bar which might be less than
8981 the width of the area reserved for the scroll bar. */
8982 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8983 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8984 else
8985 sb_width = width;
8987 /* Compute the left edge of the scroll bar. */
8988 #ifdef USE_TOOLKIT_SCROLL_BARS
8989 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8990 sb_left = left + width - sb_width - (width - sb_width) / 2;
8991 else
8992 sb_left = left + (width - sb_width) / 2;
8993 #else
8994 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8995 sb_left = left + width - sb_width;
8996 else
8997 sb_left = left;
8998 #endif
9000 /* Does the scroll bar exist yet? */
9001 if (NILP (w->vertical_scroll_bar))
9003 BLOCK_INPUT;
9004 if (width && height)
9005 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9006 left, top, width, height, False);
9007 UNBLOCK_INPUT;
9008 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9010 else
9012 /* It may just need to be moved and resized. */
9013 unsigned int mask = 0;
9015 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9017 BLOCK_INPUT;
9019 if (sb_left != XINT (bar->left))
9020 mask |= CWX;
9021 if (top != XINT (bar->top))
9022 mask |= CWY;
9023 if (sb_width != XINT (bar->width))
9024 mask |= CWWidth;
9025 if (height != XINT (bar->height))
9026 mask |= CWHeight;
9028 #ifdef USE_TOOLKIT_SCROLL_BARS
9030 /* Since toolkit scroll bars are smaller than the space reserved
9031 for them on the frame, we have to clear "under" them. */
9032 if (width && height)
9033 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9034 left, top, width, height, False);
9036 /* Move/size the scroll bar widget. */
9037 if (mask)
9038 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9039 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9040 top,
9041 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9042 max (height, 1), 0);
9044 #else /* not USE_TOOLKIT_SCROLL_BARS */
9046 /* Clear areas not covered by the scroll bar because of
9047 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9048 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9050 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9051 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9052 height, False);
9053 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9054 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9055 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9056 height, False);
9059 /* Clear areas not covered by the scroll bar because it's not as
9060 wide as the area reserved for it . This makes sure a
9061 previous mode line display is cleared after C-x 2 C-x 1, for
9062 example. */
9064 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9065 int rest = area_width - sb_width;
9066 if (rest > 0)
9067 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9068 left + area_width - rest, 0,
9069 rest, max (height, 1), False);
9072 /* Move/size the scroll bar window. */
9073 if (mask)
9075 XWindowChanges wc;
9077 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9078 wc.y = top;
9079 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9080 wc.height = height;
9081 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9082 mask, &wc);
9085 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9087 /* Remember new settings. */
9088 XSETINT (bar->left, sb_left);
9089 XSETINT (bar->top, top);
9090 XSETINT (bar->width, sb_width);
9091 XSETINT (bar->height, height);
9093 UNBLOCK_INPUT;
9096 #ifdef USE_TOOLKIT_SCROLL_BARS
9097 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9098 #else /* not USE_TOOLKIT_SCROLL_BARS */
9099 /* Set the scroll bar's current state, unless we're currently being
9100 dragged. */
9101 if (NILP (bar->dragging))
9103 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9105 if (whole == 0)
9106 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9107 else
9109 int start = ((double) position * top_range) / whole;
9110 int end = ((double) (position + portion) * top_range) / whole;
9111 x_scroll_bar_set_handle (bar, start, end, 0);
9114 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9116 XSETVECTOR (w->vertical_scroll_bar, bar);
9120 /* The following three hooks are used when we're doing a thorough
9121 redisplay of the frame. We don't explicitly know which scroll bars
9122 are going to be deleted, because keeping track of when windows go
9123 away is a real pain - "Can you say set-window-configuration, boys
9124 and girls?" Instead, we just assert at the beginning of redisplay
9125 that *all* scroll bars are to be removed, and then save a scroll bar
9126 from the fiery pit when we actually redisplay its window. */
9128 /* Arrange for all scroll bars on FRAME to be removed at the next call
9129 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9130 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9132 static void
9133 XTcondemn_scroll_bars (frame)
9134 FRAME_PTR frame;
9136 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9137 while (! NILP (FRAME_SCROLL_BARS (frame)))
9139 Lisp_Object bar;
9140 bar = FRAME_SCROLL_BARS (frame);
9141 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9142 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9143 XSCROLL_BAR (bar)->prev = Qnil;
9144 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9145 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9146 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9151 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9152 Note that WINDOW isn't necessarily condemned at all. */
9154 static void
9155 XTredeem_scroll_bar (window)
9156 struct window *window;
9158 struct scroll_bar *bar;
9159 struct frame *f;
9161 /* We can't redeem this window's scroll bar if it doesn't have one. */
9162 if (NILP (window->vertical_scroll_bar))
9163 abort ();
9165 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9167 /* Unlink it from the condemned list. */
9168 f = XFRAME (WINDOW_FRAME (window));
9169 if (NILP (bar->prev))
9171 /* If the prev pointer is nil, it must be the first in one of
9172 the lists. */
9173 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9174 /* It's not condemned. Everything's fine. */
9175 return;
9176 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9177 window->vertical_scroll_bar))
9178 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9179 else
9180 /* If its prev pointer is nil, it must be at the front of
9181 one or the other! */
9182 abort ();
9184 else
9185 XSCROLL_BAR (bar->prev)->next = bar->next;
9187 if (! NILP (bar->next))
9188 XSCROLL_BAR (bar->next)->prev = bar->prev;
9190 bar->next = FRAME_SCROLL_BARS (f);
9191 bar->prev = Qnil;
9192 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9193 if (! NILP (bar->next))
9194 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9197 /* Remove all scroll bars on FRAME that haven't been saved since the
9198 last call to `*condemn_scroll_bars_hook'. */
9200 static void
9201 XTjudge_scroll_bars (f)
9202 FRAME_PTR f;
9204 Lisp_Object bar, next;
9206 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9208 /* Clear out the condemned list now so we won't try to process any
9209 more events on the hapless scroll bars. */
9210 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9212 for (; ! NILP (bar); bar = next)
9214 struct scroll_bar *b = XSCROLL_BAR (bar);
9216 x_scroll_bar_remove (b);
9218 next = b->next;
9219 b->next = b->prev = Qnil;
9222 /* Now there should be no references to the condemned scroll bars,
9223 and they should get garbage-collected. */
9227 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9228 is a no-op when using toolkit scroll bars.
9230 This may be called from a signal handler, so we have to ignore GC
9231 mark bits. */
9233 static void
9234 x_scroll_bar_expose (bar, event)
9235 struct scroll_bar *bar;
9236 XEvent *event;
9238 #ifndef USE_TOOLKIT_SCROLL_BARS
9240 Window w = SCROLL_BAR_X_WINDOW (bar);
9241 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9242 GC gc = f->output_data.x->normal_gc;
9243 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9245 BLOCK_INPUT;
9247 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9249 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9250 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9252 /* x, y, width, height */
9253 0, 0,
9254 XINT (bar->width) - 1 - width_trim - width_trim,
9255 XINT (bar->height) - 1);
9257 UNBLOCK_INPUT;
9259 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9262 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9263 is set to something other than no_event, it is enqueued.
9265 This may be called from a signal handler, so we have to ignore GC
9266 mark bits. */
9268 #ifndef USE_TOOLKIT_SCROLL_BARS
9270 static void
9271 x_scroll_bar_handle_click (bar, event, emacs_event)
9272 struct scroll_bar *bar;
9273 XEvent *event;
9274 struct input_event *emacs_event;
9276 if (! GC_WINDOWP (bar->window))
9277 abort ();
9279 emacs_event->kind = scroll_bar_click;
9280 emacs_event->code = event->xbutton.button - Button1;
9281 emacs_event->modifiers
9282 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9283 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9284 event->xbutton.state)
9285 | (event->type == ButtonRelease
9286 ? up_modifier
9287 : down_modifier));
9288 emacs_event->frame_or_window = bar->window;
9289 emacs_event->arg = Qnil;
9290 emacs_event->timestamp = event->xbutton.time;
9292 #if 0
9293 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9294 int internal_height
9295 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9296 #endif
9297 int top_range
9298 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9299 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9301 if (y < 0) y = 0;
9302 if (y > top_range) y = top_range;
9304 if (y < XINT (bar->start))
9305 emacs_event->part = scroll_bar_above_handle;
9306 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9307 emacs_event->part = scroll_bar_handle;
9308 else
9309 emacs_event->part = scroll_bar_below_handle;
9311 /* Just because the user has clicked on the handle doesn't mean
9312 they want to drag it. Lisp code needs to be able to decide
9313 whether or not we're dragging. */
9314 #if 0
9315 /* If the user has just clicked on the handle, record where they're
9316 holding it. */
9317 if (event->type == ButtonPress
9318 && emacs_event->part == scroll_bar_handle)
9319 XSETINT (bar->dragging, y - XINT (bar->start));
9320 #endif
9322 /* If the user has released the handle, set it to its final position. */
9323 if (event->type == ButtonRelease
9324 && ! NILP (bar->dragging))
9326 int new_start = y - XINT (bar->dragging);
9327 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9329 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9330 bar->dragging = Qnil;
9333 /* Same deal here as the other #if 0. */
9334 #if 0
9335 /* Clicks on the handle are always reported as occurring at the top of
9336 the handle. */
9337 if (emacs_event->part == scroll_bar_handle)
9338 emacs_event->x = bar->start;
9339 else
9340 XSETINT (emacs_event->x, y);
9341 #else
9342 XSETINT (emacs_event->x, y);
9343 #endif
9345 XSETINT (emacs_event->y, top_range);
9349 /* Handle some mouse motion while someone is dragging the scroll bar.
9351 This may be called from a signal handler, so we have to ignore GC
9352 mark bits. */
9354 static void
9355 x_scroll_bar_note_movement (bar, event)
9356 struct scroll_bar *bar;
9357 XEvent *event;
9359 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9361 last_mouse_movement_time = event->xmotion.time;
9363 f->mouse_moved = 1;
9364 XSETVECTOR (last_mouse_scroll_bar, bar);
9366 /* If we're dragging the bar, display it. */
9367 if (! GC_NILP (bar->dragging))
9369 /* Where should the handle be now? */
9370 int new_start = event->xmotion.y - XINT (bar->dragging);
9372 if (new_start != XINT (bar->start))
9374 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9376 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9381 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9383 /* Return information to the user about the current position of the mouse
9384 on the scroll bar. */
9386 static void
9387 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9388 FRAME_PTR *fp;
9389 Lisp_Object *bar_window;
9390 enum scroll_bar_part *part;
9391 Lisp_Object *x, *y;
9392 unsigned long *time;
9394 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9395 Window w = SCROLL_BAR_X_WINDOW (bar);
9396 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9397 int win_x, win_y;
9398 Window dummy_window;
9399 int dummy_coord;
9400 unsigned int dummy_mask;
9402 BLOCK_INPUT;
9404 /* Get the mouse's position relative to the scroll bar window, and
9405 report that. */
9406 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9408 /* Root, child, root x and root y. */
9409 &dummy_window, &dummy_window,
9410 &dummy_coord, &dummy_coord,
9412 /* Position relative to scroll bar. */
9413 &win_x, &win_y,
9415 /* Mouse buttons and modifier keys. */
9416 &dummy_mask))
9418 else
9420 #if 0
9421 int inside_height
9422 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9423 #endif
9424 int top_range
9425 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9427 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9429 if (! NILP (bar->dragging))
9430 win_y -= XINT (bar->dragging);
9432 if (win_y < 0)
9433 win_y = 0;
9434 if (win_y > top_range)
9435 win_y = top_range;
9437 *fp = f;
9438 *bar_window = bar->window;
9440 if (! NILP (bar->dragging))
9441 *part = scroll_bar_handle;
9442 else if (win_y < XINT (bar->start))
9443 *part = scroll_bar_above_handle;
9444 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9445 *part = scroll_bar_handle;
9446 else
9447 *part = scroll_bar_below_handle;
9449 XSETINT (*x, win_y);
9450 XSETINT (*y, top_range);
9452 f->mouse_moved = 0;
9453 last_mouse_scroll_bar = Qnil;
9456 *time = last_mouse_movement_time;
9458 UNBLOCK_INPUT;
9462 /* The screen has been cleared so we may have changed foreground or
9463 background colors, and the scroll bars may need to be redrawn.
9464 Clear out the scroll bars, and ask for expose events, so we can
9465 redraw them. */
9467 void
9468 x_scroll_bar_clear (f)
9469 FRAME_PTR f;
9471 #ifndef USE_TOOLKIT_SCROLL_BARS
9472 Lisp_Object bar;
9474 /* We can have scroll bars even if this is 0,
9475 if we just turned off scroll bar mode.
9476 But in that case we should not clear them. */
9477 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9478 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9479 bar = XSCROLL_BAR (bar)->next)
9480 XClearArea (FRAME_X_DISPLAY (f),
9481 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9482 0, 0, 0, 0, True);
9483 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9486 /* This processes Expose events from the menu-bar specific X event
9487 loop in xmenu.c. This allows to redisplay the frame if necessary
9488 when handling menu-bar or pop-up items. */
9491 process_expose_from_menu (event)
9492 XEvent event;
9494 FRAME_PTR f;
9495 struct x_display_info *dpyinfo;
9496 int frame_exposed_p = 0;
9498 BLOCK_INPUT;
9500 dpyinfo = x_display_info_for_display (event.xexpose.display);
9501 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9502 if (f)
9504 if (f->async_visible == 0)
9506 f->async_visible = 1;
9507 f->async_iconified = 0;
9508 f->output_data.x->has_been_visible = 1;
9509 SET_FRAME_GARBAGED (f);
9511 else
9513 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9514 event.xexpose.x, event.xexpose.y,
9515 event.xexpose.width, event.xexpose.height);
9516 frame_exposed_p = 1;
9519 else
9521 struct scroll_bar *bar
9522 = x_window_to_scroll_bar (event.xexpose.window);
9524 if (bar)
9525 x_scroll_bar_expose (bar, &event);
9528 UNBLOCK_INPUT;
9529 return frame_exposed_p;
9532 /* Define a queue to save up SelectionRequest events for later handling. */
9534 struct selection_event_queue
9536 XEvent event;
9537 struct selection_event_queue *next;
9540 static struct selection_event_queue *queue;
9542 /* Nonzero means queue up certain events--don't process them yet. */
9544 static int x_queue_selection_requests;
9546 /* Queue up an X event *EVENT, to be processed later. */
9548 static void
9549 x_queue_event (f, event)
9550 FRAME_PTR f;
9551 XEvent *event;
9553 struct selection_event_queue *queue_tmp
9554 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9556 if (queue_tmp != NULL)
9558 queue_tmp->event = *event;
9559 queue_tmp->next = queue;
9560 queue = queue_tmp;
9564 /* Take all the queued events and put them back
9565 so that they get processed afresh. */
9567 static void
9568 x_unqueue_events (display)
9569 Display *display;
9571 while (queue != NULL)
9573 struct selection_event_queue *queue_tmp = queue;
9574 XPutBackEvent (display, &queue_tmp->event);
9575 queue = queue_tmp->next;
9576 xfree ((char *)queue_tmp);
9580 /* Start queuing SelectionRequest events. */
9582 void
9583 x_start_queuing_selection_requests (display)
9584 Display *display;
9586 x_queue_selection_requests++;
9589 /* Stop queuing SelectionRequest events. */
9591 void
9592 x_stop_queuing_selection_requests (display)
9593 Display *display;
9595 x_queue_selection_requests--;
9596 x_unqueue_events (display);
9599 /* The main X event-reading loop - XTread_socket. */
9601 /* Time stamp of enter window event. This is only used by XTread_socket,
9602 but we have to put it out here, since static variables within functions
9603 sometimes don't work. */
9605 static Time enter_timestamp;
9607 /* This holds the state XLookupString needs to implement dead keys
9608 and other tricks known as "compose processing". _X Window System_
9609 says that a portable program can't use this, but Stephen Gildea assures
9610 me that letting the compiler initialize it to zeros will work okay.
9612 This must be defined outside of XTread_socket, for the same reasons
9613 given for enter_time stamp, above. */
9615 static XComposeStatus compose_status;
9617 /* Record the last 100 characters stored
9618 to help debug the loss-of-chars-during-GC problem. */
9620 static int temp_index;
9621 static short temp_buffer[100];
9623 /* Set this to nonzero to fake an "X I/O error"
9624 on a particular display. */
9626 struct x_display_info *XTread_socket_fake_io_error;
9628 /* When we find no input here, we occasionally do a no-op command
9629 to verify that the X server is still running and we can still talk with it.
9630 We try all the open displays, one by one.
9631 This variable is used for cycling thru the displays. */
9633 static struct x_display_info *next_noop_dpyinfo;
9635 #define SET_SAVED_MENU_EVENT(size) \
9636 do \
9638 if (f->output_data.x->saved_menu_event == 0) \
9639 f->output_data.x->saved_menu_event \
9640 = (XEvent *) xmalloc (sizeof (XEvent)); \
9641 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9642 if (numchars >= 1) \
9644 bufp->kind = menu_bar_activate_event; \
9645 XSETFRAME (bufp->frame_or_window, f); \
9646 bufp->arg = Qnil; \
9647 bufp++; \
9648 count++; \
9649 numchars--; \
9652 while (0)
9654 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9655 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9657 /* Read events coming from the X server.
9658 This routine is called by the SIGIO handler.
9659 We return as soon as there are no more events to be read.
9661 Events representing keys are stored in buffer BUFP,
9662 which can hold up to NUMCHARS characters.
9663 We return the number of characters stored into the buffer,
9664 thus pretending to be `read'.
9666 EXPECTED is nonzero if the caller knows input is available. */
9669 XTread_socket (sd, bufp, numchars, expected)
9670 register int sd;
9671 /* register */ struct input_event *bufp;
9672 /* register */ int numchars;
9673 int expected;
9675 int count = 0;
9676 int nbytes = 0;
9677 XEvent event;
9678 struct frame *f;
9679 int event_found = 0;
9680 struct x_display_info *dpyinfo;
9681 struct coding_system coding;
9683 if (interrupt_input_blocked)
9685 interrupt_input_pending = 1;
9686 return -1;
9689 interrupt_input_pending = 0;
9690 BLOCK_INPUT;
9692 /* So people can tell when we have read the available input. */
9693 input_signal_count++;
9695 if (numchars <= 0)
9696 abort (); /* Don't think this happens. */
9698 ++handling_signal;
9700 /* The input should be decoded if it is from XIM. Currently the
9701 locale of XIM is the same as that of the system. So, we can use
9702 Vlocale_coding_system which is initialized properly at Emacs
9703 startup time. */
9704 setup_coding_system (Vlocale_coding_system, &coding);
9705 coding.src_multibyte = 0;
9706 coding.dst_multibyte = 1;
9707 /* The input is converted to events, thus we can't handle
9708 composition. Anyway, there's no XIM that gives us composition
9709 information. */
9710 coding.composing = COMPOSITION_DISABLED;
9712 /* Find the display we are supposed to read input for.
9713 It's the one communicating on descriptor SD. */
9714 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9716 #if 0 /* This ought to be unnecessary; let's verify it. */
9717 #ifdef FIOSNBIO
9718 /* If available, Xlib uses FIOSNBIO to make the socket
9719 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9720 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9721 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9722 fcntl (dpyinfo->connection, F_SETFL, 0);
9723 #endif /* ! defined (FIOSNBIO) */
9724 #endif
9726 #if 0 /* This code can't be made to work, with multiple displays,
9727 and appears not to be used on any system any more.
9728 Also keyboard.c doesn't turn O_NDELAY on and off
9729 for X connections. */
9730 #ifndef SIGIO
9731 #ifndef HAVE_SELECT
9732 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9734 extern int read_alarm_should_throw;
9735 read_alarm_should_throw = 1;
9736 XPeekEvent (dpyinfo->display, &event);
9737 read_alarm_should_throw = 0;
9739 #endif /* HAVE_SELECT */
9740 #endif /* SIGIO */
9741 #endif
9743 /* For debugging, this gives a way to fake an I/O error. */
9744 if (dpyinfo == XTread_socket_fake_io_error)
9746 XTread_socket_fake_io_error = 0;
9747 x_io_error_quitter (dpyinfo->display);
9750 while (XPending (dpyinfo->display))
9752 XNextEvent (dpyinfo->display, &event);
9754 #ifdef HAVE_X_I18N
9756 /* Filter events for the current X input method.
9757 XFilterEvent returns non-zero if the input method has
9758 consumed the event. We pass the frame's X window to
9759 XFilterEvent because that's the one for which the IC
9760 was created. */
9761 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9762 event.xclient.window);
9763 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9764 break;
9766 #endif
9767 event_found = 1;
9769 switch (event.type)
9771 case ClientMessage:
9773 if (event.xclient.message_type
9774 == dpyinfo->Xatom_wm_protocols
9775 && event.xclient.format == 32)
9777 if (event.xclient.data.l[0]
9778 == dpyinfo->Xatom_wm_take_focus)
9780 /* Use x_any_window_to_frame because this
9781 could be the shell widget window
9782 if the frame has no title bar. */
9783 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9784 #ifdef HAVE_X_I18N
9785 /* Not quite sure this is needed -pd */
9786 if (f && FRAME_XIC (f))
9787 XSetICFocus (FRAME_XIC (f));
9788 #endif
9789 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9790 instructs the WM to set the input focus automatically for
9791 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9792 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9793 it has set the focus. So, XSetInputFocus below is not
9794 needed.
9796 The call to XSetInputFocus below has also caused trouble. In
9797 cases where the XSetInputFocus done by the WM and the one
9798 below are temporally close (on a fast machine), the call
9799 below can generate additional FocusIn events which confuse
9800 Emacs. */
9802 /* Since we set WM_TAKE_FOCUS, we must call
9803 XSetInputFocus explicitly. But not if f is null,
9804 since that might be an event for a deleted frame. */
9805 if (f)
9807 Display *d = event.xclient.display;
9808 /* Catch and ignore errors, in case window has been
9809 iconified by a window manager such as GWM. */
9810 int count = x_catch_errors (d);
9811 XSetInputFocus (d, event.xclient.window,
9812 /* The ICCCM says this is
9813 the only valid choice. */
9814 RevertToParent,
9815 event.xclient.data.l[1]);
9816 /* This is needed to detect the error
9817 if there is an error. */
9818 XSync (d, False);
9819 x_uncatch_errors (d, count);
9821 /* Not certain about handling scroll bars here */
9822 #endif /* 0 */
9824 else if (event.xclient.data.l[0]
9825 == dpyinfo->Xatom_wm_save_yourself)
9827 /* Save state modify the WM_COMMAND property to
9828 something which can reinstate us. This notifies
9829 the session manager, who's looking for such a
9830 PropertyNotify. Can restart processing when
9831 a keyboard or mouse event arrives. */
9832 if (numchars > 0)
9834 f = x_top_window_to_frame (dpyinfo,
9835 event.xclient.window);
9837 /* This is just so we only give real data once
9838 for a single Emacs process. */
9839 if (f == SELECTED_FRAME ())
9840 XSetCommand (FRAME_X_DISPLAY (f),
9841 event.xclient.window,
9842 initial_argv, initial_argc);
9843 else if (f)
9844 XSetCommand (FRAME_X_DISPLAY (f),
9845 event.xclient.window,
9846 0, 0);
9849 else if (event.xclient.data.l[0]
9850 == dpyinfo->Xatom_wm_delete_window)
9852 struct frame *f
9853 = x_any_window_to_frame (dpyinfo,
9854 event.xclient.window);
9856 if (f)
9858 if (numchars == 0)
9859 abort ();
9861 bufp->kind = delete_window_event;
9862 XSETFRAME (bufp->frame_or_window, f);
9863 bufp->arg = Qnil;
9864 bufp++;
9866 count += 1;
9867 numchars -= 1;
9871 else if (event.xclient.message_type
9872 == dpyinfo->Xatom_wm_configure_denied)
9875 else if (event.xclient.message_type
9876 == dpyinfo->Xatom_wm_window_moved)
9878 int new_x, new_y;
9879 struct frame *f
9880 = x_window_to_frame (dpyinfo, event.xclient.window);
9882 new_x = event.xclient.data.s[0];
9883 new_y = event.xclient.data.s[1];
9885 if (f)
9887 f->output_data.x->left_pos = new_x;
9888 f->output_data.x->top_pos = new_y;
9891 #ifdef HACK_EDITRES
9892 else if (event.xclient.message_type
9893 == dpyinfo->Xatom_editres)
9895 struct frame *f
9896 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9897 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9898 &event, NULL);
9900 #endif /* HACK_EDITRES */
9901 else if ((event.xclient.message_type
9902 == dpyinfo->Xatom_DONE)
9903 || (event.xclient.message_type
9904 == dpyinfo->Xatom_PAGE))
9906 /* Ghostview job completed. Kill it. We could
9907 reply with "Next" if we received "Page", but we
9908 currently never do because we are interested in
9909 images, only, which should have 1 page. */
9910 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9911 struct frame *f
9912 = x_window_to_frame (dpyinfo, event.xclient.window);
9913 x_kill_gs_process (pixmap, f);
9914 expose_frame (f, 0, 0, 0, 0);
9916 #ifdef USE_TOOLKIT_SCROLL_BARS
9917 /* Scroll bar callbacks send a ClientMessage from which
9918 we construct an input_event. */
9919 else if (event.xclient.message_type
9920 == dpyinfo->Xatom_Scrollbar)
9922 x_scroll_bar_to_input_event (&event, bufp);
9923 ++bufp, ++count, --numchars;
9924 goto out;
9926 #endif /* USE_TOOLKIT_SCROLL_BARS */
9927 else
9928 goto OTHER;
9930 break;
9932 case SelectionNotify:
9933 #ifdef USE_X_TOOLKIT
9934 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9935 goto OTHER;
9936 #endif /* not USE_X_TOOLKIT */
9937 x_handle_selection_notify (&event.xselection);
9938 break;
9940 case SelectionClear: /* Someone has grabbed ownership. */
9941 #ifdef USE_X_TOOLKIT
9942 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9943 goto OTHER;
9944 #endif /* USE_X_TOOLKIT */
9946 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9948 if (numchars == 0)
9949 abort ();
9951 bufp->kind = selection_clear_event;
9952 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9953 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9954 SELECTION_EVENT_TIME (bufp) = eventp->time;
9955 bufp->frame_or_window = Qnil;
9956 bufp->arg = Qnil;
9957 bufp++;
9959 count += 1;
9960 numchars -= 1;
9962 break;
9964 case SelectionRequest: /* Someone wants our selection. */
9965 #ifdef USE_X_TOOLKIT
9966 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9967 goto OTHER;
9968 #endif /* USE_X_TOOLKIT */
9969 if (x_queue_selection_requests)
9970 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9971 &event);
9972 else
9974 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9976 if (numchars == 0)
9977 abort ();
9979 bufp->kind = selection_request_event;
9980 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9981 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9982 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9983 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9984 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9985 SELECTION_EVENT_TIME (bufp) = eventp->time;
9986 bufp->frame_or_window = Qnil;
9987 bufp->arg = Qnil;
9988 bufp++;
9990 count += 1;
9991 numchars -= 1;
9993 break;
9995 case PropertyNotify:
9996 #ifdef USE_X_TOOLKIT
9997 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9998 goto OTHER;
9999 #endif /* not USE_X_TOOLKIT */
10000 x_handle_property_notify (&event.xproperty);
10001 break;
10003 case ReparentNotify:
10004 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10005 if (f)
10007 int x, y;
10008 f->output_data.x->parent_desc = event.xreparent.parent;
10009 x_real_positions (f, &x, &y);
10010 f->output_data.x->left_pos = x;
10011 f->output_data.x->top_pos = y;
10013 break;
10015 case Expose:
10016 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10017 if (f)
10019 if (f->async_visible == 0)
10021 f->async_visible = 1;
10022 f->async_iconified = 0;
10023 f->output_data.x->has_been_visible = 1;
10024 SET_FRAME_GARBAGED (f);
10026 else
10027 expose_frame (x_window_to_frame (dpyinfo,
10028 event.xexpose.window),
10029 event.xexpose.x, event.xexpose.y,
10030 event.xexpose.width, event.xexpose.height);
10032 else
10034 #ifndef USE_TOOLKIT_SCROLL_BARS
10035 struct scroll_bar *bar;
10036 #endif
10037 #if defined USE_X_TOOLKIT && defined USE_LUCID
10038 /* Submenus of the Lucid menu bar aren't widgets
10039 themselves, so there's no way to dispatch events
10040 to them. Recognize this case separately. */
10042 Widget widget
10043 = x_window_to_menu_bar (event.xexpose.window);
10044 if (widget)
10045 xlwmenu_redisplay (widget);
10047 #endif /* USE_X_TOOLKIT && USE_LUCID */
10049 #ifdef USE_TOOLKIT_SCROLL_BARS
10050 /* Dispatch event to the widget. */
10051 goto OTHER;
10052 #else /* not USE_TOOLKIT_SCROLL_BARS */
10053 bar = x_window_to_scroll_bar (event.xexpose.window);
10055 if (bar)
10056 x_scroll_bar_expose (bar, &event);
10057 #ifdef USE_X_TOOLKIT
10058 else
10059 goto OTHER;
10060 #endif /* USE_X_TOOLKIT */
10061 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10063 break;
10065 case GraphicsExpose: /* This occurs when an XCopyArea's
10066 source area was obscured or not
10067 available.*/
10068 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10069 if (f)
10071 expose_frame (f,
10072 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10073 event.xgraphicsexpose.width,
10074 event.xgraphicsexpose.height);
10076 #ifdef USE_X_TOOLKIT
10077 else
10078 goto OTHER;
10079 #endif /* USE_X_TOOLKIT */
10080 break;
10082 case NoExpose: /* This occurs when an XCopyArea's
10083 source area was completely
10084 available */
10085 break;
10087 case UnmapNotify:
10088 /* Redo the mouse-highlight after the tooltip has gone. */
10089 if (event.xmap.window == tip_window)
10091 tip_window = 0;
10092 redo_mouse_highlight ();
10095 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10096 if (f) /* F may no longer exist if
10097 the frame was deleted. */
10099 /* While a frame is unmapped, display generation is
10100 disabled; you don't want to spend time updating a
10101 display that won't ever be seen. */
10102 f->async_visible = 0;
10103 /* We can't distinguish, from the event, whether the window
10104 has become iconified or invisible. So assume, if it
10105 was previously visible, than now it is iconified.
10106 But x_make_frame_invisible clears both
10107 the visible flag and the iconified flag;
10108 and that way, we know the window is not iconified now. */
10109 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10111 f->async_iconified = 1;
10113 bufp->kind = iconify_event;
10114 XSETFRAME (bufp->frame_or_window, f);
10115 bufp->arg = Qnil;
10116 bufp++;
10117 count++;
10118 numchars--;
10121 goto OTHER;
10123 case MapNotify:
10124 if (event.xmap.window == tip_window)
10125 /* The tooltip has been drawn already. Avoid
10126 the SET_FRAME_GARBAGED below. */
10127 goto OTHER;
10129 /* We use x_top_window_to_frame because map events can
10130 come for sub-windows and they don't mean that the
10131 frame is visible. */
10132 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10133 if (f)
10135 f->async_visible = 1;
10136 f->async_iconified = 0;
10137 f->output_data.x->has_been_visible = 1;
10139 /* wait_reading_process_input will notice this and update
10140 the frame's display structures. */
10141 SET_FRAME_GARBAGED (f);
10143 if (f->iconified)
10145 bufp->kind = deiconify_event;
10146 XSETFRAME (bufp->frame_or_window, f);
10147 bufp->arg = Qnil;
10148 bufp++;
10149 count++;
10150 numchars--;
10152 else if (! NILP (Vframe_list)
10153 && ! NILP (XCDR (Vframe_list)))
10154 /* Force a redisplay sooner or later
10155 to update the frame titles
10156 in case this is the second frame. */
10157 record_asynch_buffer_change ();
10159 goto OTHER;
10161 case KeyPress:
10162 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10164 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10165 if (f == 0)
10167 /* Scroll bars consume key events, but we want
10168 the keys to go to the scroll bar's frame. */
10169 Widget widget = XtWindowToWidget (dpyinfo->display,
10170 event.xkey.window);
10171 if (widget && XmIsScrollBar (widget))
10173 widget = XtParent (widget);
10174 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10177 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10179 if (f != 0)
10181 KeySym keysym, orig_keysym;
10182 /* al%imercury@uunet.uu.net says that making this 81
10183 instead of 80 fixed a bug whereby meta chars made
10184 his Emacs hang.
10186 It seems that some version of XmbLookupString has
10187 a bug of not returning XBufferOverflow in
10188 status_return even if the input is too long to
10189 fit in 81 bytes. So, we must prepare sufficient
10190 bytes for copy_buffer. 513 bytes (256 chars for
10191 two-byte character set) seems to be a faily good
10192 approximation. -- 2000.8.10 handa@etl.go.jp */
10193 unsigned char copy_buffer[513];
10194 unsigned char *copy_bufptr = copy_buffer;
10195 int copy_bufsiz = sizeof (copy_buffer);
10196 int modifiers;
10198 event.xkey.state
10199 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10200 extra_keyboard_modifiers);
10201 modifiers = event.xkey.state;
10203 /* This will have to go some day... */
10205 /* make_lispy_event turns chars into control chars.
10206 Don't do it here because XLookupString is too eager. */
10207 event.xkey.state &= ~ControlMask;
10208 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10209 | dpyinfo->super_mod_mask
10210 | dpyinfo->hyper_mod_mask
10211 | dpyinfo->alt_mod_mask);
10213 /* In case Meta is ComposeCharacter,
10214 clear its status. According to Markus Ehrnsperger
10215 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10216 this enables ComposeCharacter to work whether or
10217 not it is combined with Meta. */
10218 if (modifiers & dpyinfo->meta_mod_mask)
10219 bzero (&compose_status, sizeof (compose_status));
10221 #ifdef HAVE_X_I18N
10222 if (FRAME_XIC (f))
10224 Status status_return;
10226 nbytes = XmbLookupString (FRAME_XIC (f),
10227 &event.xkey, copy_bufptr,
10228 copy_bufsiz, &keysym,
10229 &status_return);
10230 if (status_return == XBufferOverflow)
10232 copy_bufsiz = nbytes + 1;
10233 copy_bufptr = (char *) alloca (copy_bufsiz);
10234 nbytes = XmbLookupString (FRAME_XIC (f),
10235 &event.xkey, copy_bufptr,
10236 copy_bufsiz, &keysym,
10237 &status_return);
10240 if (status_return == XLookupNone)
10241 break;
10242 else if (status_return == XLookupChars)
10244 keysym = NoSymbol;
10245 modifiers = 0;
10247 else if (status_return != XLookupKeySym
10248 && status_return != XLookupBoth)
10249 abort ();
10251 else
10252 nbytes = XLookupString (&event.xkey, copy_bufptr,
10253 copy_bufsiz, &keysym,
10254 &compose_status);
10255 #else
10256 nbytes = XLookupString (&event.xkey, copy_bufptr,
10257 copy_bufsiz, &keysym,
10258 &compose_status);
10259 #endif
10261 orig_keysym = keysym;
10263 if (numchars > 1)
10265 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10266 || keysym == XK_Delete
10267 #ifdef XK_ISO_Left_Tab
10268 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10269 #endif
10270 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10271 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10272 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10273 #ifdef HPUX
10274 /* This recognizes the "extended function keys".
10275 It seems there's no cleaner way.
10276 Test IsModifierKey to avoid handling mode_switch
10277 incorrectly. */
10278 || ((unsigned) (keysym) >= XK_Select
10279 && (unsigned)(keysym) < XK_KP_Space)
10280 #endif
10281 #ifdef XK_dead_circumflex
10282 || orig_keysym == XK_dead_circumflex
10283 #endif
10284 #ifdef XK_dead_grave
10285 || orig_keysym == XK_dead_grave
10286 #endif
10287 #ifdef XK_dead_tilde
10288 || orig_keysym == XK_dead_tilde
10289 #endif
10290 #ifdef XK_dead_diaeresis
10291 || orig_keysym == XK_dead_diaeresis
10292 #endif
10293 #ifdef XK_dead_macron
10294 || orig_keysym == XK_dead_macron
10295 #endif
10296 #ifdef XK_dead_degree
10297 || orig_keysym == XK_dead_degree
10298 #endif
10299 #ifdef XK_dead_acute
10300 || orig_keysym == XK_dead_acute
10301 #endif
10302 #ifdef XK_dead_cedilla
10303 || orig_keysym == XK_dead_cedilla
10304 #endif
10305 #ifdef XK_dead_breve
10306 || orig_keysym == XK_dead_breve
10307 #endif
10308 #ifdef XK_dead_ogonek
10309 || orig_keysym == XK_dead_ogonek
10310 #endif
10311 #ifdef XK_dead_caron
10312 || orig_keysym == XK_dead_caron
10313 #endif
10314 #ifdef XK_dead_doubleacute
10315 || orig_keysym == XK_dead_doubleacute
10316 #endif
10317 #ifdef XK_dead_abovedot
10318 || orig_keysym == XK_dead_abovedot
10319 #endif
10320 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10321 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10322 /* Any "vendor-specific" key is ok. */
10323 || (orig_keysym & (1 << 28)))
10324 && ! (IsModifierKey (orig_keysym)
10325 #ifndef HAVE_X11R5
10326 #ifdef XK_Mode_switch
10327 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10328 #endif
10329 #ifdef XK_Num_Lock
10330 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10331 #endif
10332 #endif /* not HAVE_X11R5 */
10335 if (temp_index == sizeof temp_buffer / sizeof (short))
10336 temp_index = 0;
10337 temp_buffer[temp_index++] = keysym;
10338 bufp->kind = non_ascii_keystroke;
10339 bufp->code = keysym;
10340 XSETFRAME (bufp->frame_or_window, f);
10341 bufp->arg = Qnil;
10342 bufp->modifiers
10343 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10344 modifiers);
10345 bufp->timestamp = event.xkey.time;
10346 bufp++;
10347 count++;
10348 numchars--;
10350 else if (numchars > nbytes)
10352 register int i;
10353 register int c;
10354 int nchars, len;
10356 for (i = 0; i < nbytes; i++)
10358 if (temp_index == (sizeof temp_buffer
10359 / sizeof (short)))
10360 temp_index = 0;
10361 temp_buffer[temp_index++] = copy_bufptr[i];
10364 if (/* If the event is not from XIM, */
10365 event.xkey.keycode != 0
10366 /* or the current locale doesn't request
10367 decoding of the intup data, ... */
10368 || coding.type == coding_type_raw_text
10369 || coding.type == coding_type_no_conversion)
10371 /* ... we can use the input data as is. */
10372 nchars = nbytes;
10374 else
10376 /* We have to decode the input data. */
10377 int require;
10378 unsigned char *p;
10380 require = decoding_buffer_size (&coding, nbytes);
10381 p = (unsigned char *) alloca (require);
10382 coding.mode |= CODING_MODE_LAST_BLOCK;
10383 decode_coding (&coding, copy_bufptr, p,
10384 nbytes, require);
10385 nbytes = coding.produced;
10386 nchars = coding.produced_char;
10387 copy_bufptr = p;
10390 /* Convert the input data to a sequence of
10391 character events. */
10392 for (i = 0; i < nbytes; i += len)
10394 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10395 nbytes - i, len);
10396 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10397 ? ascii_keystroke
10398 : multibyte_char_keystroke);
10399 bufp->code = c;
10400 XSETFRAME (bufp->frame_or_window, f);
10401 bufp->arg = Qnil;
10402 bufp->modifiers
10403 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10404 modifiers);
10405 bufp->timestamp = event.xkey.time;
10406 bufp++;
10409 count += nchars;
10410 numchars -= nchars;
10412 if (keysym == NoSymbol)
10413 break;
10415 else
10416 abort ();
10418 else
10419 abort ();
10421 #ifdef HAVE_X_I18N
10422 /* Don't dispatch this event since XtDispatchEvent calls
10423 XFilterEvent, and two calls in a row may freeze the
10424 client. */
10425 break;
10426 #else
10427 goto OTHER;
10428 #endif
10430 case KeyRelease:
10431 #ifdef HAVE_X_I18N
10432 /* Don't dispatch this event since XtDispatchEvent calls
10433 XFilterEvent, and two calls in a row may freeze the
10434 client. */
10435 break;
10436 #else
10437 goto OTHER;
10438 #endif
10440 /* Here's a possible interpretation of the whole
10441 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10442 you get a FocusIn event, you have to get a FocusOut
10443 event before you relinquish the focus. If you
10444 haven't received a FocusIn event, then a mere
10445 LeaveNotify is enough to free you. */
10447 case EnterNotify:
10449 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10451 if (event.xcrossing.focus)
10453 /* Avoid nasty pop/raise loops. */
10454 if (f && (!(f->auto_raise)
10455 || !(f->auto_lower)
10456 || (event.xcrossing.time - enter_timestamp) > 500))
10458 x_new_focus_frame (dpyinfo, f);
10459 enter_timestamp = event.xcrossing.time;
10462 else if (f == dpyinfo->x_focus_frame)
10463 x_new_focus_frame (dpyinfo, 0);
10465 /* EnterNotify counts as mouse movement,
10466 so update things that depend on mouse position. */
10467 if (f && !f->output_data.x->hourglass_p)
10468 note_mouse_movement (f, &event.xmotion);
10469 goto OTHER;
10472 case FocusIn:
10473 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10474 if (event.xfocus.detail != NotifyPointer)
10475 dpyinfo->x_focus_event_frame = f;
10476 if (f)
10478 x_new_focus_frame (dpyinfo, f);
10480 /* Don't stop displaying the initial startup message
10481 for a switch-frame event we don't need. */
10482 if (GC_NILP (Vterminal_frame)
10483 && GC_CONSP (Vframe_list)
10484 && !GC_NILP (XCDR (Vframe_list)))
10486 bufp->kind = FOCUS_IN_EVENT;
10487 XSETFRAME (bufp->frame_or_window, f);
10488 bufp->arg = Qnil;
10489 ++bufp, ++count, --numchars;
10493 #ifdef HAVE_X_I18N
10494 if (f && FRAME_XIC (f))
10495 XSetICFocus (FRAME_XIC (f));
10496 #endif
10498 goto OTHER;
10500 case LeaveNotify:
10501 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10502 if (f)
10504 if (f == dpyinfo->mouse_face_mouse_frame)
10506 /* If we move outside the frame, then we're
10507 certainly no longer on any text in the frame. */
10508 clear_mouse_face (dpyinfo);
10509 dpyinfo->mouse_face_mouse_frame = 0;
10512 /* Generate a nil HELP_EVENT to cancel a help-echo.
10513 Do it only if there's something to cancel.
10514 Otherwise, the startup message is cleared when
10515 the mouse leaves the frame. */
10516 if (any_help_event_p)
10518 Lisp_Object frame;
10519 int n;
10521 XSETFRAME (frame, f);
10522 help_echo = Qnil;
10523 n = gen_help_event (bufp, numchars,
10524 Qnil, frame, Qnil, Qnil, 0);
10525 bufp += n, count += n, numchars -= n;
10528 if (event.xcrossing.focus)
10529 x_mouse_leave (dpyinfo);
10530 else
10532 if (f == dpyinfo->x_focus_event_frame)
10533 dpyinfo->x_focus_event_frame = 0;
10534 if (f == dpyinfo->x_focus_frame)
10535 x_new_focus_frame (dpyinfo, 0);
10538 goto OTHER;
10540 case FocusOut:
10541 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10542 if (event.xfocus.detail != NotifyPointer
10543 && f == dpyinfo->x_focus_event_frame)
10544 dpyinfo->x_focus_event_frame = 0;
10545 if (f && f == dpyinfo->x_focus_frame)
10546 x_new_focus_frame (dpyinfo, 0);
10548 #ifdef HAVE_X_I18N
10549 if (f && FRAME_XIC (f))
10550 XUnsetICFocus (FRAME_XIC (f));
10551 #endif
10553 goto OTHER;
10555 case MotionNotify:
10557 previous_help_echo = help_echo;
10558 help_echo = help_echo_object = help_echo_window = Qnil;
10559 help_echo_pos = -1;
10561 if (dpyinfo->grabbed && last_mouse_frame
10562 && FRAME_LIVE_P (last_mouse_frame))
10563 f = last_mouse_frame;
10564 else
10565 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10567 if (f)
10568 note_mouse_movement (f, &event.xmotion);
10569 else
10571 #ifndef USE_TOOLKIT_SCROLL_BARS
10572 struct scroll_bar *bar
10573 = x_window_to_scroll_bar (event.xmotion.window);
10575 if (bar)
10576 x_scroll_bar_note_movement (bar, &event);
10577 #endif /* USE_TOOLKIT_SCROLL_BARS */
10579 /* If we move outside the frame, then we're
10580 certainly no longer on any text in the frame. */
10581 clear_mouse_face (dpyinfo);
10584 /* If the contents of the global variable help_echo
10585 has changed, generate a HELP_EVENT. */
10586 if (!NILP (help_echo)
10587 || !NILP (previous_help_echo))
10589 Lisp_Object frame;
10590 int n;
10592 if (f)
10593 XSETFRAME (frame, f);
10594 else
10595 frame = Qnil;
10597 any_help_event_p = 1;
10598 n = gen_help_event (bufp, numchars, help_echo, frame,
10599 help_echo_window, help_echo_object,
10600 help_echo_pos);
10601 bufp += n, count += n, numchars -= n;
10604 goto OTHER;
10607 case ConfigureNotify:
10608 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10609 if (f)
10611 #ifndef USE_X_TOOLKIT
10612 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10613 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10615 /* In the toolkit version, change_frame_size
10616 is called by the code that handles resizing
10617 of the EmacsFrame widget. */
10619 /* Even if the number of character rows and columns has
10620 not changed, the font size may have changed, so we need
10621 to check the pixel dimensions as well. */
10622 if (columns != f->width
10623 || rows != f->height
10624 || event.xconfigure.width != f->output_data.x->pixel_width
10625 || event.xconfigure.height != f->output_data.x->pixel_height)
10627 change_frame_size (f, rows, columns, 0, 1, 0);
10628 SET_FRAME_GARBAGED (f);
10629 cancel_mouse_face (f);
10631 #endif
10633 f->output_data.x->pixel_width = event.xconfigure.width;
10634 f->output_data.x->pixel_height = event.xconfigure.height;
10636 /* What we have now is the position of Emacs's own window.
10637 Convert that to the position of the window manager window. */
10638 x_real_positions (f, &f->output_data.x->left_pos,
10639 &f->output_data.x->top_pos);
10641 #ifdef HAVE_X_I18N
10642 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10643 xic_set_statusarea (f);
10644 #endif
10646 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10648 /* Since the WM decorations come below top_pos now,
10649 we must put them below top_pos in the future. */
10650 f->output_data.x->win_gravity = NorthWestGravity;
10651 x_wm_set_size_hint (f, (long) 0, 0);
10653 #ifdef USE_MOTIF
10654 /* Some window managers pass (0,0) as the location of
10655 the window, and the Motif event handler stores it
10656 in the emacs widget, which messes up Motif menus. */
10657 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10659 event.xconfigure.x = f->output_data.x->widget->core.x;
10660 event.xconfigure.y = f->output_data.x->widget->core.y;
10662 #endif /* USE_MOTIF */
10664 goto OTHER;
10666 case ButtonPress:
10667 case ButtonRelease:
10669 /* If we decide we want to generate an event to be seen
10670 by the rest of Emacs, we put it here. */
10671 struct input_event emacs_event;
10672 int tool_bar_p = 0;
10674 emacs_event.kind = no_event;
10675 bzero (&compose_status, sizeof (compose_status));
10677 if (dpyinfo->grabbed
10678 && last_mouse_frame
10679 && FRAME_LIVE_P (last_mouse_frame))
10680 f = last_mouse_frame;
10681 else
10682 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10684 if (f)
10686 /* Is this in the tool-bar? */
10687 if (WINDOWP (f->tool_bar_window)
10688 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10690 Lisp_Object window;
10691 int p, x, y;
10693 x = event.xbutton.x;
10694 y = event.xbutton.y;
10696 /* Set x and y. */
10697 window = window_from_coordinates (f, x, y, &p, 1);
10698 if (EQ (window, f->tool_bar_window))
10700 x_handle_tool_bar_click (f, &event.xbutton);
10701 tool_bar_p = 1;
10705 if (!tool_bar_p)
10706 if (!dpyinfo->x_focus_frame
10707 || f == dpyinfo->x_focus_frame)
10708 construct_mouse_click (&emacs_event, &event, f);
10710 else
10712 #ifndef USE_TOOLKIT_SCROLL_BARS
10713 struct scroll_bar *bar
10714 = x_window_to_scroll_bar (event.xbutton.window);
10716 if (bar)
10717 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10718 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10721 if (event.type == ButtonPress)
10723 dpyinfo->grabbed |= (1 << event.xbutton.button);
10724 last_mouse_frame = f;
10725 /* Ignore any mouse motion that happened
10726 before this event; any subsequent mouse-movement
10727 Emacs events should reflect only motion after
10728 the ButtonPress. */
10729 if (f != 0)
10730 f->mouse_moved = 0;
10732 if (!tool_bar_p)
10733 last_tool_bar_item = -1;
10735 else
10737 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10740 if (numchars >= 1 && emacs_event.kind != no_event)
10742 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10743 bufp++;
10744 count++;
10745 numchars--;
10748 #ifdef USE_X_TOOLKIT
10749 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10750 /* For a down-event in the menu bar,
10751 don't pass it to Xt right now.
10752 Instead, save it away
10753 and we will pass it to Xt from kbd_buffer_get_event.
10754 That way, we can run some Lisp code first. */
10755 if (f && event.type == ButtonPress
10756 /* Verify the event is really within the menu bar
10757 and not just sent to it due to grabbing. */
10758 && event.xbutton.x >= 0
10759 && event.xbutton.x < f->output_data.x->pixel_width
10760 && event.xbutton.y >= 0
10761 && event.xbutton.y < f->output_data.x->menubar_height
10762 && event.xbutton.same_screen)
10764 SET_SAVED_BUTTON_EVENT;
10765 XSETFRAME (last_mouse_press_frame, f);
10767 else if (event.type == ButtonPress)
10769 last_mouse_press_frame = Qnil;
10770 goto OTHER;
10773 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10774 but I am trying to be cautious. */
10775 else if (event.type == ButtonRelease)
10777 if (!NILP (last_mouse_press_frame))
10779 f = XFRAME (last_mouse_press_frame);
10780 if (f->output_data.x)
10781 SET_SAVED_BUTTON_EVENT;
10783 else
10784 goto OTHER;
10786 #endif /* USE_MOTIF */
10787 else
10788 goto OTHER;
10789 #endif /* USE_X_TOOLKIT */
10791 break;
10793 case CirculateNotify:
10794 goto OTHER;
10796 case CirculateRequest:
10797 goto OTHER;
10799 case VisibilityNotify:
10800 goto OTHER;
10802 case MappingNotify:
10803 /* Someone has changed the keyboard mapping - update the
10804 local cache. */
10805 switch (event.xmapping.request)
10807 case MappingModifier:
10808 x_find_modifier_meanings (dpyinfo);
10809 /* This is meant to fall through. */
10810 case MappingKeyboard:
10811 XRefreshKeyboardMapping (&event.xmapping);
10813 goto OTHER;
10815 default:
10816 OTHER:
10817 #ifdef USE_X_TOOLKIT
10818 BLOCK_INPUT;
10819 XtDispatchEvent (&event);
10820 UNBLOCK_INPUT;
10821 #endif /* USE_X_TOOLKIT */
10822 break;
10827 out:;
10829 /* On some systems, an X bug causes Emacs to get no more events
10830 when the window is destroyed. Detect that. (1994.) */
10831 if (! event_found)
10833 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10834 One XNOOP in 100 loops will make Emacs terminate.
10835 B. Bretthauer, 1994 */
10836 x_noop_count++;
10837 if (x_noop_count >= 100)
10839 x_noop_count=0;
10841 if (next_noop_dpyinfo == 0)
10842 next_noop_dpyinfo = x_display_list;
10844 XNoOp (next_noop_dpyinfo->display);
10846 /* Each time we get here, cycle through the displays now open. */
10847 next_noop_dpyinfo = next_noop_dpyinfo->next;
10851 /* If the focus was just given to an auto-raising frame,
10852 raise it now. */
10853 /* ??? This ought to be able to handle more than one such frame. */
10854 if (pending_autoraise_frame)
10856 x_raise_frame (pending_autoraise_frame);
10857 pending_autoraise_frame = 0;
10860 UNBLOCK_INPUT;
10861 --handling_signal;
10862 return count;
10868 /***********************************************************************
10869 Text Cursor
10870 ***********************************************************************/
10872 /* Note if the text cursor of window W has been overwritten by a
10873 drawing operation that outputs N glyphs starting at HPOS in the
10874 line given by output_cursor.vpos. N < 0 means all the rest of the
10875 line after HPOS has been written. */
10877 static void
10878 note_overwritten_text_cursor (w, hpos, n)
10879 struct window *w;
10880 int hpos, n;
10882 if (updated_area == TEXT_AREA
10883 && output_cursor.vpos == w->phys_cursor.vpos
10884 && hpos <= w->phys_cursor.hpos
10885 && (n < 0
10886 || hpos + n > w->phys_cursor.hpos))
10887 w->phys_cursor_on_p = 0;
10891 /* Set clipping for output in glyph row ROW. W is the window in which
10892 we operate. GC is the graphics context to set clipping in.
10893 WHOLE_LINE_P non-zero means include the areas used for truncation
10894 mark display and alike in the clipping rectangle.
10896 ROW may be a text row or, e.g., a mode line. Text rows must be
10897 clipped to the interior of the window dedicated to text display,
10898 mode lines must be clipped to the whole window. */
10900 static void
10901 x_clip_to_row (w, row, gc, whole_line_p)
10902 struct window *w;
10903 struct glyph_row *row;
10904 GC gc;
10905 int whole_line_p;
10907 struct frame *f = XFRAME (WINDOW_FRAME (w));
10908 XRectangle clip_rect;
10909 int window_x, window_y, window_width, window_height;
10911 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10913 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10914 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10915 clip_rect.y = max (clip_rect.y, window_y);
10916 clip_rect.width = window_width;
10917 clip_rect.height = row->visible_height;
10919 /* If clipping to the whole line, including trunc marks, extend
10920 the rectangle to the left and increase its width. */
10921 if (whole_line_p)
10923 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10924 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10927 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10931 /* Draw a hollow box cursor on window W in glyph row ROW. */
10933 static void
10934 x_draw_hollow_cursor (w, row)
10935 struct window *w;
10936 struct glyph_row *row;
10938 struct frame *f = XFRAME (WINDOW_FRAME (w));
10939 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10940 Display *dpy = FRAME_X_DISPLAY (f);
10941 int x, y, wd, h;
10942 XGCValues xgcv;
10943 struct glyph *cursor_glyph;
10944 GC gc;
10946 /* Compute frame-relative coordinates from window-relative
10947 coordinates. */
10948 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10949 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10950 + row->ascent - w->phys_cursor_ascent);
10951 h = row->height - 1;
10953 /* Get the glyph the cursor is on. If we can't tell because
10954 the current matrix is invalid or such, give up. */
10955 cursor_glyph = get_phys_cursor_glyph (w);
10956 if (cursor_glyph == NULL)
10957 return;
10959 /* Compute the width of the rectangle to draw. If on a stretch
10960 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10961 rectangle as wide as the glyph, but use a canonical character
10962 width instead. */
10963 wd = cursor_glyph->pixel_width - 1;
10964 if (cursor_glyph->type == STRETCH_GLYPH
10965 && !x_stretch_cursor_p)
10966 wd = min (CANON_X_UNIT (f), wd);
10968 /* The foreground of cursor_gc is typically the same as the normal
10969 background color, which can cause the cursor box to be invisible. */
10970 xgcv.foreground = f->output_data.x->cursor_pixel;
10971 if (dpyinfo->scratch_cursor_gc)
10972 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10973 else
10974 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10975 GCForeground, &xgcv);
10976 gc = dpyinfo->scratch_cursor_gc;
10978 /* Set clipping, draw the rectangle, and reset clipping again. */
10979 x_clip_to_row (w, row, gc, 0);
10980 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10981 XSetClipMask (dpy, gc, None);
10985 /* Draw a bar cursor on window W in glyph row ROW.
10987 Implementation note: One would like to draw a bar cursor with an
10988 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10989 Unfortunately, I didn't find a font yet that has this property set.
10990 --gerd. */
10992 static void
10993 x_draw_bar_cursor (w, row, width)
10994 struct window *w;
10995 struct glyph_row *row;
10996 int width;
10998 struct frame *f = XFRAME (w->frame);
10999 struct glyph *cursor_glyph;
11000 GC gc;
11001 int x;
11002 unsigned long mask;
11003 XGCValues xgcv;
11004 Display *dpy;
11005 Window window;
11007 /* If cursor is out of bounds, don't draw garbage. This can happen
11008 in mini-buffer windows when switching between echo area glyphs
11009 and mini-buffer. */
11010 cursor_glyph = get_phys_cursor_glyph (w);
11011 if (cursor_glyph == NULL)
11012 return;
11014 /* If on an image, draw like a normal cursor. That's usually better
11015 visible than drawing a bar, esp. if the image is large so that
11016 the bar might not be in the window. */
11017 if (cursor_glyph->type == IMAGE_GLYPH)
11019 struct glyph_row *row;
11020 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11021 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11023 else
11025 xgcv.background = f->output_data.x->cursor_pixel;
11026 xgcv.foreground = f->output_data.x->cursor_pixel;
11027 xgcv.graphics_exposures = 0;
11028 mask = GCForeground | GCBackground | GCGraphicsExposures;
11029 dpy = FRAME_X_DISPLAY (f);
11030 window = FRAME_X_WINDOW (f);
11031 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11033 if (gc)
11034 XChangeGC (dpy, gc, mask, &xgcv);
11035 else
11037 gc = XCreateGC (dpy, window, mask, &xgcv);
11038 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11041 if (width < 0)
11042 width = f->output_data.x->cursor_width;
11044 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11045 x_clip_to_row (w, row, gc, 0);
11046 XFillRectangle (dpy, window, gc,
11048 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11049 min (cursor_glyph->pixel_width, width),
11050 row->height);
11051 XSetClipMask (dpy, gc, None);
11056 /* Clear the cursor of window W to background color, and mark the
11057 cursor as not shown. This is used when the text where the cursor
11058 is is about to be rewritten. */
11060 static void
11061 x_clear_cursor (w)
11062 struct window *w;
11064 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11065 x_update_window_cursor (w, 0);
11069 /* Draw the cursor glyph of window W in glyph row ROW. See the
11070 comment of x_draw_glyphs for the meaning of HL. */
11072 static void
11073 x_draw_phys_cursor_glyph (w, row, hl)
11074 struct window *w;
11075 struct glyph_row *row;
11076 enum draw_glyphs_face hl;
11078 /* If cursor hpos is out of bounds, don't draw garbage. This can
11079 happen in mini-buffer windows when switching between echo area
11080 glyphs and mini-buffer. */
11081 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11083 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11084 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11085 hl, 0, 0, 0);
11087 /* When we erase the cursor, and ROW is overlapped by other
11088 rows, make sure that these overlapping parts of other rows
11089 are redrawn. */
11090 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11092 if (row > w->current_matrix->rows
11093 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11094 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11096 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11097 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11098 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11104 /* Erase the image of a cursor of window W from the screen. */
11106 static void
11107 x_erase_phys_cursor (w)
11108 struct window *w;
11110 struct frame *f = XFRAME (w->frame);
11111 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11112 int hpos = w->phys_cursor.hpos;
11113 int vpos = w->phys_cursor.vpos;
11114 int mouse_face_here_p = 0;
11115 struct glyph_matrix *active_glyphs = w->current_matrix;
11116 struct glyph_row *cursor_row;
11117 struct glyph *cursor_glyph;
11118 enum draw_glyphs_face hl;
11120 /* No cursor displayed or row invalidated => nothing to do on the
11121 screen. */
11122 if (w->phys_cursor_type == NO_CURSOR)
11123 goto mark_cursor_off;
11125 /* VPOS >= active_glyphs->nrows means that window has been resized.
11126 Don't bother to erase the cursor. */
11127 if (vpos >= active_glyphs->nrows)
11128 goto mark_cursor_off;
11130 /* If row containing cursor is marked invalid, there is nothing we
11131 can do. */
11132 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11133 if (!cursor_row->enabled_p)
11134 goto mark_cursor_off;
11136 /* This can happen when the new row is shorter than the old one.
11137 In this case, either x_draw_glyphs or clear_end_of_line
11138 should have cleared the cursor. Note that we wouldn't be
11139 able to erase the cursor in this case because we don't have a
11140 cursor glyph at hand. */
11141 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11142 goto mark_cursor_off;
11144 /* If the cursor is in the mouse face area, redisplay that when
11145 we clear the cursor. */
11146 if (! NILP (dpyinfo->mouse_face_window)
11147 && w == XWINDOW (dpyinfo->mouse_face_window)
11148 && (vpos > dpyinfo->mouse_face_beg_row
11149 || (vpos == dpyinfo->mouse_face_beg_row
11150 && hpos >= dpyinfo->mouse_face_beg_col))
11151 && (vpos < dpyinfo->mouse_face_end_row
11152 || (vpos == dpyinfo->mouse_face_end_row
11153 && hpos < dpyinfo->mouse_face_end_col))
11154 /* Don't redraw the cursor's spot in mouse face if it is at the
11155 end of a line (on a newline). The cursor appears there, but
11156 mouse highlighting does not. */
11157 && cursor_row->used[TEXT_AREA] > hpos)
11158 mouse_face_here_p = 1;
11160 /* Maybe clear the display under the cursor. */
11161 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11163 int x;
11164 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11166 cursor_glyph = get_phys_cursor_glyph (w);
11167 if (cursor_glyph == NULL)
11168 goto mark_cursor_off;
11170 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11172 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11174 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11175 cursor_row->y)),
11176 cursor_glyph->pixel_width,
11177 cursor_row->visible_height,
11178 False);
11181 /* Erase the cursor by redrawing the character underneath it. */
11182 if (mouse_face_here_p)
11183 hl = DRAW_MOUSE_FACE;
11184 else if (cursor_row->inverse_p)
11185 hl = DRAW_INVERSE_VIDEO;
11186 else
11187 hl = DRAW_NORMAL_TEXT;
11188 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11190 mark_cursor_off:
11191 w->phys_cursor_on_p = 0;
11192 w->phys_cursor_type = NO_CURSOR;
11196 /* Display or clear cursor of window W. If ON is zero, clear the
11197 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11198 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11200 void
11201 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11202 struct window *w;
11203 int on, hpos, vpos, x, y;
11205 struct frame *f = XFRAME (w->frame);
11206 int new_cursor_type;
11207 int new_cursor_width;
11208 struct glyph_matrix *current_glyphs;
11209 struct glyph_row *glyph_row;
11210 struct glyph *glyph;
11212 /* This is pointless on invisible frames, and dangerous on garbaged
11213 windows and frames; in the latter case, the frame or window may
11214 be in the midst of changing its size, and x and y may be off the
11215 window. */
11216 if (! FRAME_VISIBLE_P (f)
11217 || FRAME_GARBAGED_P (f)
11218 || vpos >= w->current_matrix->nrows
11219 || hpos >= w->current_matrix->matrix_w)
11220 return;
11222 /* If cursor is off and we want it off, return quickly. */
11223 if (!on && !w->phys_cursor_on_p)
11224 return;
11226 current_glyphs = w->current_matrix;
11227 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11228 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11230 /* If cursor row is not enabled, we don't really know where to
11231 display the cursor. */
11232 if (!glyph_row->enabled_p)
11234 w->phys_cursor_on_p = 0;
11235 return;
11238 xassert (interrupt_input_blocked);
11240 /* Set new_cursor_type to the cursor we want to be displayed. In a
11241 mini-buffer window, we want the cursor only to appear if we are
11242 reading input from this window. For the selected window, we want
11243 the cursor type given by the frame parameter. If explicitly
11244 marked off, draw no cursor. In all other cases, we want a hollow
11245 box cursor. */
11246 new_cursor_width = -1;
11247 if (cursor_in_echo_area
11248 && FRAME_HAS_MINIBUF_P (f)
11249 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11251 if (w == XWINDOW (echo_area_window))
11252 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11253 else
11254 new_cursor_type = HOLLOW_BOX_CURSOR;
11256 else
11258 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11259 || w != XWINDOW (f->selected_window))
11261 extern int cursor_in_non_selected_windows;
11263 if (MINI_WINDOW_P (w)
11264 || !cursor_in_non_selected_windows
11265 || NILP (XBUFFER (w->buffer)->cursor_type))
11266 new_cursor_type = NO_CURSOR;
11267 else
11268 new_cursor_type = HOLLOW_BOX_CURSOR;
11270 else if (w->cursor_off_p)
11271 new_cursor_type = NO_CURSOR;
11272 else
11274 struct buffer *b = XBUFFER (w->buffer);
11276 if (EQ (b->cursor_type, Qt))
11277 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11278 else
11279 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11280 &new_cursor_width);
11284 /* If cursor is currently being shown and we don't want it to be or
11285 it is in the wrong place, or the cursor type is not what we want,
11286 erase it. */
11287 if (w->phys_cursor_on_p
11288 && (!on
11289 || w->phys_cursor.x != x
11290 || w->phys_cursor.y != y
11291 || new_cursor_type != w->phys_cursor_type))
11292 x_erase_phys_cursor (w);
11294 /* If the cursor is now invisible and we want it to be visible,
11295 display it. */
11296 if (on && !w->phys_cursor_on_p)
11298 w->phys_cursor_ascent = glyph_row->ascent;
11299 w->phys_cursor_height = glyph_row->height;
11301 /* Set phys_cursor_.* before x_draw_.* is called because some
11302 of them may need the information. */
11303 w->phys_cursor.x = x;
11304 w->phys_cursor.y = glyph_row->y;
11305 w->phys_cursor.hpos = hpos;
11306 w->phys_cursor.vpos = vpos;
11307 w->phys_cursor_type = new_cursor_type;
11308 w->phys_cursor_on_p = 1;
11310 switch (new_cursor_type)
11312 case HOLLOW_BOX_CURSOR:
11313 x_draw_hollow_cursor (w, glyph_row);
11314 break;
11316 case FILLED_BOX_CURSOR:
11317 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11318 break;
11320 case BAR_CURSOR:
11321 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11322 break;
11324 case NO_CURSOR:
11325 break;
11327 default:
11328 abort ();
11331 #ifdef HAVE_X_I18N
11332 if (w == XWINDOW (f->selected_window))
11333 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11334 xic_set_preeditarea (w, x, y);
11335 #endif
11338 #ifndef XFlush
11339 if (updating_frame != f)
11340 XFlush (FRAME_X_DISPLAY (f));
11341 #endif
11345 /* Display the cursor on window W, or clear it. X and Y are window
11346 relative pixel coordinates. HPOS and VPOS are glyph matrix
11347 positions. If W is not the selected window, display a hollow
11348 cursor. ON non-zero means display the cursor at X, Y which
11349 correspond to HPOS, VPOS, otherwise it is cleared. */
11351 void
11352 x_display_cursor (w, on, hpos, vpos, x, y)
11353 struct window *w;
11354 int on, hpos, vpos, x, y;
11356 BLOCK_INPUT;
11357 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11358 UNBLOCK_INPUT;
11362 /* Display the cursor on window W, or clear it, according to ON_P.
11363 Don't change the cursor's position. */
11365 void
11366 x_update_cursor (f, on_p)
11367 struct frame *f;
11369 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11373 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11374 in the window tree rooted at W. */
11376 static void
11377 x_update_cursor_in_window_tree (w, on_p)
11378 struct window *w;
11379 int on_p;
11381 while (w)
11383 if (!NILP (w->hchild))
11384 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11385 else if (!NILP (w->vchild))
11386 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11387 else
11388 x_update_window_cursor (w, on_p);
11390 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11395 /* Switch the display of W's cursor on or off, according to the value
11396 of ON. */
11398 static void
11399 x_update_window_cursor (w, on)
11400 struct window *w;
11401 int on;
11403 /* Don't update cursor in windows whose frame is in the process
11404 of being deleted. */
11405 if (w->current_matrix)
11407 BLOCK_INPUT;
11408 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11409 w->phys_cursor.x, w->phys_cursor.y);
11410 UNBLOCK_INPUT;
11417 /* Icons. */
11419 /* Refresh bitmap kitchen sink icon for frame F
11420 when we get an expose event for it. */
11422 void
11423 refreshicon (f)
11424 struct frame *f;
11426 /* Normally, the window manager handles this function. */
11429 /* Make the x-window of frame F use the gnu icon bitmap. */
11432 x_bitmap_icon (f, file)
11433 struct frame *f;
11434 Lisp_Object file;
11436 int bitmap_id;
11438 if (FRAME_X_WINDOW (f) == 0)
11439 return 1;
11441 /* Free up our existing icon bitmap if any. */
11442 if (f->output_data.x->icon_bitmap > 0)
11443 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11444 f->output_data.x->icon_bitmap = 0;
11446 if (STRINGP (file))
11447 bitmap_id = x_create_bitmap_from_file (f, file);
11448 else
11450 /* Create the GNU bitmap if necessary. */
11451 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11452 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11453 = x_create_bitmap_from_data (f, gnu_bits,
11454 gnu_width, gnu_height);
11456 /* The first time we create the GNU bitmap,
11457 this increments the ref-count one extra time.
11458 As a result, the GNU bitmap is never freed.
11459 That way, we don't have to worry about allocating it again. */
11460 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11462 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11465 x_wm_set_icon_pixmap (f, bitmap_id);
11466 f->output_data.x->icon_bitmap = bitmap_id;
11468 return 0;
11472 /* Make the x-window of frame F use a rectangle with text.
11473 Use ICON_NAME as the text. */
11476 x_text_icon (f, icon_name)
11477 struct frame *f;
11478 char *icon_name;
11480 if (FRAME_X_WINDOW (f) == 0)
11481 return 1;
11483 #ifdef HAVE_X11R4
11485 XTextProperty text;
11486 text.value = (unsigned char *) icon_name;
11487 text.encoding = XA_STRING;
11488 text.format = 8;
11489 text.nitems = strlen (icon_name);
11490 #ifdef USE_X_TOOLKIT
11491 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11492 &text);
11493 #else /* not USE_X_TOOLKIT */
11494 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11495 #endif /* not USE_X_TOOLKIT */
11497 #else /* not HAVE_X11R4 */
11498 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11499 #endif /* not HAVE_X11R4 */
11501 if (f->output_data.x->icon_bitmap > 0)
11502 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11503 f->output_data.x->icon_bitmap = 0;
11504 x_wm_set_icon_pixmap (f, 0);
11506 return 0;
11509 #define X_ERROR_MESSAGE_SIZE 200
11511 /* If non-nil, this should be a string.
11512 It means catch X errors and store the error message in this string. */
11514 static Lisp_Object x_error_message_string;
11516 /* An X error handler which stores the error message in
11517 x_error_message_string. This is called from x_error_handler if
11518 x_catch_errors is in effect. */
11520 static void
11521 x_error_catcher (display, error)
11522 Display *display;
11523 XErrorEvent *error;
11525 XGetErrorText (display, error->error_code,
11526 XSTRING (x_error_message_string)->data,
11527 X_ERROR_MESSAGE_SIZE);
11530 /* Begin trapping X errors for display DPY. Actually we trap X errors
11531 for all displays, but DPY should be the display you are actually
11532 operating on.
11534 After calling this function, X protocol errors no longer cause
11535 Emacs to exit; instead, they are recorded in the string
11536 stored in x_error_message_string.
11538 Calling x_check_errors signals an Emacs error if an X error has
11539 occurred since the last call to x_catch_errors or x_check_errors.
11541 Calling x_uncatch_errors resumes the normal error handling. */
11543 void x_check_errors ();
11544 static Lisp_Object x_catch_errors_unwind ();
11547 x_catch_errors (dpy)
11548 Display *dpy;
11550 int count = specpdl_ptr - specpdl;
11552 /* Make sure any errors from previous requests have been dealt with. */
11553 XSync (dpy, False);
11555 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11557 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11558 XSTRING (x_error_message_string)->data[0] = 0;
11560 return count;
11563 /* Unbind the binding that we made to check for X errors. */
11565 static Lisp_Object
11566 x_catch_errors_unwind (old_val)
11567 Lisp_Object old_val;
11569 x_error_message_string = old_val;
11570 return Qnil;
11573 /* If any X protocol errors have arrived since the last call to
11574 x_catch_errors or x_check_errors, signal an Emacs error using
11575 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11577 void
11578 x_check_errors (dpy, format)
11579 Display *dpy;
11580 char *format;
11582 /* Make sure to catch any errors incurred so far. */
11583 XSync (dpy, False);
11585 if (XSTRING (x_error_message_string)->data[0])
11586 error (format, XSTRING (x_error_message_string)->data);
11589 /* Nonzero if we had any X protocol errors
11590 since we did x_catch_errors on DPY. */
11593 x_had_errors_p (dpy)
11594 Display *dpy;
11596 /* Make sure to catch any errors incurred so far. */
11597 XSync (dpy, False);
11599 return XSTRING (x_error_message_string)->data[0] != 0;
11602 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11604 void
11605 x_clear_errors (dpy)
11606 Display *dpy;
11608 XSTRING (x_error_message_string)->data[0] = 0;
11611 /* Stop catching X protocol errors and let them make Emacs die.
11612 DPY should be the display that was passed to x_catch_errors.
11613 COUNT should be the value that was returned by
11614 the corresponding call to x_catch_errors. */
11616 void
11617 x_uncatch_errors (dpy, count)
11618 Display *dpy;
11619 int count;
11621 unbind_to (count, Qnil);
11624 #if 0
11625 static unsigned int x_wire_count;
11626 x_trace_wire ()
11628 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11630 #endif /* ! 0 */
11633 /* Handle SIGPIPE, which can happen when the connection to a server
11634 simply goes away. SIGPIPE is handled by x_connection_signal.
11635 Don't need to do anything, because the write which caused the
11636 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11637 which will do the appropriate cleanup for us. */
11639 static SIGTYPE
11640 x_connection_signal (signalnum) /* If we don't have an argument, */
11641 int signalnum; /* some compilers complain in signal calls. */
11643 #ifdef USG
11644 /* USG systems forget handlers when they are used;
11645 must reestablish each time */
11646 signal (signalnum, x_connection_signal);
11647 #endif /* USG */
11651 /************************************************************************
11652 Handling X errors
11653 ************************************************************************/
11655 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11656 the text of an error message that lead to the connection loss. */
11658 static SIGTYPE
11659 x_connection_closed (dpy, error_message)
11660 Display *dpy;
11661 char *error_message;
11663 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11664 Lisp_Object frame, tail;
11665 int count;
11666 char *msg;
11668 msg = (char *) alloca (strlen (error_message) + 1);
11669 strcpy (msg, error_message);
11670 handling_signal = 0;
11672 /* Prevent being called recursively because of an error condition
11673 below. Otherwise, we might end up with printing ``can't find per
11674 display information'' in the recursive call instead of printing
11675 the original message here. */
11676 count = x_catch_errors (dpy);
11678 /* We have to close the display to inform Xt that it doesn't
11679 exist anymore. If we don't, Xt will continue to wait for
11680 events from the display. As a consequence, a sequence of
11682 M-x make-frame-on-display RET :1 RET
11683 ...kill the new frame, so that we get an IO error...
11684 M-x make-frame-on-display RET :1 RET
11686 will indefinitely wait in Xt for events for display `:1', opened
11687 in the first class to make-frame-on-display.
11689 Closing the display is reported to lead to a bus error on
11690 OpenWindows in certain situations. I suspect that is a bug
11691 in OpenWindows. I don't know how to cicumvent it here. */
11693 #ifdef USE_X_TOOLKIT
11694 /* If DPYINFO is null, this means we didn't open the display
11695 in the first place, so don't try to close it. */
11696 if (dpyinfo)
11697 XtCloseDisplay (dpy);
11698 #endif
11700 /* Indicate that this display is dead. */
11701 if (dpyinfo)
11702 dpyinfo->display = 0;
11704 /* First delete frames whose mini-buffers are on frames
11705 that are on the dead display. */
11706 FOR_EACH_FRAME (tail, frame)
11708 Lisp_Object minibuf_frame;
11709 minibuf_frame
11710 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11711 if (FRAME_X_P (XFRAME (frame))
11712 && FRAME_X_P (XFRAME (minibuf_frame))
11713 && ! EQ (frame, minibuf_frame)
11714 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11715 Fdelete_frame (frame, Qt);
11718 /* Now delete all remaining frames on the dead display.
11719 We are now sure none of these is used as the mini-buffer
11720 for another frame that we need to delete. */
11721 FOR_EACH_FRAME (tail, frame)
11722 if (FRAME_X_P (XFRAME (frame))
11723 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11725 /* Set this to t so that Fdelete_frame won't get confused
11726 trying to find a replacement. */
11727 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11728 Fdelete_frame (frame, Qt);
11731 if (dpyinfo)
11732 x_delete_display (dpyinfo);
11734 x_uncatch_errors (dpy, count);
11736 if (x_display_list == 0)
11738 fprintf (stderr, "%s\n", msg);
11739 shut_down_emacs (0, 0, Qnil);
11740 exit (70);
11743 /* Ordinary stack unwind doesn't deal with these. */
11744 #ifdef SIGIO
11745 sigunblock (sigmask (SIGIO));
11746 #endif
11747 sigunblock (sigmask (SIGALRM));
11748 TOTALLY_UNBLOCK_INPUT;
11750 clear_waiting_for_input ();
11751 error ("%s", msg);
11755 /* This is the usual handler for X protocol errors.
11756 It kills all frames on the display that we got the error for.
11757 If that was the only one, it prints an error message and kills Emacs. */
11759 static void
11760 x_error_quitter (display, error)
11761 Display *display;
11762 XErrorEvent *error;
11764 char buf[256], buf1[356];
11766 /* Note that there is no real way portable across R3/R4 to get the
11767 original error handler. */
11769 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11770 sprintf (buf1, "X protocol error: %s on protocol request %d",
11771 buf, error->request_code);
11772 x_connection_closed (display, buf1);
11776 /* This is the first-level handler for X protocol errors.
11777 It calls x_error_quitter or x_error_catcher. */
11779 static int
11780 x_error_handler (display, error)
11781 Display *display;
11782 XErrorEvent *error;
11784 if (! NILP (x_error_message_string))
11785 x_error_catcher (display, error);
11786 else
11787 x_error_quitter (display, error);
11788 return 0;
11791 /* This is the handler for X IO errors, always.
11792 It kills all frames on the display that we lost touch with.
11793 If that was the only one, it prints an error message and kills Emacs. */
11795 static int
11796 x_io_error_quitter (display)
11797 Display *display;
11799 char buf[256];
11801 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11802 x_connection_closed (display, buf);
11803 return 0;
11806 /* Changing the font of the frame. */
11808 /* Give frame F the font named FONTNAME as its default font, and
11809 return the full name of that font. FONTNAME may be a wildcard
11810 pattern; in that case, we choose some font that fits the pattern.
11811 The return value shows which font we chose. */
11813 Lisp_Object
11814 x_new_font (f, fontname)
11815 struct frame *f;
11816 register char *fontname;
11818 struct font_info *fontp
11819 = FS_LOAD_FONT (f, 0, fontname, -1);
11821 if (!fontp)
11822 return Qnil;
11824 f->output_data.x->font = (XFontStruct *) (fontp->font);
11825 f->output_data.x->baseline_offset = fontp->baseline_offset;
11826 f->output_data.x->fontset = -1;
11828 /* Compute the scroll bar width in character columns. */
11829 if (f->scroll_bar_pixel_width > 0)
11831 int wid = FONT_WIDTH (f->output_data.x->font);
11832 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11834 else
11836 int wid = FONT_WIDTH (f->output_data.x->font);
11837 f->scroll_bar_cols = (14 + wid - 1) / wid;
11840 /* Now make the frame display the given font. */
11841 if (FRAME_X_WINDOW (f) != 0)
11843 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11844 f->output_data.x->font->fid);
11845 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11846 f->output_data.x->font->fid);
11847 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11848 f->output_data.x->font->fid);
11850 frame_update_line_height (f);
11852 /* Don't change the size of a tip frame; there's no point in
11853 doing it because it's done in Fx_show_tip, and it leads to
11854 problems because the tip frame has no widget. */
11855 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11856 x_set_window_size (f, 0, f->width, f->height);
11858 else
11859 /* If we are setting a new frame's font for the first time,
11860 there are no faces yet, so this font's height is the line height. */
11861 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11863 return build_string (fontp->full_name);
11866 /* Give frame F the fontset named FONTSETNAME as its default font, and
11867 return the full name of that fontset. FONTSETNAME may be a wildcard
11868 pattern; in that case, we choose some fontset that fits the pattern.
11869 The return value shows which fontset we chose. */
11871 Lisp_Object
11872 x_new_fontset (f, fontsetname)
11873 struct frame *f;
11874 char *fontsetname;
11876 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11877 Lisp_Object result;
11879 if (fontset < 0)
11880 return Qnil;
11882 if (f->output_data.x->fontset == fontset)
11883 /* This fontset is already set in frame F. There's nothing more
11884 to do. */
11885 return fontset_name (fontset);
11887 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11889 if (!STRINGP (result))
11890 /* Can't load ASCII font. */
11891 return Qnil;
11893 /* Since x_new_font doesn't update any fontset information, do it now. */
11894 f->output_data.x->fontset = fontset;
11896 #ifdef HAVE_X_I18N
11897 if (FRAME_XIC (f)
11898 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11899 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11900 #endif
11902 return build_string (fontsetname);
11906 /***********************************************************************
11907 X Input Methods
11908 ***********************************************************************/
11910 #ifdef HAVE_X_I18N
11912 #ifdef HAVE_X11R6
11914 /* XIM destroy callback function, which is called whenever the
11915 connection to input method XIM dies. CLIENT_DATA contains a
11916 pointer to the x_display_info structure corresponding to XIM. */
11918 static void
11919 xim_destroy_callback (xim, client_data, call_data)
11920 XIM xim;
11921 XPointer client_data;
11922 XPointer call_data;
11924 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11925 Lisp_Object frame, tail;
11927 BLOCK_INPUT;
11929 /* No need to call XDestroyIC.. */
11930 FOR_EACH_FRAME (tail, frame)
11932 struct frame *f = XFRAME (frame);
11933 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11935 FRAME_XIC (f) = NULL;
11936 if (FRAME_XIC_FONTSET (f))
11938 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11939 FRAME_XIC_FONTSET (f) = NULL;
11944 /* No need to call XCloseIM. */
11945 dpyinfo->xim = NULL;
11946 XFree (dpyinfo->xim_styles);
11947 UNBLOCK_INPUT;
11950 #endif /* HAVE_X11R6 */
11952 /* Open the connection to the XIM server on display DPYINFO.
11953 RESOURCE_NAME is the resource name Emacs uses. */
11955 static void
11956 xim_open_dpy (dpyinfo, resource_name)
11957 struct x_display_info *dpyinfo;
11958 char *resource_name;
11960 #ifdef USE_XIM
11961 XIM xim;
11963 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11964 dpyinfo->xim = xim;
11966 if (xim)
11968 #ifdef HAVE_X11R6
11969 XIMCallback destroy;
11970 #endif
11972 /* Get supported styles and XIM values. */
11973 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11975 #ifdef HAVE_X11R6
11976 destroy.callback = xim_destroy_callback;
11977 destroy.client_data = (XPointer)dpyinfo;
11978 /* This isn't prptotyped in OSF 5.0. */
11979 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11980 #endif
11983 #else /* not USE_XIM */
11984 dpyinfo->xim = NULL;
11985 #endif /* not USE_XIM */
11989 #ifdef HAVE_X11R6_XIM
11991 struct xim_inst_t
11993 struct x_display_info *dpyinfo;
11994 char *resource_name;
11997 /* XIM instantiate callback function, which is called whenever an XIM
11998 server is available. DISPLAY is teh display of the XIM.
11999 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12000 when the callback was registered. */
12002 static void
12003 xim_instantiate_callback (display, client_data, call_data)
12004 Display *display;
12005 XPointer client_data;
12006 XPointer call_data;
12008 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12009 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12011 /* We don't support multiple XIM connections. */
12012 if (dpyinfo->xim)
12013 return;
12015 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12017 /* Create XIC for the existing frames on the same display, as long
12018 as they have no XIC. */
12019 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12021 Lisp_Object tail, frame;
12023 BLOCK_INPUT;
12024 FOR_EACH_FRAME (tail, frame)
12026 struct frame *f = XFRAME (frame);
12028 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12029 if (FRAME_XIC (f) == NULL)
12031 create_frame_xic (f);
12032 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12033 xic_set_statusarea (f);
12034 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12036 struct window *w = XWINDOW (f->selected_window);
12037 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12042 UNBLOCK_INPUT;
12046 #endif /* HAVE_X11R6_XIM */
12049 /* Open a connection to the XIM server on display DPYINFO.
12050 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12051 connection only at the first time. On X11R6, open the connection
12052 in the XIM instantiate callback function. */
12054 static void
12055 xim_initialize (dpyinfo, resource_name)
12056 struct x_display_info *dpyinfo;
12057 char *resource_name;
12059 #ifdef USE_XIM
12060 #ifdef HAVE_X11R6_XIM
12061 struct xim_inst_t *xim_inst;
12062 int len;
12064 dpyinfo->xim = NULL;
12065 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12066 xim_inst->dpyinfo = dpyinfo;
12067 len = strlen (resource_name);
12068 xim_inst->resource_name = (char *) xmalloc (len + 1);
12069 bcopy (resource_name, xim_inst->resource_name, len + 1);
12070 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12071 resource_name, EMACS_CLASS,
12072 xim_instantiate_callback,
12073 /* Fixme: This is XPointer in
12074 XFree86 but (XPointer *) on
12075 Tru64, at least. */
12076 (XPointer) xim_inst);
12077 #else /* not HAVE_X11R6_XIM */
12078 dpyinfo->xim = NULL;
12079 xim_open_dpy (dpyinfo, resource_name);
12080 #endif /* not HAVE_X11R6_XIM */
12082 #else /* not USE_XIM */
12083 dpyinfo->xim = NULL;
12084 #endif /* not USE_XIM */
12088 /* Close the connection to the XIM server on display DPYINFO. */
12090 static void
12091 xim_close_dpy (dpyinfo)
12092 struct x_display_info *dpyinfo;
12094 #ifdef USE_XIM
12095 #ifdef HAVE_X11R6_XIM
12096 if (dpyinfo->display)
12097 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12098 NULL, EMACS_CLASS,
12099 xim_instantiate_callback, NULL);
12100 #endif /* not HAVE_X11R6_XIM */
12101 if (dpyinfo->display)
12102 XCloseIM (dpyinfo->xim);
12103 dpyinfo->xim = NULL;
12104 XFree (dpyinfo->xim_styles);
12105 #endif /* USE_XIM */
12108 #endif /* not HAVE_X11R6_XIM */
12112 /* Calculate the absolute position in frame F
12113 from its current recorded position values and gravity. */
12115 void
12116 x_calc_absolute_position (f)
12117 struct frame *f;
12119 Window child;
12120 int win_x = 0, win_y = 0;
12121 int flags = f->output_data.x->size_hint_flags;
12122 int this_window;
12124 /* We have nothing to do if the current position
12125 is already for the top-left corner. */
12126 if (! ((flags & XNegative) || (flags & YNegative)))
12127 return;
12129 #ifdef USE_X_TOOLKIT
12130 this_window = XtWindow (f->output_data.x->widget);
12131 #else
12132 this_window = FRAME_X_WINDOW (f);
12133 #endif
12135 /* Find the position of the outside upper-left corner of
12136 the inner window, with respect to the outer window.
12137 But do this only if we will need the results. */
12138 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12140 int count;
12142 BLOCK_INPUT;
12143 count = x_catch_errors (FRAME_X_DISPLAY (f));
12144 while (1)
12146 x_clear_errors (FRAME_X_DISPLAY (f));
12147 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12149 /* From-window, to-window. */
12150 this_window,
12151 f->output_data.x->parent_desc,
12153 /* From-position, to-position. */
12154 0, 0, &win_x, &win_y,
12156 /* Child of win. */
12157 &child);
12158 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12160 Window newroot, newparent = 0xdeadbeef;
12161 Window *newchildren;
12162 unsigned int nchildren;
12164 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12165 &newparent, &newchildren, &nchildren))
12166 break;
12168 XFree ((char *) newchildren);
12170 f->output_data.x->parent_desc = newparent;
12172 else
12173 break;
12176 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12177 UNBLOCK_INPUT;
12180 /* Treat negative positions as relative to the leftmost bottommost
12181 position that fits on the screen. */
12182 if (flags & XNegative)
12183 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12184 - 2 * f->output_data.x->border_width - win_x
12185 - PIXEL_WIDTH (f)
12186 + f->output_data.x->left_pos);
12189 int height = PIXEL_HEIGHT (f);
12191 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12192 /* Something is fishy here. When using Motif, starting Emacs with
12193 `-g -0-0', the frame appears too low by a few pixels.
12195 This seems to be so because initially, while Emacs is starting,
12196 the column widget's height and the frame's pixel height are
12197 different. The column widget's height is the right one. In
12198 later invocations, when Emacs is up, the frame's pixel height
12199 is right, though.
12201 It's not obvious where the initial small difference comes from.
12202 2000-12-01, gerd. */
12204 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12205 #endif
12207 if (flags & YNegative)
12208 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12209 - 2 * f->output_data.x->border_width
12210 - win_y
12211 - height
12212 + f->output_data.x->top_pos);
12215 /* The left_pos and top_pos
12216 are now relative to the top and left screen edges,
12217 so the flags should correspond. */
12218 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12221 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12222 to really change the position, and 0 when calling from
12223 x_make_frame_visible (in that case, XOFF and YOFF are the current
12224 position values). It is -1 when calling from x_set_frame_parameters,
12225 which means, do adjust for borders but don't change the gravity. */
12227 void
12228 x_set_offset (f, xoff, yoff, change_gravity)
12229 struct frame *f;
12230 register int xoff, yoff;
12231 int change_gravity;
12233 int modified_top, modified_left;
12235 if (change_gravity > 0)
12237 f->output_data.x->top_pos = yoff;
12238 f->output_data.x->left_pos = xoff;
12239 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12240 if (xoff < 0)
12241 f->output_data.x->size_hint_flags |= XNegative;
12242 if (yoff < 0)
12243 f->output_data.x->size_hint_flags |= YNegative;
12244 f->output_data.x->win_gravity = NorthWestGravity;
12246 x_calc_absolute_position (f);
12248 BLOCK_INPUT;
12249 x_wm_set_size_hint (f, (long) 0, 0);
12251 modified_left = f->output_data.x->left_pos;
12252 modified_top = f->output_data.x->top_pos;
12253 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12254 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12255 /* It is a mystery why we need to add the border_width here
12256 when the frame is already visible, but experiment says we do. */
12257 if (change_gravity != 0)
12259 modified_left += f->output_data.x->border_width;
12260 modified_top += f->output_data.x->border_width;
12262 #endif
12264 #ifdef USE_X_TOOLKIT
12265 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12266 modified_left, modified_top);
12267 #else /* not USE_X_TOOLKIT */
12268 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12269 modified_left, modified_top);
12270 #endif /* not USE_X_TOOLKIT */
12271 UNBLOCK_INPUT;
12275 /* Change the size of frame F's X window to COLS/ROWS in the case F
12276 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12277 top-left-corner window gravity for this size change and subsequent
12278 size changes. Otherwise we leave the window gravity unchanged. */
12280 static void
12281 x_set_window_size_1 (f, change_gravity, cols, rows)
12282 struct frame *f;
12283 int change_gravity;
12284 int cols, rows;
12286 int pixelwidth, pixelheight;
12288 check_frame_size (f, &rows, &cols);
12289 f->output_data.x->vertical_scroll_bar_extra
12290 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12292 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12293 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12294 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12295 f->output_data.x->flags_areas_extra
12296 = FRAME_FLAGS_AREA_WIDTH (f);
12297 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12298 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12300 f->output_data.x->win_gravity = NorthWestGravity;
12301 x_wm_set_size_hint (f, (long) 0, 0);
12303 XSync (FRAME_X_DISPLAY (f), False);
12304 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12305 pixelwidth, pixelheight);
12307 /* Now, strictly speaking, we can't be sure that this is accurate,
12308 but the window manager will get around to dealing with the size
12309 change request eventually, and we'll hear how it went when the
12310 ConfigureNotify event gets here.
12312 We could just not bother storing any of this information here,
12313 and let the ConfigureNotify event set everything up, but that
12314 might be kind of confusing to the Lisp code, since size changes
12315 wouldn't be reported in the frame parameters until some random
12316 point in the future when the ConfigureNotify event arrives.
12318 We pass 1 for DELAY since we can't run Lisp code inside of
12319 a BLOCK_INPUT. */
12320 change_frame_size (f, rows, cols, 0, 1, 0);
12321 PIXEL_WIDTH (f) = pixelwidth;
12322 PIXEL_HEIGHT (f) = pixelheight;
12324 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12325 receive in the ConfigureNotify event; if we get what we asked
12326 for, then the event won't cause the screen to become garbaged, so
12327 we have to make sure to do it here. */
12328 SET_FRAME_GARBAGED (f);
12330 XFlush (FRAME_X_DISPLAY (f));
12334 /* Call this to change the size of frame F's x-window.
12335 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12336 for this size change and subsequent size changes.
12337 Otherwise we leave the window gravity unchanged. */
12339 void
12340 x_set_window_size (f, change_gravity, cols, rows)
12341 struct frame *f;
12342 int change_gravity;
12343 int cols, rows;
12345 BLOCK_INPUT;
12347 #ifdef USE_X_TOOLKIT
12349 if (f->output_data.x->widget != NULL)
12351 /* The x and y position of the widget is clobbered by the
12352 call to XtSetValues within EmacsFrameSetCharSize.
12353 This is a real kludge, but I don't understand Xt so I can't
12354 figure out a correct fix. Can anyone else tell me? -- rms. */
12355 int xpos = f->output_data.x->widget->core.x;
12356 int ypos = f->output_data.x->widget->core.y;
12357 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12358 f->output_data.x->widget->core.x = xpos;
12359 f->output_data.x->widget->core.y = ypos;
12361 else
12362 x_set_window_size_1 (f, change_gravity, cols, rows);
12364 #else /* not USE_X_TOOLKIT */
12366 x_set_window_size_1 (f, change_gravity, cols, rows);
12368 #endif /* not USE_X_TOOLKIT */
12370 /* If cursor was outside the new size, mark it as off. */
12371 mark_window_cursors_off (XWINDOW (f->root_window));
12373 /* Clear out any recollection of where the mouse highlighting was,
12374 since it might be in a place that's outside the new frame size.
12375 Actually checking whether it is outside is a pain in the neck,
12376 so don't try--just let the highlighting be done afresh with new size. */
12377 cancel_mouse_face (f);
12379 UNBLOCK_INPUT;
12382 /* Mouse warping. */
12384 void
12385 x_set_mouse_position (f, x, y)
12386 struct frame *f;
12387 int x, y;
12389 int pix_x, pix_y;
12391 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12392 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12394 if (pix_x < 0) pix_x = 0;
12395 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12397 if (pix_y < 0) pix_y = 0;
12398 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12400 BLOCK_INPUT;
12402 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12403 0, 0, 0, 0, pix_x, pix_y);
12404 UNBLOCK_INPUT;
12407 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12409 void
12410 x_set_mouse_pixel_position (f, pix_x, pix_y)
12411 struct frame *f;
12412 int pix_x, pix_y;
12414 BLOCK_INPUT;
12416 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12417 0, 0, 0, 0, pix_x, pix_y);
12418 UNBLOCK_INPUT;
12421 /* focus shifting, raising and lowering. */
12423 void
12424 x_focus_on_frame (f)
12425 struct frame *f;
12427 #if 0 /* This proves to be unpleasant. */
12428 x_raise_frame (f);
12429 #endif
12430 #if 0
12431 /* I don't think that the ICCCM allows programs to do things like this
12432 without the interaction of the window manager. Whatever you end up
12433 doing with this code, do it to x_unfocus_frame too. */
12434 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12435 RevertToPointerRoot, CurrentTime);
12436 #endif /* ! 0 */
12439 void
12440 x_unfocus_frame (f)
12441 struct frame *f;
12443 #if 0
12444 /* Look at the remarks in x_focus_on_frame. */
12445 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12446 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12447 RevertToPointerRoot, CurrentTime);
12448 #endif /* ! 0 */
12451 /* Raise frame F. */
12453 void
12454 x_raise_frame (f)
12455 struct frame *f;
12457 if (f->async_visible)
12459 BLOCK_INPUT;
12460 #ifdef USE_X_TOOLKIT
12461 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12462 #else /* not USE_X_TOOLKIT */
12463 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12464 #endif /* not USE_X_TOOLKIT */
12465 XFlush (FRAME_X_DISPLAY (f));
12466 UNBLOCK_INPUT;
12470 /* Lower frame F. */
12472 void
12473 x_lower_frame (f)
12474 struct frame *f;
12476 if (f->async_visible)
12478 BLOCK_INPUT;
12479 #ifdef USE_X_TOOLKIT
12480 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12481 #else /* not USE_X_TOOLKIT */
12482 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12483 #endif /* not USE_X_TOOLKIT */
12484 XFlush (FRAME_X_DISPLAY (f));
12485 UNBLOCK_INPUT;
12489 static void
12490 XTframe_raise_lower (f, raise_flag)
12491 FRAME_PTR f;
12492 int raise_flag;
12494 if (raise_flag)
12495 x_raise_frame (f);
12496 else
12497 x_lower_frame (f);
12500 /* Change of visibility. */
12502 /* This tries to wait until the frame is really visible.
12503 However, if the window manager asks the user where to position
12504 the frame, this will return before the user finishes doing that.
12505 The frame will not actually be visible at that time,
12506 but it will become visible later when the window manager
12507 finishes with it. */
12509 void
12510 x_make_frame_visible (f)
12511 struct frame *f;
12513 Lisp_Object type;
12514 int original_top, original_left;
12515 int retry_count = 2;
12517 retry:
12519 BLOCK_INPUT;
12521 type = x_icon_type (f);
12522 if (!NILP (type))
12523 x_bitmap_icon (f, type);
12525 if (! FRAME_VISIBLE_P (f))
12527 /* We test FRAME_GARBAGED_P here to make sure we don't
12528 call x_set_offset a second time
12529 if we get to x_make_frame_visible a second time
12530 before the window gets really visible. */
12531 if (! FRAME_ICONIFIED_P (f)
12532 && ! f->output_data.x->asked_for_visible)
12533 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12535 f->output_data.x->asked_for_visible = 1;
12537 if (! EQ (Vx_no_window_manager, Qt))
12538 x_wm_set_window_state (f, NormalState);
12539 #ifdef USE_X_TOOLKIT
12540 /* This was XtPopup, but that did nothing for an iconified frame. */
12541 XtMapWidget (f->output_data.x->widget);
12542 #else /* not USE_X_TOOLKIT */
12543 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12544 #endif /* not USE_X_TOOLKIT */
12545 #if 0 /* This seems to bring back scroll bars in the wrong places
12546 if the window configuration has changed. They seem
12547 to come back ok without this. */
12548 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12549 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12550 #endif
12553 XFlush (FRAME_X_DISPLAY (f));
12555 /* Synchronize to ensure Emacs knows the frame is visible
12556 before we do anything else. We do this loop with input not blocked
12557 so that incoming events are handled. */
12559 Lisp_Object frame;
12560 int count;
12561 /* This must be before UNBLOCK_INPUT
12562 since events that arrive in response to the actions above
12563 will set it when they are handled. */
12564 int previously_visible = f->output_data.x->has_been_visible;
12566 original_left = f->output_data.x->left_pos;
12567 original_top = f->output_data.x->top_pos;
12569 /* This must come after we set COUNT. */
12570 UNBLOCK_INPUT;
12572 /* We unblock here so that arriving X events are processed. */
12574 /* Now move the window back to where it was "supposed to be".
12575 But don't do it if the gravity is negative.
12576 When the gravity is negative, this uses a position
12577 that is 3 pixels too low. Perhaps that's really the border width.
12579 Don't do this if the window has never been visible before,
12580 because the window manager may choose the position
12581 and we don't want to override it. */
12583 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12584 && f->output_data.x->win_gravity == NorthWestGravity
12585 && previously_visible)
12587 Drawable rootw;
12588 int x, y;
12589 unsigned int width, height, border, depth;
12591 BLOCK_INPUT;
12593 /* On some window managers (such as FVWM) moving an existing
12594 window, even to the same place, causes the window manager
12595 to introduce an offset. This can cause the window to move
12596 to an unexpected location. Check the geometry (a little
12597 slow here) and then verify that the window is in the right
12598 place. If the window is not in the right place, move it
12599 there, and take the potential window manager hit. */
12600 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12601 &rootw, &x, &y, &width, &height, &border, &depth);
12603 if (original_left != x || original_top != y)
12604 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12605 original_left, original_top);
12607 UNBLOCK_INPUT;
12610 XSETFRAME (frame, f);
12612 /* Wait until the frame is visible. Process X events until a
12613 MapNotify event has been seen, or until we think we won't get a
12614 MapNotify at all.. */
12615 for (count = input_signal_count + 10;
12616 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12618 /* Force processing of queued events. */
12619 x_sync (f);
12621 /* Machines that do polling rather than SIGIO have been
12622 observed to go into a busy-wait here. So we'll fake an
12623 alarm signal to let the handler know that there's something
12624 to be read. We used to raise a real alarm, but it seems
12625 that the handler isn't always enabled here. This is
12626 probably a bug. */
12627 if (input_polling_used ())
12629 /* It could be confusing if a real alarm arrives while
12630 processing the fake one. Turn it off and let the
12631 handler reset it. */
12632 extern void poll_for_input_1 P_ ((void));
12633 int old_poll_suppress_count = poll_suppress_count;
12634 poll_suppress_count = 1;
12635 poll_for_input_1 ();
12636 poll_suppress_count = old_poll_suppress_count;
12639 /* See if a MapNotify event has been processed. */
12640 FRAME_SAMPLE_VISIBILITY (f);
12643 /* 2000-09-28: In
12645 (let ((f (selected-frame)))
12646 (iconify-frame f)
12647 (raise-frame f))
12649 the frame is not raised with various window managers on
12650 FreeBSD, Linux and Solaris. It turns out that, for some
12651 unknown reason, the call to XtMapWidget is completely ignored.
12652 Mapping the widget a second time works. */
12654 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12655 goto retry;
12659 /* Change from mapped state to withdrawn state. */
12661 /* Make the frame visible (mapped and not iconified). */
12663 void
12664 x_make_frame_invisible (f)
12665 struct frame *f;
12667 Window window;
12669 #ifdef USE_X_TOOLKIT
12670 /* Use the frame's outermost window, not the one we normally draw on. */
12671 window = XtWindow (f->output_data.x->widget);
12672 #else /* not USE_X_TOOLKIT */
12673 window = FRAME_X_WINDOW (f);
12674 #endif /* not USE_X_TOOLKIT */
12676 /* Don't keep the highlight on an invisible frame. */
12677 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12678 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12680 #if 0/* This might add unreliability; I don't trust it -- rms. */
12681 if (! f->async_visible && ! f->async_iconified)
12682 return;
12683 #endif
12685 BLOCK_INPUT;
12687 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12688 that the current position of the window is user-specified, rather than
12689 program-specified, so that when the window is mapped again, it will be
12690 placed at the same location, without forcing the user to position it
12691 by hand again (they have already done that once for this window.) */
12692 x_wm_set_size_hint (f, (long) 0, 1);
12694 #ifdef HAVE_X11R4
12696 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12697 DefaultScreen (FRAME_X_DISPLAY (f))))
12699 UNBLOCK_INPUT_RESIGNAL;
12700 error ("Can't notify window manager of window withdrawal");
12702 #else /* ! defined (HAVE_X11R4) */
12704 /* Tell the window manager what we're going to do. */
12705 if (! EQ (Vx_no_window_manager, Qt))
12707 XEvent unmap;
12709 unmap.xunmap.type = UnmapNotify;
12710 unmap.xunmap.window = window;
12711 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12712 unmap.xunmap.from_configure = False;
12713 if (! XSendEvent (FRAME_X_DISPLAY (f),
12714 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12715 False,
12716 SubstructureRedirectMaskSubstructureNotifyMask,
12717 &unmap))
12719 UNBLOCK_INPUT_RESIGNAL;
12720 error ("Can't notify window manager of withdrawal");
12724 /* Unmap the window ourselves. Cheeky! */
12725 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12726 #endif /* ! defined (HAVE_X11R4) */
12728 /* We can't distinguish this from iconification
12729 just by the event that we get from the server.
12730 So we can't win using the usual strategy of letting
12731 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12732 and synchronize with the server to make sure we agree. */
12733 f->visible = 0;
12734 FRAME_ICONIFIED_P (f) = 0;
12735 f->async_visible = 0;
12736 f->async_iconified = 0;
12738 x_sync (f);
12740 UNBLOCK_INPUT;
12743 /* Change window state from mapped to iconified. */
12745 void
12746 x_iconify_frame (f)
12747 struct frame *f;
12749 int result;
12750 Lisp_Object type;
12752 /* Don't keep the highlight on an invisible frame. */
12753 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12754 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12756 if (f->async_iconified)
12757 return;
12759 BLOCK_INPUT;
12761 FRAME_SAMPLE_VISIBILITY (f);
12763 type = x_icon_type (f);
12764 if (!NILP (type))
12765 x_bitmap_icon (f, type);
12767 #ifdef USE_X_TOOLKIT
12769 if (! FRAME_VISIBLE_P (f))
12771 if (! EQ (Vx_no_window_manager, Qt))
12772 x_wm_set_window_state (f, IconicState);
12773 /* This was XtPopup, but that did nothing for an iconified frame. */
12774 XtMapWidget (f->output_data.x->widget);
12775 /* The server won't give us any event to indicate
12776 that an invisible frame was changed to an icon,
12777 so we have to record it here. */
12778 f->iconified = 1;
12779 f->visible = 1;
12780 f->async_iconified = 1;
12781 f->async_visible = 0;
12782 UNBLOCK_INPUT;
12783 return;
12786 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12787 XtWindow (f->output_data.x->widget),
12788 DefaultScreen (FRAME_X_DISPLAY (f)));
12789 UNBLOCK_INPUT;
12791 if (!result)
12792 error ("Can't notify window manager of iconification");
12794 f->async_iconified = 1;
12795 f->async_visible = 0;
12798 BLOCK_INPUT;
12799 XFlush (FRAME_X_DISPLAY (f));
12800 UNBLOCK_INPUT;
12801 #else /* not USE_X_TOOLKIT */
12803 /* Make sure the X server knows where the window should be positioned,
12804 in case the user deiconifies with the window manager. */
12805 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12806 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12808 /* Since we don't know which revision of X we're running, we'll use both
12809 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12811 /* X11R4: send a ClientMessage to the window manager using the
12812 WM_CHANGE_STATE type. */
12814 XEvent message;
12816 message.xclient.window = FRAME_X_WINDOW (f);
12817 message.xclient.type = ClientMessage;
12818 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12819 message.xclient.format = 32;
12820 message.xclient.data.l[0] = IconicState;
12822 if (! XSendEvent (FRAME_X_DISPLAY (f),
12823 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12824 False,
12825 SubstructureRedirectMask | SubstructureNotifyMask,
12826 &message))
12828 UNBLOCK_INPUT_RESIGNAL;
12829 error ("Can't notify window manager of iconification");
12833 /* X11R3: set the initial_state field of the window manager hints to
12834 IconicState. */
12835 x_wm_set_window_state (f, IconicState);
12837 if (!FRAME_VISIBLE_P (f))
12839 /* If the frame was withdrawn, before, we must map it. */
12840 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12843 f->async_iconified = 1;
12844 f->async_visible = 0;
12846 XFlush (FRAME_X_DISPLAY (f));
12847 UNBLOCK_INPUT;
12848 #endif /* not USE_X_TOOLKIT */
12852 /* Free X resources of frame F. */
12854 void
12855 x_free_frame_resources (f)
12856 struct frame *f;
12858 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12860 BLOCK_INPUT;
12862 /* If a display connection is dead, don't try sending more
12863 commands to the X server. */
12864 if (dpyinfo->display)
12866 if (f->output_data.x->icon_desc)
12867 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12869 #ifdef HAVE_X_I18N
12870 if (FRAME_XIC (f))
12871 free_frame_xic (f);
12872 #endif
12874 if (FRAME_X_WINDOW (f))
12875 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12877 #ifdef USE_X_TOOLKIT
12878 if (f->output_data.x->widget)
12880 XtDestroyWidget (f->output_data.x->widget);
12881 f->output_data.x->widget = NULL;
12883 free_frame_menubar (f);
12884 #endif /* USE_X_TOOLKIT */
12886 unload_color (f, f->output_data.x->foreground_pixel);
12887 unload_color (f, f->output_data.x->background_pixel);
12888 unload_color (f, f->output_data.x->cursor_pixel);
12889 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12890 unload_color (f, f->output_data.x->border_pixel);
12891 unload_color (f, f->output_data.x->mouse_pixel);
12893 if (f->output_data.x->scroll_bar_background_pixel != -1)
12894 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12895 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12896 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12897 if (f->output_data.x->white_relief.allocated_p)
12898 unload_color (f, f->output_data.x->white_relief.pixel);
12899 if (f->output_data.x->black_relief.allocated_p)
12900 unload_color (f, f->output_data.x->black_relief.pixel);
12902 if (FRAME_FACE_CACHE (f))
12903 free_frame_faces (f);
12905 x_free_gcs (f);
12906 XFlush (FRAME_X_DISPLAY (f));
12909 if (f->output_data.x->saved_menu_event)
12910 xfree (f->output_data.x->saved_menu_event);
12912 xfree (f->output_data.x);
12913 f->output_data.x = NULL;
12915 if (f == dpyinfo->x_focus_frame)
12916 dpyinfo->x_focus_frame = 0;
12917 if (f == dpyinfo->x_focus_event_frame)
12918 dpyinfo->x_focus_event_frame = 0;
12919 if (f == dpyinfo->x_highlight_frame)
12920 dpyinfo->x_highlight_frame = 0;
12922 if (f == dpyinfo->mouse_face_mouse_frame)
12924 dpyinfo->mouse_face_beg_row
12925 = dpyinfo->mouse_face_beg_col = -1;
12926 dpyinfo->mouse_face_end_row
12927 = dpyinfo->mouse_face_end_col = -1;
12928 dpyinfo->mouse_face_window = Qnil;
12929 dpyinfo->mouse_face_deferred_gc = 0;
12930 dpyinfo->mouse_face_mouse_frame = 0;
12933 UNBLOCK_INPUT;
12937 /* Destroy the X window of frame F. */
12939 void
12940 x_destroy_window (f)
12941 struct frame *f;
12943 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12945 /* If a display connection is dead, don't try sending more
12946 commands to the X server. */
12947 if (dpyinfo->display != 0)
12948 x_free_frame_resources (f);
12950 dpyinfo->reference_count--;
12954 /* Setting window manager hints. */
12956 /* Set the normal size hints for the window manager, for frame F.
12957 FLAGS is the flags word to use--or 0 meaning preserve the flags
12958 that the window now has.
12959 If USER_POSITION is nonzero, we set the USPosition
12960 flag (this is useful when FLAGS is 0). */
12962 void
12963 x_wm_set_size_hint (f, flags, user_position)
12964 struct frame *f;
12965 long flags;
12966 int user_position;
12968 XSizeHints size_hints;
12970 #ifdef USE_X_TOOLKIT
12971 Arg al[2];
12972 int ac = 0;
12973 Dimension widget_width, widget_height;
12974 Window window = XtWindow (f->output_data.x->widget);
12975 #else /* not USE_X_TOOLKIT */
12976 Window window = FRAME_X_WINDOW (f);
12977 #endif /* not USE_X_TOOLKIT */
12979 /* Setting PMaxSize caused various problems. */
12980 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12982 size_hints.x = f->output_data.x->left_pos;
12983 size_hints.y = f->output_data.x->top_pos;
12985 #ifdef USE_X_TOOLKIT
12986 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12987 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12988 XtGetValues (f->output_data.x->widget, al, ac);
12989 size_hints.height = widget_height;
12990 size_hints.width = widget_width;
12991 #else /* not USE_X_TOOLKIT */
12992 size_hints.height = PIXEL_HEIGHT (f);
12993 size_hints.width = PIXEL_WIDTH (f);
12994 #endif /* not USE_X_TOOLKIT */
12996 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12997 size_hints.height_inc = f->output_data.x->line_height;
12998 size_hints.max_width
12999 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13000 size_hints.max_height
13001 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13003 /* Calculate the base and minimum sizes.
13005 (When we use the X toolkit, we don't do it here.
13006 Instead we copy the values that the widgets are using, below.) */
13007 #ifndef USE_X_TOOLKIT
13009 int base_width, base_height;
13010 int min_rows = 0, min_cols = 0;
13012 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13013 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13015 check_frame_size (f, &min_rows, &min_cols);
13017 /* The window manager uses the base width hints to calculate the
13018 current number of rows and columns in the frame while
13019 resizing; min_width and min_height aren't useful for this
13020 purpose, since they might not give the dimensions for a
13021 zero-row, zero-column frame.
13023 We use the base_width and base_height members if we have
13024 them; otherwise, we set the min_width and min_height members
13025 to the size for a zero x zero frame. */
13027 #ifdef HAVE_X11R4
13028 size_hints.flags |= PBaseSize;
13029 size_hints.base_width = base_width;
13030 size_hints.base_height = base_height;
13031 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13032 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13033 #else
13034 size_hints.min_width = base_width;
13035 size_hints.min_height = base_height;
13036 #endif
13039 /* If we don't need the old flags, we don't need the old hint at all. */
13040 if (flags)
13042 size_hints.flags |= flags;
13043 goto no_read;
13045 #endif /* not USE_X_TOOLKIT */
13048 XSizeHints hints; /* Sometimes I hate X Windows... */
13049 long supplied_return;
13050 int value;
13052 #ifdef HAVE_X11R4
13053 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13054 &supplied_return);
13055 #else
13056 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13057 #endif
13059 #ifdef USE_X_TOOLKIT
13060 size_hints.base_height = hints.base_height;
13061 size_hints.base_width = hints.base_width;
13062 size_hints.min_height = hints.min_height;
13063 size_hints.min_width = hints.min_width;
13064 #endif
13066 if (flags)
13067 size_hints.flags |= flags;
13068 else
13070 if (value == 0)
13071 hints.flags = 0;
13072 if (hints.flags & PSize)
13073 size_hints.flags |= PSize;
13074 if (hints.flags & PPosition)
13075 size_hints.flags |= PPosition;
13076 if (hints.flags & USPosition)
13077 size_hints.flags |= USPosition;
13078 if (hints.flags & USSize)
13079 size_hints.flags |= USSize;
13083 #ifndef USE_X_TOOLKIT
13084 no_read:
13085 #endif
13087 #ifdef PWinGravity
13088 size_hints.win_gravity = f->output_data.x->win_gravity;
13089 size_hints.flags |= PWinGravity;
13091 if (user_position)
13093 size_hints.flags &= ~ PPosition;
13094 size_hints.flags |= USPosition;
13096 #endif /* PWinGravity */
13098 #ifdef HAVE_X11R4
13099 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13100 #else
13101 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13102 #endif
13105 /* Used for IconicState or NormalState */
13107 void
13108 x_wm_set_window_state (f, state)
13109 struct frame *f;
13110 int state;
13112 #ifdef USE_X_TOOLKIT
13113 Arg al[1];
13115 XtSetArg (al[0], XtNinitialState, state);
13116 XtSetValues (f->output_data.x->widget, al, 1);
13117 #else /* not USE_X_TOOLKIT */
13118 Window window = FRAME_X_WINDOW (f);
13120 f->output_data.x->wm_hints.flags |= StateHint;
13121 f->output_data.x->wm_hints.initial_state = state;
13123 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13124 #endif /* not USE_X_TOOLKIT */
13127 void
13128 x_wm_set_icon_pixmap (f, pixmap_id)
13129 struct frame *f;
13130 int pixmap_id;
13132 Pixmap icon_pixmap;
13134 #ifndef USE_X_TOOLKIT
13135 Window window = FRAME_X_WINDOW (f);
13136 #endif
13138 if (pixmap_id > 0)
13140 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13141 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13143 else
13145 /* It seems there is no way to turn off use of an icon pixmap.
13146 The following line does it, only if no icon has yet been created,
13147 for some window managers. But with mwm it crashes.
13148 Some people say it should clear the IconPixmapHint bit in this case,
13149 but that doesn't work, and the X consortium said it isn't the
13150 right thing at all. Since there is no way to win,
13151 best to explicitly give up. */
13152 #if 0
13153 f->output_data.x->wm_hints.icon_pixmap = None;
13154 #else
13155 return;
13156 #endif
13159 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13162 Arg al[1];
13163 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13164 XtSetValues (f->output_data.x->widget, al, 1);
13167 #else /* not USE_X_TOOLKIT */
13169 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13170 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13172 #endif /* not USE_X_TOOLKIT */
13175 void
13176 x_wm_set_icon_position (f, icon_x, icon_y)
13177 struct frame *f;
13178 int icon_x, icon_y;
13180 #ifdef USE_X_TOOLKIT
13181 Window window = XtWindow (f->output_data.x->widget);
13182 #else
13183 Window window = FRAME_X_WINDOW (f);
13184 #endif
13186 f->output_data.x->wm_hints.flags |= IconPositionHint;
13187 f->output_data.x->wm_hints.icon_x = icon_x;
13188 f->output_data.x->wm_hints.icon_y = icon_y;
13190 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13194 /***********************************************************************
13195 Fonts
13196 ***********************************************************************/
13198 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13200 struct font_info *
13201 x_get_font_info (f, font_idx)
13202 FRAME_PTR f;
13203 int font_idx;
13205 return (FRAME_X_FONT_TABLE (f) + font_idx);
13209 /* Return a list of names of available fonts matching PATTERN on frame F.
13211 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13212 to be listed.
13214 SIZE < 0 means include scalable fonts.
13216 Frame F null means we have not yet created any frame on X, and
13217 consult the first display in x_display_list. MAXNAMES sets a limit
13218 on how many fonts to match. */
13220 Lisp_Object
13221 x_list_fonts (f, pattern, size, maxnames)
13222 struct frame *f;
13223 Lisp_Object pattern;
13224 int size;
13225 int maxnames;
13227 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13228 Lisp_Object tem, second_best;
13229 struct x_display_info *dpyinfo
13230 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13231 Display *dpy = dpyinfo->display;
13232 int try_XLoadQueryFont = 0;
13233 int count;
13234 int allow_scalable_fonts_p = 0;
13236 if (size < 0)
13238 allow_scalable_fonts_p = 1;
13239 size = 0;
13242 patterns = Fassoc (pattern, Valternate_fontname_alist);
13243 if (NILP (patterns))
13244 patterns = Fcons (pattern, Qnil);
13246 if (maxnames == 1 && !size)
13247 /* We can return any single font matching PATTERN. */
13248 try_XLoadQueryFont = 1;
13250 for (; CONSP (patterns); patterns = XCDR (patterns))
13252 int num_fonts;
13253 char **names = NULL;
13255 pattern = XCAR (patterns);
13256 /* See if we cached the result for this particular query.
13257 The cache is an alist of the form:
13258 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13259 tem = XCDR (dpyinfo->name_list_element);
13260 key = Fcons (Fcons (pattern, make_number (maxnames)),
13261 allow_scalable_fonts_p ? Qt : Qnil);
13262 list = Fassoc (key, tem);
13263 if (!NILP (list))
13265 list = Fcdr_safe (list);
13266 /* We have a cashed list. Don't have to get the list again. */
13267 goto label_cached;
13270 /* At first, put PATTERN in the cache. */
13272 BLOCK_INPUT;
13273 count = x_catch_errors (dpy);
13275 if (try_XLoadQueryFont)
13277 XFontStruct *font;
13278 unsigned long value;
13280 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13281 if (x_had_errors_p (dpy))
13283 /* This error is perhaps due to insufficient memory on X
13284 server. Let's just ignore it. */
13285 font = NULL;
13286 x_clear_errors (dpy);
13289 if (font
13290 && XGetFontProperty (font, XA_FONT, &value))
13292 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13293 int len = strlen (name);
13294 char *tmp;
13296 /* If DXPC (a Differential X Protocol Compressor)
13297 Ver.3.7 is running, XGetAtomName will return null
13298 string. We must avoid such a name. */
13299 if (len == 0)
13300 try_XLoadQueryFont = 0;
13301 else
13303 num_fonts = 1;
13304 names = (char **) alloca (sizeof (char *));
13305 /* Some systems only allow alloca assigned to a
13306 simple var. */
13307 tmp = (char *) alloca (len + 1); names[0] = tmp;
13308 bcopy (name, names[0], len + 1);
13309 XFree (name);
13312 else
13313 try_XLoadQueryFont = 0;
13315 if (font)
13316 XFreeFont (dpy, font);
13319 if (!try_XLoadQueryFont)
13321 /* We try at least 10 fonts because XListFonts will return
13322 auto-scaled fonts at the head. */
13323 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13324 &num_fonts);
13325 if (x_had_errors_p (dpy))
13327 /* This error is perhaps due to insufficient memory on X
13328 server. Let's just ignore it. */
13329 names = NULL;
13330 x_clear_errors (dpy);
13334 x_uncatch_errors (dpy, count);
13335 UNBLOCK_INPUT;
13337 if (names)
13339 int i;
13341 /* Make a list of all the fonts we got back.
13342 Store that in the font cache for the display. */
13343 for (i = 0; i < num_fonts; i++)
13345 int width = 0;
13346 char *p = names[i];
13347 int average_width = -1, dashes = 0;
13349 /* Count the number of dashes in NAMES[I]. If there are
13350 14 dashes, and the field value following 12th dash
13351 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13352 is usually too ugly to be used for editing. Let's
13353 ignore it. */
13354 while (*p)
13355 if (*p++ == '-')
13357 dashes++;
13358 if (dashes == 7) /* PIXEL_SIZE field */
13359 width = atoi (p);
13360 else if (dashes == 12) /* AVERAGE_WIDTH field */
13361 average_width = atoi (p);
13364 if (allow_scalable_fonts_p
13365 || dashes < 14 || average_width != 0)
13367 tem = build_string (names[i]);
13368 if (NILP (Fassoc (tem, list)))
13370 if (STRINGP (Vx_pixel_size_width_font_regexp)
13371 && ((fast_c_string_match_ignore_case
13372 (Vx_pixel_size_width_font_regexp, names[i]))
13373 >= 0))
13374 /* We can set the value of PIXEL_SIZE to the
13375 width of this font. */
13376 list = Fcons (Fcons (tem, make_number (width)), list);
13377 else
13378 /* For the moment, width is not known. */
13379 list = Fcons (Fcons (tem, Qnil), list);
13383 if (!try_XLoadQueryFont)
13384 XFreeFontNames (names);
13387 /* Now store the result in the cache. */
13388 XCDR (dpyinfo->name_list_element)
13389 = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
13391 label_cached:
13392 if (NILP (list)) continue; /* Try the remaining alternatives. */
13394 newlist = second_best = Qnil;
13395 /* Make a list of the fonts that have the right width. */
13396 for (; CONSP (list); list = XCDR (list))
13398 int found_size;
13400 tem = XCAR (list);
13402 if (!CONSP (tem) || NILP (XCAR (tem)))
13403 continue;
13404 if (!size)
13406 newlist = Fcons (XCAR (tem), newlist);
13407 continue;
13410 if (!INTEGERP (XCDR (tem)))
13412 /* Since we have not yet known the size of this font, we
13413 must try slow function call XLoadQueryFont. */
13414 XFontStruct *thisinfo;
13416 BLOCK_INPUT;
13417 count = x_catch_errors (dpy);
13418 thisinfo = XLoadQueryFont (dpy,
13419 XSTRING (XCAR (tem))->data);
13420 if (x_had_errors_p (dpy))
13422 /* This error is perhaps due to insufficient memory on X
13423 server. Let's just ignore it. */
13424 thisinfo = NULL;
13425 x_clear_errors (dpy);
13427 x_uncatch_errors (dpy, count);
13428 UNBLOCK_INPUT;
13430 if (thisinfo)
13432 XCDR (tem)
13433 = (thisinfo->min_bounds.width == 0
13434 ? make_number (0)
13435 : make_number (thisinfo->max_bounds.width));
13436 XFreeFont (dpy, thisinfo);
13438 else
13439 /* For unknown reason, the previous call of XListFont had
13440 returned a font which can't be opened. Record the size
13441 as 0 not to try to open it again. */
13442 XCDR (tem) = make_number (0);
13445 found_size = XINT (XCDR (tem));
13446 if (found_size == size)
13447 newlist = Fcons (XCAR (tem), newlist);
13448 else if (found_size > 0)
13450 if (NILP (second_best))
13451 second_best = tem;
13452 else if (found_size < size)
13454 if (XINT (XCDR (second_best)) > size
13455 || XINT (XCDR (second_best)) < found_size)
13456 second_best = tem;
13458 else
13460 if (XINT (XCDR (second_best)) > size
13461 && XINT (XCDR (second_best)) > found_size)
13462 second_best = tem;
13466 if (!NILP (newlist))
13467 break;
13468 else if (!NILP (second_best))
13470 newlist = Fcons (XCAR (second_best), Qnil);
13471 break;
13475 return newlist;
13479 #if GLYPH_DEBUG
13481 /* Check that FONT is valid on frame F. It is if it can be found in F's
13482 font table. */
13484 static void
13485 x_check_font (f, font)
13486 struct frame *f;
13487 XFontStruct *font;
13489 int i;
13490 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13492 xassert (font != NULL);
13494 for (i = 0; i < dpyinfo->n_fonts; i++)
13495 if (dpyinfo->font_table[i].name
13496 && font == dpyinfo->font_table[i].font)
13497 break;
13499 xassert (i < dpyinfo->n_fonts);
13502 #endif /* GLYPH_DEBUG != 0 */
13504 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13505 Note: There are (broken) X fonts out there with invalid XFontStruct
13506 min_bounds contents. For example, handa@etl.go.jp reports that
13507 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13508 have font->min_bounds.width == 0. */
13510 static INLINE void
13511 x_font_min_bounds (font, w, h)
13512 XFontStruct *font;
13513 int *w, *h;
13515 *h = FONT_HEIGHT (font);
13516 *w = font->min_bounds.width;
13518 /* Try to handle the case where FONT->min_bounds has invalid
13519 contents. Since the only font known to have invalid min_bounds
13520 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13521 if (*w <= 0)
13522 *w = font->max_bounds.width;
13526 /* Compute the smallest character width and smallest font height over
13527 all fonts available on frame F. Set the members smallest_char_width
13528 and smallest_font_height in F's x_display_info structure to
13529 the values computed. Value is non-zero if smallest_font_height or
13530 smallest_char_width become smaller than they were before. */
13532 static int
13533 x_compute_min_glyph_bounds (f)
13534 struct frame *f;
13536 int i;
13537 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13538 XFontStruct *font;
13539 int old_width = dpyinfo->smallest_char_width;
13540 int old_height = dpyinfo->smallest_font_height;
13542 dpyinfo->smallest_font_height = 100000;
13543 dpyinfo->smallest_char_width = 100000;
13545 for (i = 0; i < dpyinfo->n_fonts; ++i)
13546 if (dpyinfo->font_table[i].name)
13548 struct font_info *fontp = dpyinfo->font_table + i;
13549 int w, h;
13551 font = (XFontStruct *) fontp->font;
13552 xassert (font != (XFontStruct *) ~0);
13553 x_font_min_bounds (font, &w, &h);
13555 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13556 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13559 xassert (dpyinfo->smallest_char_width > 0
13560 && dpyinfo->smallest_font_height > 0);
13562 return (dpyinfo->n_fonts == 1
13563 || dpyinfo->smallest_char_width < old_width
13564 || dpyinfo->smallest_font_height < old_height);
13568 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13569 pointer to the structure font_info while allocating it dynamically.
13570 If SIZE is 0, load any size of font.
13571 If loading is failed, return NULL. */
13573 struct font_info *
13574 x_load_font (f, fontname, size)
13575 struct frame *f;
13576 register char *fontname;
13577 int size;
13579 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13580 Lisp_Object font_names;
13581 int count;
13583 /* Get a list of all the fonts that match this name. Once we
13584 have a list of matching fonts, we compare them against the fonts
13585 we already have by comparing names. */
13586 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13588 if (!NILP (font_names))
13590 Lisp_Object tail;
13591 int i;
13593 for (i = 0; i < dpyinfo->n_fonts; i++)
13594 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13595 if (dpyinfo->font_table[i].name
13596 && (!strcmp (dpyinfo->font_table[i].name,
13597 XSTRING (XCAR (tail))->data)
13598 || !strcmp (dpyinfo->font_table[i].full_name,
13599 XSTRING (XCAR (tail))->data)))
13600 return (dpyinfo->font_table + i);
13603 /* Load the font and add it to the table. */
13605 char *full_name;
13606 XFontStruct *font;
13607 struct font_info *fontp;
13608 unsigned long value;
13609 int i;
13611 /* If we have found fonts by x_list_font, load one of them. If
13612 not, we still try to load a font by the name given as FONTNAME
13613 because XListFonts (called in x_list_font) of some X server has
13614 a bug of not finding a font even if the font surely exists and
13615 is loadable by XLoadQueryFont. */
13616 if (size > 0 && !NILP (font_names))
13617 fontname = (char *) XSTRING (XCAR (font_names))->data;
13619 BLOCK_INPUT;
13620 count = x_catch_errors (FRAME_X_DISPLAY (f));
13621 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13622 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13624 /* This error is perhaps due to insufficient memory on X
13625 server. Let's just ignore it. */
13626 font = NULL;
13627 x_clear_errors (FRAME_X_DISPLAY (f));
13629 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13630 UNBLOCK_INPUT;
13631 if (!font)
13632 return NULL;
13634 /* Find a free slot in the font table. */
13635 for (i = 0; i < dpyinfo->n_fonts; ++i)
13636 if (dpyinfo->font_table[i].name == NULL)
13637 break;
13639 /* If no free slot found, maybe enlarge the font table. */
13640 if (i == dpyinfo->n_fonts
13641 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13643 int sz;
13644 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13645 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13646 dpyinfo->font_table
13647 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13650 fontp = dpyinfo->font_table + i;
13651 if (i == dpyinfo->n_fonts)
13652 ++dpyinfo->n_fonts;
13654 /* Now fill in the slots of *FONTP. */
13655 BLOCK_INPUT;
13656 fontp->font = font;
13657 fontp->font_idx = i;
13658 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13659 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13661 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13662 full_name = 0;
13663 if (XGetFontProperty (font, XA_FONT, &value))
13665 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13666 char *p = name;
13667 int dashes = 0;
13669 /* Count the number of dashes in the "full name".
13670 If it is too few, this isn't really the font's full name,
13671 so don't use it.
13672 In X11R4, the fonts did not come with their canonical names
13673 stored in them. */
13674 while (*p)
13676 if (*p == '-')
13677 dashes++;
13678 p++;
13681 if (dashes >= 13)
13683 full_name = (char *) xmalloc (p - name + 1);
13684 bcopy (name, full_name, p - name + 1);
13687 XFree (name);
13690 if (full_name != 0)
13691 fontp->full_name = full_name;
13692 else
13693 fontp->full_name = fontp->name;
13695 fontp->size = font->max_bounds.width;
13696 fontp->height = FONT_HEIGHT (font);
13698 if (NILP (font_names))
13700 /* We come here because of a bug of XListFonts mentioned at
13701 the head of this block. Let's store this information in
13702 the cache for x_list_fonts. */
13703 Lisp_Object lispy_name = build_string (fontname);
13704 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13705 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13706 Qnil);
13708 XCDR (dpyinfo->name_list_element)
13709 = Fcons (Fcons (key,
13710 Fcons (Fcons (lispy_full_name,
13711 make_number (fontp->size)),
13712 Qnil)),
13713 XCDR (dpyinfo->name_list_element));
13714 if (full_name)
13716 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13717 Qnil);
13718 XCDR (dpyinfo->name_list_element)
13719 = Fcons (Fcons (key,
13720 Fcons (Fcons (lispy_full_name,
13721 make_number (fontp->size)),
13722 Qnil)),
13723 XCDR (dpyinfo->name_list_element));
13727 /* The slot `encoding' specifies how to map a character
13728 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13729 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13730 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13731 2:0xA020..0xFF7F). For the moment, we don't know which charset
13732 uses this font. So, we set information in fontp->encoding[1]
13733 which is never used by any charset. If mapping can't be
13734 decided, set FONT_ENCODING_NOT_DECIDED. */
13735 fontp->encoding[1]
13736 = (font->max_byte1 == 0
13737 /* 1-byte font */
13738 ? (font->min_char_or_byte2 < 0x80
13739 ? (font->max_char_or_byte2 < 0x80
13740 ? 0 /* 0x20..0x7F */
13741 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13742 : 1) /* 0xA0..0xFF */
13743 /* 2-byte font */
13744 : (font->min_byte1 < 0x80
13745 ? (font->max_byte1 < 0x80
13746 ? (font->min_char_or_byte2 < 0x80
13747 ? (font->max_char_or_byte2 < 0x80
13748 ? 0 /* 0x2020..0x7F7F */
13749 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13750 : 3) /* 0x20A0..0x7FFF */
13751 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13752 : (font->min_char_or_byte2 < 0x80
13753 ? (font->max_char_or_byte2 < 0x80
13754 ? 2 /* 0xA020..0xFF7F */
13755 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13756 : 1))); /* 0xA0A0..0xFFFF */
13758 fontp->baseline_offset
13759 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13760 ? (long) value : 0);
13761 fontp->relative_compose
13762 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13763 ? (long) value : 0);
13764 fontp->default_ascent
13765 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13766 ? (long) value : 0);
13768 /* Set global flag fonts_changed_p to non-zero if the font loaded
13769 has a character with a smaller width than any other character
13770 before, or if the font loaded has a smalle>r height than any
13771 other font loaded before. If this happens, it will make a
13772 glyph matrix reallocation necessary. */
13773 fonts_changed_p = x_compute_min_glyph_bounds (f);
13774 UNBLOCK_INPUT;
13775 return fontp;
13780 /* Return a pointer to struct font_info of a font named FONTNAME for
13781 frame F. If no such font is loaded, return NULL. */
13783 struct font_info *
13784 x_query_font (f, fontname)
13785 struct frame *f;
13786 register char *fontname;
13788 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13789 int i;
13791 for (i = 0; i < dpyinfo->n_fonts; i++)
13792 if (dpyinfo->font_table[i].name
13793 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13794 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13795 return (dpyinfo->font_table + i);
13796 return NULL;
13800 /* Find a CCL program for a font specified by FONTP, and set the member
13801 `encoder' of the structure. */
13803 void
13804 x_find_ccl_program (fontp)
13805 struct font_info *fontp;
13807 Lisp_Object list, elt;
13809 elt = Qnil;
13810 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13812 elt = XCAR (list);
13813 if (CONSP (elt)
13814 && STRINGP (XCAR (elt))
13815 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13816 >= 0)
13817 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13818 >= 0)))
13819 break;
13822 if (! NILP (list))
13824 struct ccl_program *ccl
13825 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13827 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13828 xfree (ccl);
13829 else
13830 fontp->font_encoder = ccl;
13836 /***********************************************************************
13837 Initialization
13838 ***********************************************************************/
13840 #ifdef USE_X_TOOLKIT
13841 static XrmOptionDescRec emacs_options[] = {
13842 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13843 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13845 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13846 XrmoptionSepArg, NULL},
13847 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13849 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13850 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13851 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13852 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13853 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13854 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13855 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13857 #endif /* USE_X_TOOLKIT */
13859 static int x_initialized;
13861 #ifdef MULTI_KBOARD
13862 /* Test whether two display-name strings agree up to the dot that separates
13863 the screen number from the server number. */
13864 static int
13865 same_x_server (name1, name2)
13866 char *name1, *name2;
13868 int seen_colon = 0;
13869 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13870 int system_name_length = strlen (system_name);
13871 int length_until_period = 0;
13873 while (system_name[length_until_period] != 0
13874 && system_name[length_until_period] != '.')
13875 length_until_period++;
13877 /* Treat `unix' like an empty host name. */
13878 if (! strncmp (name1, "unix:", 5))
13879 name1 += 4;
13880 if (! strncmp (name2, "unix:", 5))
13881 name2 += 4;
13882 /* Treat this host's name like an empty host name. */
13883 if (! strncmp (name1, system_name, system_name_length)
13884 && name1[system_name_length] == ':')
13885 name1 += system_name_length;
13886 if (! strncmp (name2, system_name, system_name_length)
13887 && name2[system_name_length] == ':')
13888 name2 += system_name_length;
13889 /* Treat this host's domainless name like an empty host name. */
13890 if (! strncmp (name1, system_name, length_until_period)
13891 && name1[length_until_period] == ':')
13892 name1 += length_until_period;
13893 if (! strncmp (name2, system_name, length_until_period)
13894 && name2[length_until_period] == ':')
13895 name2 += length_until_period;
13897 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13899 if (*name1 == ':')
13900 seen_colon++;
13901 if (seen_colon && *name1 == '.')
13902 return 1;
13904 return (seen_colon
13905 && (*name1 == '.' || *name1 == '\0')
13906 && (*name2 == '.' || *name2 == '\0'));
13908 #endif
13910 struct x_display_info *
13911 x_term_init (display_name, xrm_option, resource_name)
13912 Lisp_Object display_name;
13913 char *xrm_option;
13914 char *resource_name;
13916 int connection;
13917 Display *dpy;
13918 struct x_display_info *dpyinfo;
13919 XrmDatabase xrdb;
13921 BLOCK_INPUT;
13923 if (!x_initialized)
13925 x_initialize ();
13926 x_initialized = 1;
13929 #ifdef USE_X_TOOLKIT
13930 /* weiner@footloose.sps.mot.com reports that this causes
13931 errors with X11R5:
13932 X protocol error: BadAtom (invalid Atom parameter)
13933 on protocol request 18skiloaf.
13934 So let's not use it until R6. */
13935 #ifdef HAVE_X11XTR6
13936 XtSetLanguageProc (NULL, NULL, NULL);
13937 #endif
13940 int argc = 0;
13941 char *argv[3];
13943 argv[0] = "";
13944 argc = 1;
13945 if (xrm_option)
13947 argv[argc++] = "-xrm";
13948 argv[argc++] = xrm_option;
13950 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13951 resource_name, EMACS_CLASS,
13952 emacs_options, XtNumber (emacs_options),
13953 &argc, argv);
13955 #ifdef HAVE_X11XTR6
13956 /* I think this is to compensate for XtSetLanguageProc. */
13957 fixup_locale ();
13958 #endif
13961 #else /* not USE_X_TOOLKIT */
13962 #ifdef HAVE_X11R5
13963 XSetLocaleModifiers ("");
13964 #endif
13965 dpy = XOpenDisplay (XSTRING (display_name)->data);
13966 #endif /* not USE_X_TOOLKIT */
13968 /* Detect failure. */
13969 if (dpy == 0)
13971 UNBLOCK_INPUT;
13972 return 0;
13975 /* We have definitely succeeded. Record the new connection. */
13977 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13978 bzero (dpyinfo, sizeof *dpyinfo);
13980 #ifdef MULTI_KBOARD
13982 struct x_display_info *share;
13983 Lisp_Object tail;
13985 for (share = x_display_list, tail = x_display_name_list; share;
13986 share = share->next, tail = XCDR (tail))
13987 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13988 XSTRING (display_name)->data))
13989 break;
13990 if (share)
13991 dpyinfo->kboard = share->kboard;
13992 else
13994 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13995 init_kboard (dpyinfo->kboard);
13996 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13998 char *vendor = ServerVendor (dpy);
13999 UNBLOCK_INPUT;
14000 dpyinfo->kboard->Vsystem_key_alist
14001 = call1 (Qvendor_specific_keysyms,
14002 build_string (vendor ? vendor : ""));
14003 BLOCK_INPUT;
14006 dpyinfo->kboard->next_kboard = all_kboards;
14007 all_kboards = dpyinfo->kboard;
14008 /* Don't let the initial kboard remain current longer than necessary.
14009 That would cause problems if a file loaded on startup tries to
14010 prompt in the mini-buffer. */
14011 if (current_kboard == initial_kboard)
14012 current_kboard = dpyinfo->kboard;
14014 dpyinfo->kboard->reference_count++;
14016 #endif
14018 /* Put this display on the chain. */
14019 dpyinfo->next = x_display_list;
14020 x_display_list = dpyinfo;
14022 /* Put it on x_display_name_list as well, to keep them parallel. */
14023 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14024 x_display_name_list);
14025 dpyinfo->name_list_element = XCAR (x_display_name_list);
14027 dpyinfo->display = dpy;
14029 #if 0
14030 XSetAfterFunction (x_current_display, x_trace_wire);
14031 #endif /* ! 0 */
14033 dpyinfo->x_id_name
14034 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14035 + STRING_BYTES (XSTRING (Vsystem_name))
14036 + 2);
14037 sprintf (dpyinfo->x_id_name, "%s@%s",
14038 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
14040 /* Figure out which modifier bits mean what. */
14041 x_find_modifier_meanings (dpyinfo);
14043 /* Get the scroll bar cursor. */
14044 dpyinfo->vertical_scroll_bar_cursor
14045 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14047 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14048 resource_name, EMACS_CLASS);
14049 #ifdef HAVE_XRMSETDATABASE
14050 XrmSetDatabase (dpyinfo->display, xrdb);
14051 #else
14052 dpyinfo->display->db = xrdb;
14053 #endif
14054 /* Put the rdb where we can find it in a way that works on
14055 all versions. */
14056 dpyinfo->xrdb = xrdb;
14058 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14059 DefaultScreen (dpyinfo->display));
14060 select_visual (dpyinfo);
14061 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14062 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14063 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14064 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14065 dpyinfo->grabbed = 0;
14066 dpyinfo->reference_count = 0;
14067 dpyinfo->icon_bitmap_id = -1;
14068 dpyinfo->font_table = NULL;
14069 dpyinfo->n_fonts = 0;
14070 dpyinfo->font_table_size = 0;
14071 dpyinfo->bitmaps = 0;
14072 dpyinfo->bitmaps_size = 0;
14073 dpyinfo->bitmaps_last = 0;
14074 dpyinfo->scratch_cursor_gc = 0;
14075 dpyinfo->mouse_face_mouse_frame = 0;
14076 dpyinfo->mouse_face_deferred_gc = 0;
14077 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14078 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14079 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14080 dpyinfo->mouse_face_window = Qnil;
14081 dpyinfo->mouse_face_overlay = Qnil;
14082 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14083 dpyinfo->mouse_face_defer = 0;
14084 dpyinfo->x_focus_frame = 0;
14085 dpyinfo->x_focus_event_frame = 0;
14086 dpyinfo->x_highlight_frame = 0;
14087 dpyinfo->image_cache = make_image_cache ();
14089 /* See if a private colormap is requested. */
14090 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14092 if (dpyinfo->visual->class == PseudoColor)
14094 Lisp_Object value;
14095 value = display_x_get_resource (dpyinfo,
14096 build_string ("privateColormap"),
14097 build_string ("PrivateColormap"),
14098 Qnil, Qnil);
14099 if (STRINGP (value)
14100 && (!strcmp (XSTRING (value)->data, "true")
14101 || !strcmp (XSTRING (value)->data, "on")))
14102 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14105 else
14106 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14107 dpyinfo->visual, AllocNone);
14110 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14111 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14112 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14113 dpyinfo->resy = pixels * 25.4 / mm;
14114 pixels = DisplayWidth (dpyinfo->display, screen_number);
14115 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14116 dpyinfo->resx = pixels * 25.4 / mm;
14119 dpyinfo->Xatom_wm_protocols
14120 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14121 dpyinfo->Xatom_wm_take_focus
14122 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14123 dpyinfo->Xatom_wm_save_yourself
14124 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14125 dpyinfo->Xatom_wm_delete_window
14126 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14127 dpyinfo->Xatom_wm_change_state
14128 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14129 dpyinfo->Xatom_wm_configure_denied
14130 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14131 dpyinfo->Xatom_wm_window_moved
14132 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14133 dpyinfo->Xatom_editres
14134 = XInternAtom (dpyinfo->display, "Editres", False);
14135 dpyinfo->Xatom_CLIPBOARD
14136 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14137 dpyinfo->Xatom_TIMESTAMP
14138 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14139 dpyinfo->Xatom_TEXT
14140 = XInternAtom (dpyinfo->display, "TEXT", False);
14141 dpyinfo->Xatom_COMPOUND_TEXT
14142 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14143 dpyinfo->Xatom_DELETE
14144 = XInternAtom (dpyinfo->display, "DELETE", False);
14145 dpyinfo->Xatom_MULTIPLE
14146 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14147 dpyinfo->Xatom_INCR
14148 = XInternAtom (dpyinfo->display, "INCR", False);
14149 dpyinfo->Xatom_EMACS_TMP
14150 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14151 dpyinfo->Xatom_TARGETS
14152 = XInternAtom (dpyinfo->display, "TARGETS", False);
14153 dpyinfo->Xatom_NULL
14154 = XInternAtom (dpyinfo->display, "NULL", False);
14155 dpyinfo->Xatom_ATOM_PAIR
14156 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14157 /* For properties of font. */
14158 dpyinfo->Xatom_PIXEL_SIZE
14159 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14160 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14161 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14162 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14163 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14164 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14165 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14167 /* Ghostscript support. */
14168 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14169 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14171 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14172 False);
14174 dpyinfo->cut_buffers_initialized = 0;
14176 connection = ConnectionNumber (dpyinfo->display);
14177 dpyinfo->connection = connection;
14180 char null_bits[1];
14182 null_bits[0] = 0x00;
14184 dpyinfo->null_pixel
14185 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14186 null_bits, 1, 1, (long) 0, (long) 0,
14191 extern int gray_bitmap_width, gray_bitmap_height;
14192 extern char *gray_bitmap_bits;
14193 dpyinfo->gray
14194 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14195 gray_bitmap_bits,
14196 gray_bitmap_width, gray_bitmap_height,
14197 (unsigned long) 1, (unsigned long) 0, 1);
14200 #ifdef HAVE_X_I18N
14201 xim_initialize (dpyinfo, resource_name);
14202 #endif
14204 #ifdef subprocesses
14205 /* This is only needed for distinguishing keyboard and process input. */
14206 if (connection != 0)
14207 add_keyboard_wait_descriptor (connection);
14208 #endif
14210 #ifndef F_SETOWN_BUG
14211 #ifdef F_SETOWN
14212 #ifdef F_SETOWN_SOCK_NEG
14213 /* stdin is a socket here */
14214 fcntl (connection, F_SETOWN, -getpid ());
14215 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14216 fcntl (connection, F_SETOWN, getpid ());
14217 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14218 #endif /* ! defined (F_SETOWN) */
14219 #endif /* F_SETOWN_BUG */
14221 #ifdef SIGIO
14222 if (interrupt_input)
14223 init_sigio (connection);
14224 #endif /* ! defined (SIGIO) */
14226 #ifdef USE_LUCID
14227 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14228 /* Make sure that we have a valid font for dialog boxes
14229 so that Xt does not crash. */
14231 Display *dpy = dpyinfo->display;
14232 XrmValue d, fr, to;
14233 Font font;
14234 int count;
14236 d.addr = (XPointer)&dpy;
14237 d.size = sizeof (Display *);
14238 fr.addr = XtDefaultFont;
14239 fr.size = sizeof (XtDefaultFont);
14240 to.size = sizeof (Font *);
14241 to.addr = (XPointer)&font;
14242 count = x_catch_errors (dpy);
14243 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14244 abort ();
14245 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14246 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14247 x_uncatch_errors (dpy, count);
14249 #endif
14250 #endif
14252 /* See if we should run in synchronous mode. This is useful
14253 for debugging X code. */
14255 Lisp_Object value;
14256 value = display_x_get_resource (dpyinfo,
14257 build_string ("synchronous"),
14258 build_string ("Synchronous"),
14259 Qnil, Qnil);
14260 if (STRINGP (value)
14261 && (!strcmp (XSTRING (value)->data, "true")
14262 || !strcmp (XSTRING (value)->data, "on")))
14263 XSynchronize (dpyinfo->display, True);
14266 UNBLOCK_INPUT;
14268 return dpyinfo;
14271 /* Get rid of display DPYINFO, assuming all frames are already gone,
14272 and without sending any more commands to the X server. */
14274 void
14275 x_delete_display (dpyinfo)
14276 struct x_display_info *dpyinfo;
14278 delete_keyboard_wait_descriptor (dpyinfo->connection);
14280 /* Discard this display from x_display_name_list and x_display_list.
14281 We can't use Fdelq because that can quit. */
14282 if (! NILP (x_display_name_list)
14283 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14284 x_display_name_list = XCDR (x_display_name_list);
14285 else
14287 Lisp_Object tail;
14289 tail = x_display_name_list;
14290 while (CONSP (tail) && CONSP (XCDR (tail)))
14292 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14294 XCDR (tail) = XCDR (XCDR (tail));
14295 break;
14297 tail = XCDR (tail);
14301 if (next_noop_dpyinfo == dpyinfo)
14302 next_noop_dpyinfo = dpyinfo->next;
14304 if (x_display_list == dpyinfo)
14305 x_display_list = dpyinfo->next;
14306 else
14308 struct x_display_info *tail;
14310 for (tail = x_display_list; tail; tail = tail->next)
14311 if (tail->next == dpyinfo)
14312 tail->next = tail->next->next;
14315 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14316 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14317 XrmDestroyDatabase (dpyinfo->xrdb);
14318 #endif
14319 #endif
14320 #ifdef MULTI_KBOARD
14321 if (--dpyinfo->kboard->reference_count == 0)
14322 delete_kboard (dpyinfo->kboard);
14323 #endif
14324 #ifdef HAVE_X_I18N
14325 if (dpyinfo->xim)
14326 xim_close_dpy (dpyinfo);
14327 #endif
14329 xfree (dpyinfo->font_table);
14330 xfree (dpyinfo->x_id_name);
14331 xfree (dpyinfo->color_cells);
14332 xfree (dpyinfo);
14336 /* Set up use of X before we make the first connection. */
14338 static struct redisplay_interface x_redisplay_interface =
14340 x_produce_glyphs,
14341 x_write_glyphs,
14342 x_insert_glyphs,
14343 x_clear_end_of_line,
14344 x_scroll_run,
14345 x_after_update_window_line,
14346 x_update_window_begin,
14347 x_update_window_end,
14348 XTcursor_to,
14349 x_flush,
14350 x_clear_mouse_face,
14351 x_get_glyph_overhangs,
14352 x_fix_overlapping_area
14355 void
14356 x_initialize ()
14358 rif = &x_redisplay_interface;
14360 clear_frame_hook = x_clear_frame;
14361 ins_del_lines_hook = x_ins_del_lines;
14362 change_line_highlight_hook = x_change_line_highlight;
14363 delete_glyphs_hook = x_delete_glyphs;
14364 ring_bell_hook = XTring_bell;
14365 reset_terminal_modes_hook = XTreset_terminal_modes;
14366 set_terminal_modes_hook = XTset_terminal_modes;
14367 update_begin_hook = x_update_begin;
14368 update_end_hook = x_update_end;
14369 set_terminal_window_hook = XTset_terminal_window;
14370 read_socket_hook = XTread_socket;
14371 frame_up_to_date_hook = XTframe_up_to_date;
14372 reassert_line_highlight_hook = XTreassert_line_highlight;
14373 mouse_position_hook = XTmouse_position;
14374 frame_rehighlight_hook = XTframe_rehighlight;
14375 frame_raise_lower_hook = XTframe_raise_lower;
14376 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14377 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14378 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14379 judge_scroll_bars_hook = XTjudge_scroll_bars;
14380 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14382 scroll_region_ok = 1; /* we'll scroll partial frames */
14383 char_ins_del_ok = 1;
14384 line_ins_del_ok = 1; /* we'll just blt 'em */
14385 fast_clear_end_of_line = 1; /* X does this well */
14386 memory_below_frame = 0; /* we don't remember what scrolls
14387 off the bottom */
14388 baud_rate = 19200;
14390 x_noop_count = 0;
14391 last_tool_bar_item = -1;
14392 any_help_event_p = 0;
14394 /* Try to use interrupt input; if we can't, then start polling. */
14395 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14397 #ifdef USE_X_TOOLKIT
14398 XtToolkitInitialize ();
14400 Xt_app_con = XtCreateApplicationContext ();
14402 /* Register a converter from strings to pixels, which uses
14403 Emacs' color allocation infrastructure. */
14404 XtAppSetTypeConverter (Xt_app_con,
14405 XtRString, XtRPixel, cvt_string_to_pixel,
14406 cvt_string_to_pixel_args,
14407 XtNumber (cvt_string_to_pixel_args),
14408 XtCacheByDisplay, cvt_pixel_dtor);
14410 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14412 /* Install an asynchronous timer that processes Xt timeout events
14413 every 0.1s. This is necessary because some widget sets use
14414 timeouts internally, for example the LessTif menu bar, or the
14415 Xaw3d scroll bar. When Xt timouts aren't processed, these
14416 widgets don't behave normally. */
14418 EMACS_TIME interval;
14419 EMACS_SET_SECS_USECS (interval, 0, 100000);
14420 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14422 #endif
14424 #ifdef USE_TOOLKIT_SCROLL_BARS
14425 xaw3d_arrow_scroll = False;
14426 xaw3d_pick_top = True;
14427 #endif
14429 /* Note that there is no real way portable across R3/R4 to get the
14430 original error handler. */
14431 XSetErrorHandler (x_error_handler);
14432 XSetIOErrorHandler (x_io_error_quitter);
14434 /* Disable Window Change signals; they are handled by X events. */
14435 #ifdef SIGWINCH
14436 signal (SIGWINCH, SIG_DFL);
14437 #endif /* ! defined (SIGWINCH) */
14439 signal (SIGPIPE, x_connection_signal);
14443 void
14444 syms_of_xterm ()
14446 staticpro (&x_error_message_string);
14447 x_error_message_string = Qnil;
14449 staticpro (&x_display_name_list);
14450 x_display_name_list = Qnil;
14452 staticpro (&last_mouse_scroll_bar);
14453 last_mouse_scroll_bar = Qnil;
14455 staticpro (&Qvendor_specific_keysyms);
14456 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14458 staticpro (&last_mouse_press_frame);
14459 last_mouse_press_frame = Qnil;
14461 help_echo = Qnil;
14462 staticpro (&help_echo);
14463 help_echo_object = Qnil;
14464 staticpro (&help_echo_object);
14465 help_echo_window = Qnil;
14466 staticpro (&help_echo_window);
14467 previous_help_echo = Qnil;
14468 staticpro (&previous_help_echo);
14469 help_echo_pos = -1;
14471 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14472 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
14473 For example, if a block cursor is over a tab, it will be drawn as\n\
14474 wide as that tab on the display.");
14475 x_stretch_cursor_p = 0;
14477 DEFVAR_BOOL ("x-use-underline-position-properties",
14478 &x_use_underline_position_properties,
14479 "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
14480 Nil means ignore them. If you encounter fonts with bogus\n\
14481 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
14482 to 4.1, set this to nil.");
14483 x_use_underline_position_properties = 1;
14485 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14486 "What X toolkit scroll bars Emacs uses.\n\
14487 A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
14488 Otherwise, value is a symbol describing the X toolkit.");
14489 #ifdef USE_TOOLKIT_SCROLL_BARS
14490 #ifdef USE_MOTIF
14491 Vx_toolkit_scroll_bars = intern ("motif");
14492 #elif defined HAVE_XAW3D
14493 Vx_toolkit_scroll_bars = intern ("xaw3d");
14494 #else
14495 Vx_toolkit_scroll_bars = intern ("xaw");
14496 #endif
14497 #else
14498 Vx_toolkit_scroll_bars = Qnil;
14499 #endif
14501 staticpro (&last_mouse_motion_frame);
14502 last_mouse_motion_frame = Qnil;
14505 #endif /* not HAVE_X_WINDOWS */