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)
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. */
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. */
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. */
45 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
60 #ifndef INCLUDED_FCNTL
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
71 #include "character.h"
75 #include "dispextern.h"
77 #include "termhooks.h"
85 #include "intervals.h"
91 #include <X11/Shell.h>
94 #ifdef HAVE_SYS_TIME_H
102 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
103 extern void xlwmenu_redisplay
P_ ((Widget
));
108 extern void free_frame_menubar
P_ ((struct frame
*));
109 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
112 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
114 extern void _XEditResCheckMessages ();
115 #endif /* not NO_EDITRES */
117 /* Include toolkit specific headers for the scroll bar widget. */
119 #ifdef USE_TOOLKIT_SCROLL_BARS
120 #if defined USE_MOTIF
121 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
122 #include <Xm/ScrollBar.h>
123 #else /* !USE_MOTIF i.e. use Xaw */
126 #include <X11/Xaw3d/Simple.h>
127 #include <X11/Xaw3d/Scrollbar.h>
128 #define ARROW_SCROLLBAR
129 #include <X11/Xaw3d/ScrollbarP.h>
130 #else /* !HAVE_XAW3D */
131 #include <X11/Xaw/Simple.h>
132 #include <X11/Xaw/Scrollbar.h>
133 #endif /* !HAVE_XAW3D */
135 #define XtNpickTop "pickTop"
136 #endif /* !XtNpickTop */
137 #endif /* !USE_MOTIF */
138 #endif /* USE_TOOLKIT_SCROLL_BARS */
140 #endif /* USE_X_TOOLKIT */
142 #ifndef USE_X_TOOLKIT
143 #define x_any_window_to_frame x_window_to_frame
144 #define x_top_window_to_frame x_window_to_frame
149 #ifndef XtNinitialState
150 #define XtNinitialState "initialState"
155 /* This isn't prototyped in OSF 5.0 or or XFree 4.1. */
156 extern char * XSetIMValues
P_ ((XIM
, ...));
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
164 /* Fringe bitmaps. */
166 enum fringe_bitmap_type
169 LEFT_TRUNCATION_BITMAP
,
170 RIGHT_TRUNCATION_BITMAP
,
171 OVERLAY_ARROW_BITMAP
,
172 CONTINUED_LINE_BITMAP
,
173 CONTINUATION_LINE_BITMAP
,
177 /* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
183 static unsigned char zv_bits
[] = {
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
186 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
187 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
188 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
189 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
190 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
191 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
193 /* An arrow like this: `<-'. */
196 #define left_height 8
197 static unsigned char left_bits
[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
200 /* Right truncation arrow bitmap `->'. */
202 #define right_width 8
203 #define right_height 8
204 static unsigned char right_bits
[] = {
205 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
207 /* Marker for continued lines. */
209 #define continued_width 8
210 #define continued_height 8
211 static unsigned char continued_bits
[] = {
212 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
214 /* Marker for continuation lines. */
216 #define continuation_width 8
217 #define continuation_height 8
218 static unsigned char continuation_bits
[] = {
219 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
221 /* Overlay arrow bitmap. */
227 static unsigned char ov_bits
[] = {
228 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
230 /* A triangular arrow. */
233 static unsigned char ov_bits
[] = {
234 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
238 extern Lisp_Object Qhelp_echo
;
241 /* Non-nil means Emacs uses toolkit scroll bars. */
243 Lisp_Object Vx_toolkit_scroll_bars
;
245 /* If a string, XTread_socket generates an event to display that string.
246 (The display is done in read_char.) */
248 static Lisp_Object help_echo
;
249 static Lisp_Object help_echo_window
;
250 static Lisp_Object help_echo_object
;
251 static int help_echo_pos
;
253 /* Temporary variable for XTread_socket. */
255 static Lisp_Object previous_help_echo
;
257 /* Non-zero means that a HELP_EVENT has been generated since Emacs
260 static int any_help_event_p
;
262 /* Non-zero means autoselect window with the mouse cursor. */
264 int x_autoselect_window_p
;
266 /* Non-zero means draw block and hollow cursor as wide as the glyph
267 under it. For example, if a block cursor is over a tab, it will be
268 drawn as wide as that tab on the display. */
270 int x_stretch_cursor_p
;
272 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
274 int x_use_underline_position_properties
;
276 /* This is a chain of structures for all the X displays currently in
279 struct x_display_info
*x_display_list
;
281 /* This is a list of cons cells, each of the form (NAME
282 . FONT-LIST-CACHE), one for each element of x_display_list and in
283 the same order. NAME is the name of the frame. FONT-LIST-CACHE
284 records previous values returned by x-list-fonts. */
286 Lisp_Object x_display_name_list
;
288 /* Frame being updated by update_frame. This is declared in term.c.
289 This is set by update_begin and looked at by all the XT functions.
290 It is zero while not inside an update. In that case, the XT
291 functions assume that `selected_frame' is the frame to apply to. */
293 extern struct frame
*updating_frame
;
295 /* This is a frame waiting to be auto-raised, within XTread_socket. */
297 struct frame
*pending_autoraise_frame
;
300 /* The application context for Xt use. */
301 XtAppContext Xt_app_con
;
302 static String Xt_default_resources
[] = {0};
303 #endif /* USE_X_TOOLKIT */
305 /* Nominal cursor position -- where to draw output.
306 HPOS and VPOS are window relative glyph matrix coordinates.
307 X and Y are window relative pixel coordinates. */
309 struct cursor_pos output_cursor
;
311 /* Non-zero means user is interacting with a toolkit scroll bar. */
313 static int toolkit_scroll_bar_interaction
;
317 Formerly, we used PointerMotionHintMask (in standard_event_mask)
318 so that we would have to call XQueryPointer after each MotionNotify
319 event to ask for another such event. However, this made mouse tracking
320 slow, and there was a bug that made it eventually stop.
322 Simply asking for MotionNotify all the time seems to work better.
324 In order to avoid asking for motion events and then throwing most
325 of them away or busy-polling the server for mouse positions, we ask
326 the server for pointer motion hints. This means that we get only
327 one event per group of mouse movements. "Groups" are delimited by
328 other kinds of events (focus changes and button clicks, for
329 example), or by XQueryPointer calls; when one of these happens, we
330 get another MotionNotify event the next time the mouse moves. This
331 is at least as efficient as getting motion events when mouse
332 tracking is on, and I suspect only negligibly worse when tracking
335 /* Where the mouse was last time we reported a mouse event. */
337 FRAME_PTR last_mouse_frame
;
338 static XRectangle last_mouse_glyph
;
339 static Lisp_Object last_mouse_press_frame
;
341 /* The scroll bar in which the last X motion event occurred.
343 If the last X motion event occurred in a scroll bar, we set this so
344 XTmouse_position can know whether to report a scroll bar motion or
347 If the last X motion event didn't occur in a scroll bar, we set
348 this to Qnil, to tell XTmouse_position to return an ordinary motion
351 static Lisp_Object last_mouse_scroll_bar
;
353 /* This is a hack. We would really prefer that XTmouse_position would
354 return the time associated with the position it returns, but there
355 doesn't seem to be any way to wrest the time-stamp from the server
356 along with the position query. So, we just keep track of the time
357 of the last movement we received, and return that in hopes that
358 it's somewhat accurate. */
360 static Time last_mouse_movement_time
;
362 /* Incremented by XTread_socket whenever it really tries to read
366 static int volatile input_signal_count
;
368 static int input_signal_count
;
371 /* Used locally within XTread_socket. */
373 static int x_noop_count
;
375 /* Initial values of argv and argc. */
377 extern char **initial_argv
;
378 extern int initial_argc
;
380 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
382 /* Tells if a window manager is present or not. */
384 extern Lisp_Object Vx_no_window_manager
;
386 extern Lisp_Object Qface
, Qmouse_face
;
390 /* A mask of extra modifier bits to put into every keyboard char. */
392 extern int extra_keyboard_modifiers
;
394 /* The keysyms to use for the various modifiers. */
396 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
397 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
399 static Lisp_Object Qvendor_specific_keysyms
;
401 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
402 extern Lisp_Object x_icon_type
P_ ((struct frame
*));
405 /* Enumeration for overriding/changing the face to use for drawing
406 glyphs in x_draw_glyphs. */
408 enum draw_glyphs_face
418 static int cursor_in_mouse_face_p
P_ ((struct window
*));
419 static int clear_mouse_face
P_ ((struct x_display_info
*));
420 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
421 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
422 static const XColor
*x_color_cells
P_ ((Display
*, int *));
423 static void x_update_window_end
P_ ((struct window
*, int, int));
424 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
425 void x_delete_display
P_ ((struct x_display_info
*));
426 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
428 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
429 int *, int *, Lisp_Object
));
430 static int fast_find_string_pos
P_ ((struct window
*, int, Lisp_Object
,
431 int *, int *, int *, int *, int));
432 static void set_output_cursor
P_ ((struct cursor_pos
*));
433 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
434 int *, int *, int *, int));
435 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
436 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
437 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
438 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
439 static void show_mouse_face
P_ ((struct x_display_info
*,
440 enum draw_glyphs_face
));
441 static int x_io_error_quitter
P_ ((Display
*));
442 int x_catch_errors
P_ ((Display
*));
443 void x_uncatch_errors
P_ ((Display
*, int));
444 void x_lower_frame
P_ ((struct frame
*));
445 void x_scroll_bar_clear
P_ ((struct frame
*));
446 int x_had_errors_p
P_ ((Display
*));
447 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
448 void x_raise_frame
P_ ((struct frame
*));
449 void x_set_window_size
P_ ((struct frame
*, int, int, int));
450 void x_wm_set_window_state
P_ ((struct frame
*, int));
451 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
452 void x_initialize
P_ ((void));
453 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
454 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
455 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
457 enum draw_glyphs_face
));
458 static void x_update_end
P_ ((struct frame
*));
459 static void XTframe_up_to_date
P_ ((struct frame
*));
460 static void XTset_terminal_modes
P_ ((void));
461 static void XTreset_terminal_modes
P_ ((void));
462 static void XTcursor_to
P_ ((int, int, int, int));
463 static void x_write_glyphs
P_ ((struct glyph
*, int));
464 static void x_clear_end_of_line
P_ ((int));
465 static void x_clear_frame
P_ ((void));
466 static void x_clear_cursor
P_ ((struct window
*));
467 static void frame_highlight
P_ ((struct frame
*));
468 static void frame_unhighlight
P_ ((struct frame
*));
469 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
470 static void XTframe_rehighlight
P_ ((struct frame
*));
471 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
472 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
473 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
474 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
476 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
477 static int expose_window_tree
P_ ((struct window
*, XRectangle
*));
478 static int expose_window
P_ ((struct window
*, XRectangle
*));
479 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
480 XRectangle
*, enum glyph_row_area
));
481 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
483 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
484 static void x_update_window_cursor
P_ ((struct window
*, int));
485 static void x_erase_phys_cursor
P_ ((struct window
*));
486 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
487 static void x_draw_fringe_bitmap
P_ ((struct window
*, struct glyph_row
*,
488 enum fringe_bitmap_type
, int left_p
));
490 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
492 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
493 static void x_draw_row_fringe_bitmaps
P_ ((struct window
*, struct glyph_row
*));
494 static void notice_overwritten_cursor
P_ ((struct window
*, enum glyph_row_area
,
495 int, int, int, int));
496 static void x_flush
P_ ((struct frame
*f
));
497 static void x_update_begin
P_ ((struct frame
*));
498 static void x_update_window_begin
P_ ((struct window
*));
499 static void x_draw_vertical_border
P_ ((struct window
*));
500 static void x_after_update_window_line
P_ ((struct glyph_row
*));
501 static INLINE
void take_vertical_position_into_account
P_ ((struct it
*));
502 static void x_produce_stretch_glyph
P_ ((struct it
*));
503 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Window
));
504 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
505 enum scroll_bar_part
*,
506 Lisp_Object
*, Lisp_Object
*,
508 static void x_check_fullscreen
P_ ((struct frame
*));
509 static void x_check_fullscreen_move
P_ ((struct frame
*));
511 /* Flush display of frame F, or of all frames if F is null. */
520 Lisp_Object rest
, frame
;
521 FOR_EACH_FRAME (rest
, frame
)
522 x_flush (XFRAME (frame
));
524 else if (FRAME_X_P (f
))
525 XFlush (FRAME_X_DISPLAY (f
));
530 /* Remove calls to XFlush by defining XFlush to an empty replacement.
531 Calls to XFlush should be unnecessary because the X output buffer
532 is flushed automatically as needed by calls to XPending,
533 XNextEvent, or XWindowEvent according to the XFlush man page.
534 XTread_socket calls XPending. Removing XFlush improves
537 #define XFlush(DISPLAY) (void) 0
540 /***********************************************************************
542 ***********************************************************************/
546 /* This is a function useful for recording debugging information about
547 the sequence of occurrences in this file. */
555 struct record event_record
[100];
557 int event_record_index
;
559 record_event (locus
, type
)
563 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
564 event_record_index
= 0;
566 event_record
[event_record_index
].locus
= locus
;
567 event_record
[event_record_index
].type
= type
;
568 event_record_index
++;
575 /* Return the struct x_display_info corresponding to DPY. */
577 struct x_display_info
*
578 x_display_info_for_display (dpy
)
581 struct x_display_info
*dpyinfo
;
583 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
584 if (dpyinfo
->display
== dpy
)
592 /***********************************************************************
593 Starting and ending an update
594 ***********************************************************************/
596 /* Start an update of frame F. This function is installed as a hook
597 for update_begin, i.e. it is called when update_begin is called.
598 This function is called prior to calls to x_update_window_begin for
599 each window being updated. Currently, there is nothing to do here
600 because all interesting stuff is done on a window basis. */
610 /* Start update of window W. Set the global variable updated_window
611 to the window being updated and set output_cursor to the cursor
615 x_update_window_begin (w
)
618 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
619 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
622 set_output_cursor (&w
->cursor
);
626 if (f
== display_info
->mouse_face_mouse_frame
)
628 /* Don't do highlighting for mouse motion during the update. */
629 display_info
->mouse_face_defer
= 1;
631 /* If F needs to be redrawn, simply forget about any prior mouse
633 if (FRAME_GARBAGED_P (f
))
634 display_info
->mouse_face_window
= Qnil
;
636 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
637 their mouse_face_p flag set, which means that they are always
638 unequal to rows in a desired matrix which never have that
639 flag set. So, rows containing mouse-face glyphs are never
640 scrolled, and we don't have to switch the mouse highlight off
641 here to prevent it from being scrolled. */
643 /* Can we tell that this update does not affect the window
644 where the mouse highlight is? If so, no need to turn off.
645 Likewise, don't do anything if the frame is garbaged;
646 in that case, the frame's current matrix that we would use
647 is all wrong, and we will redisplay that line anyway. */
648 if (!NILP (display_info
->mouse_face_window
)
649 && w
== XWINDOW (display_info
->mouse_face_window
))
653 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
654 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
657 if (i
< w
->desired_matrix
->nrows
)
658 clear_mouse_face (display_info
);
667 /* Draw a vertical window border to the right of window W if W doesn't
668 have vertical scroll bars. */
671 x_draw_vertical_border (w
)
674 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
676 /* Redraw borders between horizontally adjacent windows. Don't
677 do it for frames with vertical scroll bars because either the
678 right scroll bar of a window, or the left scroll bar of its
679 neighbor will suffice as a border. */
680 if (!WINDOW_RIGHTMOST_P (w
)
681 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
685 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
686 x1
+= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
689 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
690 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
695 /* End update of window W (which is equal to updated_window).
697 Draw vertical borders between horizontally adjacent windows, and
698 display W's cursor if CURSOR_ON_P is non-zero.
700 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
701 glyphs in mouse-face were overwritten. In that case we have to
702 make sure that the mouse-highlight is properly redrawn.
704 W may be a menu bar pseudo-window in case we don't have X toolkit
705 support. Such windows don't have a cursor, so don't display it
709 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
711 int cursor_on_p
, mouse_face_overwritten_p
;
713 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
715 if (!w
->pseudo_window_p
)
720 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
722 output_cursor
.x
, output_cursor
.y
);
724 x_draw_vertical_border (w
);
728 /* If a row with mouse-face was overwritten, arrange for
729 XTframe_up_to_date to redisplay the mouse highlight. */
730 if (mouse_face_overwritten_p
)
732 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
733 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
734 dpyinfo
->mouse_face_window
= Qnil
;
737 updated_window
= NULL
;
741 /* End update of frame F. This function is installed as a hook in
748 /* Mouse highlight may be displayed again. */
749 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
752 XFlush (FRAME_X_DISPLAY (f
));
757 /* This function is called from various places in xdisp.c whenever a
758 complete update has been performed. The global variable
759 updated_window is not available here. */
762 XTframe_up_to_date (f
)
767 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
769 if (dpyinfo
->mouse_face_deferred_gc
770 || f
== dpyinfo
->mouse_face_mouse_frame
)
773 if (dpyinfo
->mouse_face_mouse_frame
)
774 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
775 dpyinfo
->mouse_face_mouse_x
,
776 dpyinfo
->mouse_face_mouse_y
);
777 dpyinfo
->mouse_face_deferred_gc
= 0;
784 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
785 arrow bitmaps, or clear the fringes if no bitmaps are required
786 before DESIRED_ROW is made current. The window being updated is
787 found in updated_window. This function It is called from
788 update_window_line only if it is known that there are differences
789 between bitmaps to be drawn between current row and DESIRED_ROW. */
792 x_after_update_window_line (desired_row
)
793 struct glyph_row
*desired_row
;
795 struct window
*w
= updated_window
;
801 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
804 x_draw_row_fringe_bitmaps (w
, desired_row
);
808 /* When a window has disappeared, make sure that no rest of
809 full-width rows stays visible in the internal border. Could
810 check here if updated_window is the leftmost/rightmost window,
811 but I guess it's not worth doing since vertically split windows
812 are almost never used, internal border is rarely set, and the
813 overhead is very small. */
814 if (windows_or_buffers_changed
815 && desired_row
->full_width_p
816 && (f
= XFRAME (w
->frame
),
817 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
819 && (height
= desired_row
->visible_height
,
822 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
824 /* Internal border is drawn below the tool bar. */
825 if (WINDOWP (f
->tool_bar_window
)
826 && w
== XWINDOW (f
->tool_bar_window
))
830 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
831 0, y
, width
, height
, False
);
832 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
833 f
->output_data
.x
->pixel_width
- width
,
834 y
, width
, height
, False
);
840 /* Draw the bitmap WHICH in one of the left or right fringes of
841 window W. ROW is the glyph row for which to display the bitmap; it
842 determines the vertical position at which the bitmap has to be
846 x_draw_fringe_bitmap (w
, row
, which
, left_p
)
848 struct glyph_row
*row
;
849 enum fringe_bitmap_type which
;
852 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
853 Display
*display
= FRAME_X_DISPLAY (f
);
854 Window window
= FRAME_X_WINDOW (f
);
859 GC gc
= f
->output_data
.x
->normal_gc
;
861 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
863 /* Must clip because of partially visible lines. */
864 x_clip_to_row (w
, row
, gc
, 1);
866 /* Convert row to frame coordinates. */
867 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
871 case NO_FRINGE_BITMAP
:
876 case LEFT_TRUNCATION_BITMAP
:
882 case OVERLAY_ARROW_BITMAP
:
888 case RIGHT_TRUNCATION_BITMAP
:
894 case CONTINUED_LINE_BITMAP
:
895 wd
= continued_width
;
896 h
= continued_height
;
897 bits
= continued_bits
;
900 case CONTINUATION_LINE_BITMAP
:
901 wd
= continuation_width
;
902 h
= continuation_height
;
903 bits
= continuation_bits
;
908 h
= zv_height
- (y
% zv_period
);
909 bits
= zv_bits
+ (y
% zv_period
);
916 /* Clip bitmap if too high. */
920 /* Set dy to the offset in the row to start drawing the bitmap. */
921 dy
= (row
->height
- h
) / 2;
923 face
= FACE_FROM_ID (f
, FRINGE_FACE_ID
);
924 PREPARE_FACE_FOR_DISPLAY (f
, face
);
926 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
931 if (wd
> FRAME_X_LEFT_FRINGE_WIDTH (f
))
932 wd
= FRAME_X_LEFT_FRINGE_WIDTH (f
);
933 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
935 - (FRAME_X_LEFT_FRINGE_WIDTH (f
) - wd
) / 2);
936 if (wd
< FRAME_X_LEFT_FRINGE_WIDTH (f
) || row
->height
> h
)
938 /* If W has a vertical border to its left, don't draw over it. */
939 int border
= ((XFASTINT (w
->left
) > 0
940 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
942 b1
= (window_box_left (w
, -1)
943 - FRAME_X_LEFT_FRINGE_WIDTH (f
)
945 b2
= (FRAME_X_LEFT_FRINGE_WIDTH (f
) - border
);
950 if (wd
> FRAME_X_RIGHT_FRINGE_WIDTH (f
))
951 wd
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
952 x
= (window_box_right (w
, -1)
953 + (FRAME_X_RIGHT_FRINGE_WIDTH (f
) - wd
) / 2);
954 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
956 if (wd
< FRAME_X_RIGHT_FRINGE_WIDTH (f
) || row
->height
> h
)
958 b1
= window_box_right (w
, -1);
959 b2
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
965 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
967 /* In case the same realized face is used for fringes and
968 for something displayed in the text (e.g. face `region' on
969 mono-displays, the fill style may have been changed to
970 FillSolid in x_draw_glyph_string_background. */
972 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
974 XSetForeground (display
, face
->gc
, face
->background
);
976 XFillRectangle (display
, window
, face
->gc
,
978 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
981 row
->visible_height
);
983 XSetForeground (display
, face
->gc
, face
->foreground
);
986 if (which
!= NO_FRINGE_BITMAP
)
988 /* Draw the bitmap. I believe these small pixmaps can be cached
990 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
992 face
->background
, depth
);
993 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
994 XFreePixmap (display
, pixmap
);
997 XSetClipMask (display
, gc
, None
);
1001 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1002 function with input blocked. */
1005 x_draw_row_fringe_bitmaps (w
, row
)
1007 struct glyph_row
*row
;
1009 struct frame
*f
= XFRAME (w
->frame
);
1010 enum fringe_bitmap_type bitmap
;
1012 xassert (interrupt_input_blocked
);
1014 /* If row is completely invisible, because of vscrolling, we
1015 don't have to draw anything. */
1016 if (row
->visible_height
<= 0)
1019 if (FRAME_X_LEFT_FRINGE_WIDTH (f
) != 0)
1021 /* Decide which bitmap to draw in the left fringe. */
1022 if (row
->overlay_arrow_p
)
1023 bitmap
= OVERLAY_ARROW_BITMAP
;
1024 else if (row
->truncated_on_left_p
)
1025 bitmap
= LEFT_TRUNCATION_BITMAP
;
1026 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
1027 bitmap
= CONTINUATION_LINE_BITMAP
;
1028 else if (row
->indicate_empty_line_p
)
1029 bitmap
= ZV_LINE_BITMAP
;
1031 bitmap
= NO_FRINGE_BITMAP
;
1033 x_draw_fringe_bitmap (w
, row
, bitmap
, 1);
1036 if (FRAME_X_RIGHT_FRINGE_WIDTH (f
) != 0)
1038 /* Decide which bitmap to draw in the right fringe. */
1039 if (row
->truncated_on_right_p
)
1040 bitmap
= RIGHT_TRUNCATION_BITMAP
;
1041 else if (row
->continued_p
)
1042 bitmap
= CONTINUED_LINE_BITMAP
;
1043 else if (row
->indicate_empty_line_p
&& FRAME_X_LEFT_FRINGE_WIDTH (f
) == 0)
1044 bitmap
= ZV_LINE_BITMAP
;
1046 bitmap
= NO_FRINGE_BITMAP
;
1048 x_draw_fringe_bitmap (w
, row
, bitmap
, 0);
1054 /* This is called when starting Emacs and when restarting after
1055 suspend. When starting Emacs, no X window is mapped. And nothing
1056 must be done to Emacs's own window if it is suspended (though that
1060 XTset_terminal_modes ()
1064 /* This is called when exiting or suspending Emacs. Exiting will make
1065 the X-windows go away, and suspending requires no action. */
1068 XTreset_terminal_modes ()
1074 /***********************************************************************
1076 ***********************************************************************/
1078 /* Set the global variable output_cursor to CURSOR. All cursor
1079 positions are relative to updated_window. */
1082 set_output_cursor (cursor
)
1083 struct cursor_pos
*cursor
;
1085 output_cursor
.hpos
= cursor
->hpos
;
1086 output_cursor
.vpos
= cursor
->vpos
;
1087 output_cursor
.x
= cursor
->x
;
1088 output_cursor
.y
= cursor
->y
;
1092 /* Set a nominal cursor position.
1094 HPOS and VPOS are column/row positions in a window glyph matrix. X
1095 and Y are window text area relative pixel positions.
1097 If this is done during an update, updated_window will contain the
1098 window that is being updated and the position is the future output
1099 cursor position for that window. If updated_window is null, use
1100 selected_window and display the cursor at the given position. */
1103 XTcursor_to (vpos
, hpos
, y
, x
)
1104 int vpos
, hpos
, y
, x
;
1108 /* If updated_window is not set, work on selected_window. */
1112 w
= XWINDOW (selected_window
);
1114 /* Set the output cursor. */
1115 output_cursor
.hpos
= hpos
;
1116 output_cursor
.vpos
= vpos
;
1117 output_cursor
.x
= x
;
1118 output_cursor
.y
= y
;
1120 /* If not called as part of an update, really display the cursor.
1121 This will also set the cursor position of W. */
1122 if (updated_window
== NULL
)
1125 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1126 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1133 /***********************************************************************
1135 ***********************************************************************/
1137 /* Function prototypes of this page. */
1139 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1143 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1144 int, XChar2b
*, int));
1145 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1146 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
,
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
)
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
;
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
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
));
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))
1227 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1228 the two-byte form of C. Encoding is returned in *CHAR2B. */
1231 x_encode_char (c
, char2b
, font_info
, charset
)
1234 struct font_info
*font_info
;
1235 struct charset
*charset
;
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
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_ID (charset
);
1250 ccl
->reg
[1] = char2b
->byte2
;
1254 ccl
->reg
[0] = CHARSET_ID (charset
);
1255 ccl
->reg
[1] = char2b
->byte1
;
1256 ccl
->reg
[2] = char2b
->byte2
;
1259 ccl_driver (ccl
, NULL
, NULL
, 0, 0);
1261 /* We assume that MSBs are appropriately set/reset by CCL
1263 if (font
->max_byte1
== 0) /* 1-byte font */
1264 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1266 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1268 else if (font_info
->encoding_type
)
1270 /* Fixed encoding scheme. See fontset.h for the meaning of the
1271 encoding numbers. */
1272 unsigned char enc
= font_info
->encoding_type
;
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
)
1296 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1300 /* Unibyte case. We don't have to encode, but we have to make
1301 sure to use a face suitable for unibyte. */
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. */
1313 else if (face
->font
!= NULL
)
1315 struct font_info
*font_info
1316 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1317 struct charset
*charset
= CHARSET_FROM_ID (font_info
->charset
);
1318 unsigned code
= ENCODE_CHAR (charset
, c
);
1320 if (CHARSET_DIMENSION (charset
) == 1)
1321 char2b
->byte1
= 0, char2b
->byte2
= code
;
1323 char2b
->byte1
= code
>> 8, char2b
->byte2
= code
& 0xFF;
1325 /* Maybe encode the character in *CHAR2B. */
1326 x_encode_char (c
, char2b
, font_info
, charset
);
1329 /* Make sure X resources of the face are allocated. */
1330 xassert (face
!= NULL
);
1331 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1337 /* Get face and two-byte form of character glyph GLYPH on frame F.
1338 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1339 a pointer to a realized face that is ready for display. */
1341 static INLINE
struct face
*
1342 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
1344 struct glyph
*glyph
;
1350 xassert (glyph
->type
== CHAR_GLYPH
);
1351 face
= FACE_FROM_ID (f
, glyph
->face_id
);
1356 if (!glyph
->multibyte_p
)
1358 /* Unibyte case. We don't have to encode, but we have to make
1359 sure to use a face suitable for unibyte. */
1361 char2b
->byte2
= glyph
->u
.ch
;
1363 else if (glyph
->u
.ch
< 128
1364 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
1366 /* Case of ASCII in a face known to fit ASCII. */
1368 char2b
->byte2
= glyph
->u
.ch
;
1372 struct font_info
*font_info
1373 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1376 struct charset
*charset
= CHARSET_FROM_ID (font_info
->charset
);
1377 unsigned code
= ENCODE_CHAR (charset
, glyph
->u
.ch
);
1379 if (CHARSET_DIMENSION (charset
) == 1)
1380 char2b
->byte1
= 0, char2b
->byte2
= code
;
1382 char2b
->byte1
= code
>> 8, char2b
->byte2
= code
& 0xFF;
1384 /* Maybe encode the character in *CHAR2B. */
1385 if (CHARSET_ID (charset
) != charset_ascii
)
1387 x_encode_char (glyph
->u
.ch
, char2b
, font_info
, charset
);
1390 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1395 /* Make sure X resources of the face are allocated. */
1396 xassert (face
!= NULL
);
1397 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1402 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1403 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1409 struct glyph
*glyph
;
1410 enum glyph_row_area area
= it
->area
;
1412 xassert (it
->glyph_row
);
1413 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1415 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1416 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1418 glyph
->charpos
= CHARPOS (it
->position
);
1419 glyph
->object
= it
->object
;
1420 glyph
->pixel_width
= it
->pixel_width
;
1421 glyph
->voffset
= it
->voffset
;
1422 glyph
->type
= CHAR_GLYPH
;
1423 glyph
->multibyte_p
= it
->multibyte_p
;
1424 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1425 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1426 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1427 || it
->phys_descent
> it
->descent
);
1428 glyph
->padding_p
= 0;
1429 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
1430 glyph
->face_id
= it
->face_id
;
1431 glyph
->u
.ch
= it
->char_to_display
;
1432 ++it
->glyph_row
->used
[area
];
1436 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1437 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1440 x_append_composite_glyph (it
)
1443 struct glyph
*glyph
;
1444 enum glyph_row_area area
= it
->area
;
1446 xassert (it
->glyph_row
);
1448 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1449 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1451 glyph
->charpos
= CHARPOS (it
->position
);
1452 glyph
->object
= it
->object
;
1453 glyph
->pixel_width
= it
->pixel_width
;
1454 glyph
->voffset
= it
->voffset
;
1455 glyph
->type
= COMPOSITE_GLYPH
;
1456 glyph
->multibyte_p
= it
->multibyte_p
;
1457 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1458 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1459 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1460 || it
->phys_descent
> it
->descent
);
1461 glyph
->padding_p
= 0;
1462 glyph
->glyph_not_available_p
= 0;
1463 glyph
->face_id
= it
->face_id
;
1464 glyph
->u
.cmp_id
= it
->cmp_id
;
1465 ++it
->glyph_row
->used
[area
];
1470 /* Change IT->ascent and IT->height according to the setting of
1474 take_vertical_position_into_account (it
)
1479 if (it
->voffset
< 0)
1480 /* Increase the ascent so that we can display the text higher
1482 it
->ascent
+= abs (it
->voffset
);
1484 /* Increase the descent so that we can display the text lower
1486 it
->descent
+= it
->voffset
;
1491 /* Produce glyphs/get display metrics for the image IT is loaded with.
1492 See the description of struct display_iterator in dispextern.h for
1493 an overview of struct display_iterator. */
1496 x_produce_image_glyph (it
)
1502 xassert (it
->what
== IT_IMAGE
);
1504 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1505 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1508 /* Make sure X resources of the face and image are loaded. */
1509 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1510 prepare_image_for_display (it
->f
, img
);
1512 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
1513 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->vmargin
- it
->ascent
;
1514 it
->pixel_width
= img
->width
+ 2 * img
->hmargin
;
1518 if (face
->box
!= FACE_NO_BOX
)
1520 if (face
->box_line_width
> 0)
1522 it
->ascent
+= face
->box_line_width
;
1523 it
->descent
+= face
->box_line_width
;
1526 if (it
->start_of_box_run_p
)
1527 it
->pixel_width
+= abs (face
->box_line_width
);
1528 if (it
->end_of_box_run_p
)
1529 it
->pixel_width
+= abs (face
->box_line_width
);
1532 take_vertical_position_into_account (it
);
1536 struct glyph
*glyph
;
1537 enum glyph_row_area area
= it
->area
;
1539 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1540 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1542 glyph
->charpos
= CHARPOS (it
->position
);
1543 glyph
->object
= it
->object
;
1544 glyph
->pixel_width
= it
->pixel_width
;
1545 glyph
->voffset
= it
->voffset
;
1546 glyph
->type
= IMAGE_GLYPH
;
1547 glyph
->multibyte_p
= it
->multibyte_p
;
1548 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1549 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1550 glyph
->overlaps_vertically_p
= 0;
1551 glyph
->padding_p
= 0;
1552 glyph
->glyph_not_available_p
= 0;
1553 glyph
->face_id
= it
->face_id
;
1554 glyph
->u
.img_id
= img
->id
;
1555 ++it
->glyph_row
->used
[area
];
1561 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1562 of the glyph, WIDTH and HEIGHT are the width and height of the
1563 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1564 ascent of the glyph (0 <= ASCENT <= 1). */
1567 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1573 struct glyph
*glyph
;
1574 enum glyph_row_area area
= it
->area
;
1576 xassert (ascent
>= 0 && ascent
<= 1);
1578 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1579 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1581 glyph
->charpos
= CHARPOS (it
->position
);
1582 glyph
->object
= object
;
1583 glyph
->pixel_width
= width
;
1584 glyph
->voffset
= it
->voffset
;
1585 glyph
->type
= STRETCH_GLYPH
;
1586 glyph
->multibyte_p
= it
->multibyte_p
;
1587 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1588 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1589 glyph
->overlaps_vertically_p
= 0;
1590 glyph
->padding_p
= 0;
1591 glyph
->glyph_not_available_p
= 0;
1592 glyph
->face_id
= it
->face_id
;
1593 glyph
->u
.stretch
.ascent
= height
* ascent
;
1594 glyph
->u
.stretch
.height
= height
;
1595 ++it
->glyph_row
->used
[area
];
1600 /* Produce a stretch glyph for iterator IT. IT->object is the value
1601 of the glyph property displayed. The value must be a list
1602 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1605 1. `:width WIDTH' specifies that the space should be WIDTH *
1606 canonical char width wide. WIDTH may be an integer or floating
1609 2. `:relative-width FACTOR' specifies that the width of the stretch
1610 should be computed from the width of the first character having the
1611 `glyph' property, and should be FACTOR times that width.
1613 3. `:align-to HPOS' specifies that the space should be wide enough
1614 to reach HPOS, a value in canonical character units.
1616 Exactly one of the above pairs must be present.
1618 4. `:height HEIGHT' specifies that the height of the stretch produced
1619 should be HEIGHT, measured in canonical character units.
1621 5. `:relative-height FACTOR' specifies that the height of the
1622 stretch should be FACTOR times the height of the characters having
1625 Either none or exactly one of 4 or 5 must be present.
1627 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1628 of the stretch should be used for the ascent of the stretch.
1629 ASCENT must be in the range 0 <= ASCENT <= 100. */
1632 ((INTEGERP (X) || FLOATP (X)) \
1638 x_produce_stretch_glyph (it
)
1641 /* (space :width WIDTH :height HEIGHT. */
1643 extern Lisp_Object Qspace
;
1645 extern Lisp_Object QCwidth
, QCheight
, QCascent
;
1646 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1647 extern Lisp_Object QCalign_to
;
1648 Lisp_Object prop
, plist
;
1649 double width
= 0, height
= 0, ascent
= 0;
1650 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1651 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1653 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1655 /* List should start with `space'. */
1656 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1657 plist
= XCDR (it
->object
);
1659 /* Compute the width of the stretch. */
1660 if (prop
= Fplist_get (plist
, QCwidth
),
1662 /* Absolute width `:width WIDTH' specified and valid. */
1663 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1664 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1667 /* Relative width `:relative-width FACTOR' specified and valid.
1668 Compute the width of the characters having the `glyph'
1671 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1674 if (it
->multibyte_p
)
1676 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1677 - IT_BYTEPOS (*it
));
1678 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1681 it2
.c
= *p
, it2
.len
= 1;
1683 it2
.glyph_row
= NULL
;
1684 it2
.what
= IT_CHARACTER
;
1685 x_produce_glyphs (&it2
);
1686 width
= NUMVAL (prop
) * it2
.pixel_width
;
1688 else if (prop
= Fplist_get (plist
, QCalign_to
),
1690 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1692 /* Nothing specified -> width defaults to canonical char width. */
1693 width
= CANON_X_UNIT (it
->f
);
1695 /* Compute height. */
1696 if (prop
= Fplist_get (plist
, QCheight
),
1698 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1699 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1701 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1703 height
= FONT_HEIGHT (font
);
1705 /* Compute percentage of height used for ascent. If
1706 `:ascent ASCENT' is present and valid, use that. Otherwise,
1707 derive the ascent from the font in use. */
1708 if (prop
= Fplist_get (plist
, QCascent
),
1709 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1710 ascent
= NUMVAL (prop
) / 100.0;
1712 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1721 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1722 if (!STRINGP (object
))
1723 object
= it
->w
->buffer
;
1724 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1727 it
->pixel_width
= width
;
1728 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1729 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1732 if (face
->box
!= FACE_NO_BOX
)
1734 if (face
->box_line_width
> 0)
1736 it
->ascent
+= face
->box_line_width
;
1737 it
->descent
+= face
->box_line_width
;
1740 if (it
->start_of_box_run_p
)
1741 it
->pixel_width
+= abs (face
->box_line_width
);
1742 if (it
->end_of_box_run_p
)
1743 it
->pixel_width
+= abs (face
->box_line_width
);
1746 take_vertical_position_into_account (it
);
1749 /* Return proper value to be used as baseline offset of font that has
1750 ASCENT and DESCENT to draw characters by the font at the vertical
1751 center of the line of frame F.
1753 Here, out task is to find the value of BOFF in the following figure;
1755 -------------------------+-----------+-
1756 -+-+---------+-+ | |
1758 | | | | F_ASCENT F_HEIGHT
1761 | | |-|-+------+-----------|------- baseline
1763 | |---------|-+-+ | |
1765 -+-+---------+-+ F_DESCENT |
1766 -------------------------+-----------+-
1768 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1769 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1770 DESCENT = FONT->descent
1771 HEIGHT = FONT_HEIGHT (FONT)
1772 F_DESCENT = (F->output_data.x->font->descent
1773 - F->output_data.x->baseline_offset)
1774 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1777 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1780 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1781 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1783 /* Produce glyphs/get display metrics for the display element IT is
1784 loaded with. See the description of struct display_iterator in
1785 dispextern.h for an overview of struct display_iterator. */
1788 x_produce_glyphs (it
)
1791 it
->glyph_not_available_p
= 0;
1793 if (it
->what
== IT_CHARACTER
)
1797 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1799 int font_not_found_p
;
1800 struct font_info
*font_info
;
1801 int boff
; /* baseline offset */
1802 /* We may change it->multibyte_p upon unibyte<->multibyte
1803 conversion. So, save the current value now and restore it
1806 Note: It seems that we don't have to record multibyte_p in
1807 struct glyph because the character code itself tells if or
1808 not the character is multibyte. Thus, in the future, we must
1809 consider eliminating the field `multibyte_p' in the struct
1811 int saved_multibyte_p
= it
->multibyte_p
;
1813 /* Maybe translate single-byte characters to multibyte, or the
1815 it
->char_to_display
= it
->c
;
1816 if (!ASCII_BYTE_P (it
->c
))
1818 if (unibyte_display_via_language_environment
1819 && SINGLE_BYTE_CHAR_P (it
->c
))
1821 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1822 it
->multibyte_p
= 1;
1823 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1824 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1826 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
1827 && !it
->multibyte_p
)
1829 it
->multibyte_p
= 1;
1830 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1831 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1835 /* Get font to use. Encode IT->char_to_display. */
1836 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1837 it
->face_id
, &char2b
,
1841 /* When no suitable font found, use the default font. */
1842 font_not_found_p
= font
== NULL
;
1843 if (font_not_found_p
)
1845 font
= FRAME_FONT (it
->f
);
1846 boff
= it
->f
->output_data
.x
->baseline_offset
;
1851 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1852 boff
= font_info
->baseline_offset
;
1853 if (font_info
->vertical_centering
)
1854 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1857 if (it
->char_to_display
>= ' '
1858 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1860 /* Either unibyte or ASCII. */
1865 pcm
= x_per_char_metric (font
, &char2b
);
1866 it
->ascent
= font
->ascent
+ boff
;
1867 it
->descent
= font
->descent
- boff
;
1871 it
->phys_ascent
= pcm
->ascent
+ boff
;
1872 it
->phys_descent
= pcm
->descent
- boff
;
1873 it
->pixel_width
= pcm
->width
;
1877 it
->glyph_not_available_p
= 1;
1878 it
->phys_ascent
= font
->ascent
+ boff
;
1879 it
->phys_descent
= font
->descent
- boff
;
1880 it
->pixel_width
= FONT_WIDTH (font
);
1883 /* If this is a space inside a region of text with
1884 `space-width' property, change its width. */
1885 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1887 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1889 /* If face has a box, add the box thickness to the character
1890 height. If character has a box line to the left and/or
1891 right, add the box line width to the character's width. */
1892 if (face
->box
!= FACE_NO_BOX
)
1894 int thick
= face
->box_line_width
;
1898 it
->ascent
+= thick
;
1899 it
->descent
+= thick
;
1904 if (it
->start_of_box_run_p
)
1905 it
->pixel_width
+= thick
;
1906 if (it
->end_of_box_run_p
)
1907 it
->pixel_width
+= thick
;
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face
->overline_p
)
1915 take_vertical_position_into_account (it
);
1917 /* If we have to actually produce glyphs, do it. */
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1925 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1926 it
->ascent
+ it
->descent
, ascent
);
1929 x_append_glyph (it
);
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1934 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
1935 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1938 else if (it
->char_to_display
== '\n')
1940 /* A newline has no width but we need the height of the line. */
1941 it
->pixel_width
= 0;
1943 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1944 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1946 if (face
->box
!= FACE_NO_BOX
1947 && face
->box_line_width
> 0)
1949 it
->ascent
+= face
->box_line_width
;
1950 it
->descent
+= face
->box_line_width
;
1953 else if (it
->char_to_display
== '\t')
1955 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1956 int x
= it
->current_x
+ it
->continuation_lines_width
;
1957 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x
- x
< CANON_X_UNIT (it
->f
))
1963 next_tab_x
+= tab_width
;
1965 it
->pixel_width
= next_tab_x
- x
;
1967 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1968 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1972 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1973 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1974 it
->ascent
+ it
->descent
, ascent
);
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
1981 width of the font. */
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character by
1986 multiplying the width of font by the width of the
1988 pcm
= x_per_char_metric (font
, &char2b
);
1989 if (font_not_found_p
|| !pcm
)
1991 it
->glyph_not_available_p
= 1;
1992 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
1993 * CHAR_WIDTH (it
->char_to_display
));
1994 it
->phys_ascent
= font
->ascent
+ boff
;
1995 it
->phys_descent
= font
->descent
- boff
;
1999 it
->pixel_width
= pcm
->width
;
2000 it
->phys_ascent
= pcm
->ascent
+ boff
;
2001 it
->phys_descent
= pcm
->descent
- boff
;
2003 && (pcm
->lbearing
< 0
2004 || pcm
->rbearing
> pcm
->width
))
2005 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2008 it
->ascent
= font
->ascent
+ boff
;
2009 it
->descent
= font
->descent
- boff
;
2010 if (face
->box
!= FACE_NO_BOX
)
2012 int thick
= face
->box_line_width
;
2016 it
->ascent
+= thick
;
2017 it
->descent
+= thick
;
2022 if (it
->start_of_box_run_p
)
2023 it
->pixel_width
+= thick
;
2024 if (it
->end_of_box_run_p
)
2025 it
->pixel_width
+= thick
;
2028 /* If face has an overline, add the height of the overline
2029 (1 pixel) and a 1 pixel margin to the character height. */
2030 if (face
->overline_p
)
2033 take_vertical_position_into_account (it
);
2036 x_append_glyph (it
);
2038 it
->multibyte_p
= saved_multibyte_p
;
2040 else if (it
->what
== IT_COMPOSITION
)
2042 /* Note: A composition is represented as one glyph in the
2043 glyph matrix. There are no padding glyphs. */
2046 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2048 int font_not_found_p
;
2049 struct font_info
*font_info
;
2050 int boff
; /* baseline offset */
2051 struct composition
*cmp
= composition_table
[it
->cmp_id
];
2053 /* Maybe translate single-byte characters to multibyte. */
2054 it
->char_to_display
= it
->c
;
2055 if (unibyte_display_via_language_environment
2058 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2061 /* Get face and font to use. Encode IT->char_to_display. */
2062 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2063 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2064 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2065 it
->face_id
, &char2b
, it
->multibyte_p
);
2068 /* When no suitable font found, use the default font. */
2069 font_not_found_p
= font
== NULL
;
2070 if (font_not_found_p
)
2072 font
= FRAME_FONT (it
->f
);
2073 boff
= it
->f
->output_data
.x
->baseline_offset
;
2078 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2079 boff
= font_info
->baseline_offset
;
2080 if (font_info
->vertical_centering
)
2081 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2084 /* There are no padding glyphs, so there is only one glyph to
2085 produce for the composition. Important is that pixel_width,
2086 ascent and descent are the values of what is drawn by
2087 draw_glyphs (i.e. the values of the overall glyphs composed). */
2090 /* If we have not yet calculated pixel size data of glyphs of
2091 the composition for the current face font, calculate them
2092 now. Theoretically, we have to check all fonts for the
2093 glyphs, but that requires much time and memory space. So,
2094 here we check only the font of the first glyph. This leads
2095 to incorrect display very rarely, and C-l (recenter) can
2096 correct the display anyway. */
2097 if (cmp
->font
!= (void *) font
)
2099 /* Ascent and descent of the font of the first character of
2100 this composition (adjusted by baseline offset). Ascent
2101 and descent of overall glyphs should not be less than
2102 them respectively. */
2103 int font_ascent
= font
->ascent
+ boff
;
2104 int font_descent
= font
->descent
- boff
;
2105 /* Bounding box of the overall glyphs. */
2106 int leftmost
, rightmost
, lowest
, highest
;
2107 int i
, width
, ascent
, descent
;
2109 cmp
->font
= (void *) font
;
2111 /* Initialize the bounding box. */
2113 && (pcm
= x_per_char_metric (font
, &char2b
)))
2116 ascent
= pcm
->ascent
;
2117 descent
= pcm
->descent
;
2121 width
= FONT_WIDTH (font
);
2122 ascent
= font
->ascent
;
2123 descent
= font
->descent
;
2127 lowest
= - descent
+ boff
;
2128 highest
= ascent
+ boff
;
2132 && font_info
->default_ascent
2133 && CHAR_TABLE_P (Vuse_default_ascent
)
2134 && !NILP (Faref (Vuse_default_ascent
,
2135 make_number (it
->char_to_display
))))
2136 highest
= font_info
->default_ascent
+ boff
;
2138 /* Draw the first glyph at the normal position. It may be
2139 shifted to right later if some other glyphs are drawn at
2141 cmp
->offsets
[0] = 0;
2142 cmp
->offsets
[1] = boff
;
2144 /* Set cmp->offsets for the remaining glyphs. */
2145 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2147 int left
, right
, btm
, top
;
2148 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2149 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2151 face
= FACE_FROM_ID (it
->f
, face_id
);
2152 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2157 font
= FRAME_FONT (it
->f
);
2158 boff
= it
->f
->output_data
.x
->baseline_offset
;
2164 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2165 boff
= font_info
->baseline_offset
;
2166 if (font_info
->vertical_centering
)
2167 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2171 && (pcm
= x_per_char_metric (font
, &char2b
)))
2174 ascent
= pcm
->ascent
;
2175 descent
= pcm
->descent
;
2179 width
= FONT_WIDTH (font
);
2184 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2186 /* Relative composition with or without
2188 left
= (leftmost
+ rightmost
- width
) / 2;
2189 btm
= - descent
+ boff
;
2190 if (font_info
&& font_info
->relative_compose
2191 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2192 || NILP (Faref (Vignore_relative_composition
,
2193 make_number (ch
)))))
2196 if (- descent
>= font_info
->relative_compose
)
2197 /* One extra pixel between two glyphs. */
2199 else if (ascent
<= 0)
2200 /* One extra pixel between two glyphs. */
2201 btm
= lowest
- 1 - ascent
- descent
;
2206 /* A composition rule is specified by an integer
2207 value that encodes global and new reference
2208 points (GREF and NREF). GREF and NREF are
2209 specified by numbers as below:
2217 ---3---4---5--- baseline
2219 6---7---8 -- descent
2221 int rule
= COMPOSITION_RULE (cmp
, i
);
2222 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2224 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2225 grefx
= gref
% 3, nrefx
= nref
% 3;
2226 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2229 + grefx
* (rightmost
- leftmost
) / 2
2230 - nrefx
* width
/ 2);
2231 btm
= ((grefy
== 0 ? highest
2233 : grefy
== 2 ? lowest
2234 : (highest
+ lowest
) / 2)
2235 - (nrefy
== 0 ? ascent
+ descent
2236 : nrefy
== 1 ? descent
- boff
2238 : (ascent
+ descent
) / 2));
2241 cmp
->offsets
[i
* 2] = left
;
2242 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2244 /* Update the bounding box of the overall glyphs. */
2245 right
= left
+ width
;
2246 top
= btm
+ descent
+ ascent
;
2247 if (left
< leftmost
)
2249 if (right
> rightmost
)
2257 /* If there are glyphs whose x-offsets are negative,
2258 shift all glyphs to the right and make all x-offsets
2262 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2263 cmp
->offsets
[i
* 2] -= leftmost
;
2264 rightmost
-= leftmost
;
2267 cmp
->pixel_width
= rightmost
;
2268 cmp
->ascent
= highest
;
2269 cmp
->descent
= - lowest
;
2270 if (cmp
->ascent
< font_ascent
)
2271 cmp
->ascent
= font_ascent
;
2272 if (cmp
->descent
< font_descent
)
2273 cmp
->descent
= font_descent
;
2276 it
->pixel_width
= cmp
->pixel_width
;
2277 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2278 it
->descent
= it
->phys_descent
= cmp
->descent
;
2280 if (face
->box
!= FACE_NO_BOX
)
2282 int thick
= face
->box_line_width
;
2286 it
->ascent
+= thick
;
2287 it
->descent
+= thick
;
2292 if (it
->start_of_box_run_p
)
2293 it
->pixel_width
+= thick
;
2294 if (it
->end_of_box_run_p
)
2295 it
->pixel_width
+= thick
;
2298 /* If face has an overline, add the height of the overline
2299 (1 pixel) and a 1 pixel margin to the character height. */
2300 if (face
->overline_p
)
2303 take_vertical_position_into_account (it
);
2306 x_append_composite_glyph (it
);
2308 else if (it
->what
== IT_IMAGE
)
2309 x_produce_image_glyph (it
);
2310 else if (it
->what
== IT_STRETCH
)
2311 x_produce_stretch_glyph (it
);
2313 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2314 because this isn't true for images with `:ascent 100'. */
2315 xassert (it
->ascent
>= 0 && it
->descent
>= 0);
2316 if (it
->area
== TEXT_AREA
)
2317 it
->current_x
+= it
->pixel_width
;
2319 it
->descent
+= it
->extra_line_spacing
;
2321 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2322 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2323 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2324 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2328 /* Estimate the pixel height of the mode or top line on frame F.
2329 FACE_ID specifies what line's height to estimate. */
2332 x_estimate_mode_line_height (f
, face_id
)
2334 enum face_id face_id
;
2336 int height
= FONT_HEIGHT (FRAME_FONT (f
));
2338 /* This function is called so early when Emacs starts that the face
2339 cache and mode line face are not yet initialized. */
2340 if (FRAME_FACE_CACHE (f
))
2342 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2346 height
= FONT_HEIGHT (face
->font
);
2347 if (face
->box_line_width
> 0)
2348 height
+= 2 * face
->box_line_width
;
2356 /***********************************************************************
2358 ***********************************************************************/
2360 /* A sequence of glyphs to be drawn in the same face.
2362 This data structure is not really completely X specific, so it
2363 could possibly, at least partially, be useful for other systems. It
2364 is currently not part of the external redisplay interface because
2365 it's not clear what other systems will need. */
2369 /* X-origin of the string. */
2372 /* Y-origin and y-position of the base line of this string. */
2375 /* The width of the string, not including a face extension. */
2378 /* The width of the string, including a face extension. */
2379 int background_width
;
2381 /* The height of this string. This is the height of the line this
2382 string is drawn in, and can be different from the height of the
2383 font the string is drawn in. */
2386 /* Number of pixels this string overwrites in front of its x-origin.
2387 This number is zero if the string has an lbearing >= 0; it is
2388 -lbearing, if the string has an lbearing < 0. */
2391 /* Number of pixels this string overwrites past its right-most
2392 nominal x-position, i.e. x + width. Zero if the string's
2393 rbearing is <= its nominal width, rbearing - width otherwise. */
2396 /* The frame on which the glyph string is drawn. */
2399 /* The window on which the glyph string is drawn. */
2402 /* X display and window for convenience. */
2406 /* The glyph row for which this string was built. It determines the
2407 y-origin and height of the string. */
2408 struct glyph_row
*row
;
2410 /* The area within row. */
2411 enum glyph_row_area area
;
2413 /* Characters to be drawn, and number of characters. */
2417 /* A face-override for drawing cursors, mouse face and similar. */
2418 enum draw_glyphs_face hl
;
2420 /* Face in which this string is to be drawn. */
2423 /* Font in which this string is to be drawn. */
2426 /* Font info for this string. */
2427 struct font_info
*font_info
;
2429 /* Non-null means this string describes (part of) a composition.
2430 All characters from char2b are drawn composed. */
2431 struct composition
*cmp
;
2433 /* Index of this glyph string's first character in the glyph
2434 definition of CMP. If this is zero, this glyph string describes
2435 the first character of a composition. */
2438 /* 1 means this glyph strings face has to be drawn to the right end
2439 of the window's drawing area. */
2440 unsigned extends_to_end_of_line_p
: 1;
2442 /* 1 means the background of this string has been drawn. */
2443 unsigned background_filled_p
: 1;
2445 /* 1 means glyph string must be drawn with 16-bit functions. */
2446 unsigned two_byte_p
: 1;
2448 /* 1 means that the original font determined for drawing this glyph
2449 string could not be loaded. The member `font' has been set to
2450 the frame's default font in this case. */
2451 unsigned font_not_found_p
: 1;
2453 /* 1 means that the face in which this glyph string is drawn has a
2455 unsigned stippled_p
: 1;
2457 /* 1 means only the foreground of this glyph string must be drawn,
2458 and we should use the physical height of the line this glyph
2459 string appears in as clip rect. */
2460 unsigned for_overlaps_p
: 1;
2462 /* The GC to use for drawing this glyph string. */
2465 /* A pointer to the first glyph in the string. This glyph
2466 corresponds to char2b[0]. Needed to draw rectangles if
2467 font_not_found_p is 1. */
2468 struct glyph
*first_glyph
;
2470 /* Image, if any. */
2473 struct glyph_string
*next
, *prev
;
2480 x_dump_glyph_string (s
)
2481 struct glyph_string
*s
;
2483 fprintf (stderr
, "glyph string\n");
2484 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2485 s
->x
, s
->y
, s
->width
, s
->height
);
2486 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2487 fprintf (stderr
, " hl = %d\n", s
->hl
);
2488 fprintf (stderr
, " left overhang = %d, right = %d\n",
2489 s
->left_overhang
, s
->right_overhang
);
2490 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2491 fprintf (stderr
, " extends to end of line = %d\n",
2492 s
->extends_to_end_of_line_p
);
2493 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2494 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2497 #endif /* GLYPH_DEBUG */
2501 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2502 struct glyph_string
**,
2503 struct glyph_string
*,
2504 struct glyph_string
*));
2505 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2506 struct glyph_string
**,
2507 struct glyph_string
*,
2508 struct glyph_string
*));
2509 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2510 struct glyph_string
**,
2511 struct glyph_string
*));
2512 static int x_left_overwritten
P_ ((struct glyph_string
*));
2513 static int x_left_overwriting
P_ ((struct glyph_string
*));
2514 static int x_right_overwritten
P_ ((struct glyph_string
*));
2515 static int x_right_overwriting
P_ ((struct glyph_string
*));
2516 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2518 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2519 XChar2b
*, struct window
*,
2521 enum glyph_row_area
, int,
2522 enum draw_glyphs_face
));
2523 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2524 enum glyph_row_area
, int, int,
2525 enum draw_glyphs_face
, int));
2526 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2527 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2528 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2530 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2531 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2532 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2533 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2534 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2535 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2536 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2537 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2538 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2540 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2541 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2542 unsigned long *, double, int));
2543 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2544 double, int, unsigned long));
2545 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2546 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2547 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2548 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2549 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2550 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2551 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2553 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2554 int, int, int, int, XRectangle
*));
2555 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2556 int, int, int, XRectangle
*));
2557 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2558 enum glyph_row_area
));
2559 static int x_fill_stretch_glyph_string
P_ ((struct glyph_string
*,
2561 enum glyph_row_area
, int, int));
2564 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2568 /* Append the list of glyph strings with head H and tail T to the list
2569 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2572 x_append_glyph_string_lists (head
, tail
, h
, t
)
2573 struct glyph_string
**head
, **tail
;
2574 struct glyph_string
*h
, *t
;
2588 /* Prepend the list of glyph strings with head H and tail T to the
2589 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2593 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2594 struct glyph_string
**head
, **tail
;
2595 struct glyph_string
*h
, *t
;
2609 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2610 Set *HEAD and *TAIL to the resulting list. */
2613 x_append_glyph_string (head
, tail
, s
)
2614 struct glyph_string
**head
, **tail
;
2615 struct glyph_string
*s
;
2617 s
->next
= s
->prev
= NULL
;
2618 x_append_glyph_string_lists (head
, tail
, s
, s
);
2622 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2627 struct glyph_string
*s
;
2629 if (s
->font
== FRAME_FONT (s
->f
)
2630 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2631 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2633 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2636 /* Cursor on non-default face: must merge. */
2640 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2641 xgcv
.foreground
= s
->face
->background
;
2643 /* If the glyph would be invisible, try a different foreground. */
2644 if (xgcv
.foreground
== xgcv
.background
)
2645 xgcv
.foreground
= s
->face
->foreground
;
2646 if (xgcv
.foreground
== xgcv
.background
)
2647 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2648 if (xgcv
.foreground
== xgcv
.background
)
2649 xgcv
.foreground
= s
->face
->foreground
;
2651 /* Make sure the cursor is distinct from text in this face. */
2652 if (xgcv
.background
== s
->face
->background
2653 && xgcv
.foreground
== s
->face
->foreground
)
2655 xgcv
.background
= s
->face
->foreground
;
2656 xgcv
.foreground
= s
->face
->background
;
2659 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2660 xgcv
.font
= s
->font
->fid
;
2661 xgcv
.graphics_exposures
= False
;
2662 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2664 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2665 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2668 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2669 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2671 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2676 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2679 x_set_mouse_face_gc (s
)
2680 struct glyph_string
*s
;
2685 /* What face has to be used last for the mouse face? */
2686 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2687 face
= FACE_FROM_ID (s
->f
, face_id
);
2689 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2691 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2692 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2694 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2695 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2696 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2698 /* If font in this face is same as S->font, use it. */
2699 if (s
->font
== s
->face
->font
)
2700 s
->gc
= s
->face
->gc
;
2703 /* Otherwise construct scratch_cursor_gc with values from FACE
2708 xgcv
.background
= s
->face
->background
;
2709 xgcv
.foreground
= s
->face
->foreground
;
2710 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2711 xgcv
.font
= s
->font
->fid
;
2712 xgcv
.graphics_exposures
= False
;
2713 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2715 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2716 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2719 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2720 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2722 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2725 xassert (s
->gc
!= 0);
2729 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2730 Faces to use in the mode line have already been computed when the
2731 matrix was built, so there isn't much to do, here. */
2734 x_set_mode_line_face_gc (s
)
2735 struct glyph_string
*s
;
2737 s
->gc
= s
->face
->gc
;
2741 /* Set S->gc of glyph string S for drawing that glyph string. Set
2742 S->stippled_p to a non-zero value if the face of S has a stipple
2746 x_set_glyph_string_gc (s
)
2747 struct glyph_string
*s
;
2749 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2751 if (s
->hl
== DRAW_NORMAL_TEXT
)
2753 s
->gc
= s
->face
->gc
;
2754 s
->stippled_p
= s
->face
->stipple
!= 0;
2756 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2758 x_set_mode_line_face_gc (s
);
2759 s
->stippled_p
= s
->face
->stipple
!= 0;
2761 else if (s
->hl
== DRAW_CURSOR
)
2763 x_set_cursor_gc (s
);
2766 else if (s
->hl
== DRAW_MOUSE_FACE
)
2768 x_set_mouse_face_gc (s
);
2769 s
->stippled_p
= s
->face
->stipple
!= 0;
2771 else if (s
->hl
== DRAW_IMAGE_RAISED
2772 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2774 s
->gc
= s
->face
->gc
;
2775 s
->stippled_p
= s
->face
->stipple
!= 0;
2779 s
->gc
= s
->face
->gc
;
2780 s
->stippled_p
= s
->face
->stipple
!= 0;
2783 /* GC must have been set. */
2784 xassert (s
->gc
!= 0);
2788 /* Return in *R the clipping rectangle for glyph string S. */
2791 x_get_glyph_string_clip_rect (s
, r
)
2792 struct glyph_string
*s
;
2795 if (s
->row
->full_width_p
)
2797 /* Draw full-width. X coordinates are relative to S->w->left. */
2798 int canon_x
= CANON_X_UNIT (s
->f
);
2800 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2801 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2803 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2805 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2806 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2810 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2812 /* Unless displaying a mode or menu bar line, which are always
2813 fully visible, clip to the visible part of the row. */
2814 if (s
->w
->pseudo_window_p
)
2815 r
->height
= s
->row
->visible_height
;
2817 r
->height
= s
->height
;
2821 /* This is a text line that may be partially visible. */
2822 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2823 r
->width
= window_box_width (s
->w
, s
->area
);
2824 r
->height
= s
->row
->visible_height
;
2827 /* If S draws overlapping rows, it's sufficient to use the top and
2828 bottom of the window for clipping because this glyph string
2829 intentionally draws over other lines. */
2830 if (s
->for_overlaps_p
)
2832 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2833 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2837 /* Don't use S->y for clipping because it doesn't take partially
2838 visible lines into account. For example, it can be negative for
2839 partially visible lines at the top of a window. */
2840 if (!s
->row
->full_width_p
2841 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2842 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2844 r
->y
= max (0, s
->row
->y
);
2846 /* If drawing a tool-bar window, draw it over the internal border
2847 at the top of the window. */
2848 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2849 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2852 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2856 /* Set clipping for output of glyph string S. S may be part of a mode
2857 line or menu if we don't have X toolkit support. */
2860 x_set_glyph_string_clipping (s
)
2861 struct glyph_string
*s
;
2864 x_get_glyph_string_clip_rect (s
, &r
);
2865 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2869 /* Compute left and right overhang of glyph string S. If S is a glyph
2870 string for a composition, assume overhangs don't exist. */
2873 x_compute_glyph_string_overhangs (s
)
2874 struct glyph_string
*s
;
2877 && s
->first_glyph
->type
== CHAR_GLYPH
)
2880 int direction
, font_ascent
, font_descent
;
2881 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2882 &font_ascent
, &font_descent
, &cs
);
2883 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2884 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2889 /* Compute overhangs and x-positions for glyph string S and its
2890 predecessors, or successors. X is the starting x-position for S.
2891 BACKWARD_P non-zero means process predecessors. */
2894 x_compute_overhangs_and_x (s
, x
, backward_p
)
2895 struct glyph_string
*s
;
2903 x_compute_glyph_string_overhangs (s
);
2913 x_compute_glyph_string_overhangs (s
);
2922 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2923 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2924 assumed to be zero. */
2927 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2928 struct glyph
*glyph
;
2934 if (glyph
->type
== CHAR_GLYPH
)
2938 struct font_info
*font_info
;
2942 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
2944 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2946 && (pcm
= x_per_char_metric (font
, &char2b
)))
2948 if (pcm
->rbearing
> pcm
->width
)
2949 *right
= pcm
->rbearing
- pcm
->width
;
2950 if (pcm
->lbearing
< 0)
2951 *left
= -pcm
->lbearing
;
2957 /* Return the index of the first glyph preceding glyph string S that
2958 is overwritten by S because of S's left overhang. Value is -1
2959 if no glyphs are overwritten. */
2962 x_left_overwritten (s
)
2963 struct glyph_string
*s
;
2967 if (s
->left_overhang
)
2970 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2971 int first
= s
->first_glyph
- glyphs
;
2973 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2974 x
-= glyphs
[i
].pixel_width
;
2985 /* Return the index of the first glyph preceding glyph string S that
2986 is overwriting S because of its right overhang. Value is -1 if no
2987 glyph in front of S overwrites S. */
2990 x_left_overwriting (s
)
2991 struct glyph_string
*s
;
2994 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2995 int first
= s
->first_glyph
- glyphs
;
2999 for (i
= first
- 1; i
>= 0; --i
)
3002 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3005 x
-= glyphs
[i
].pixel_width
;
3012 /* Return the index of the last glyph following glyph string S that is
3013 not overwritten by S because of S's right overhang. Value is -1 if
3014 no such glyph is found. */
3017 x_right_overwritten (s
)
3018 struct glyph_string
*s
;
3022 if (s
->right_overhang
)
3025 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3026 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3027 int end
= s
->row
->used
[s
->area
];
3029 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
3030 x
+= glyphs
[i
].pixel_width
;
3039 /* Return the index of the last glyph following glyph string S that
3040 overwrites S because of its left overhang. Value is negative
3041 if no such glyph is found. */
3044 x_right_overwriting (s
)
3045 struct glyph_string
*s
;
3048 int end
= s
->row
->used
[s
->area
];
3049 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3050 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3054 for (i
= first
; i
< end
; ++i
)
3057 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3060 x
+= glyphs
[i
].pixel_width
;
3067 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3070 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3071 struct glyph_string
*s
;
3075 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
3076 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3077 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3078 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3082 /* Draw the background of glyph_string S. If S->background_filled_p
3083 is non-zero don't draw it. FORCE_P non-zero means draw the
3084 background even if it wouldn't be drawn normally. This is used
3085 when a string preceding S draws into the background of S, or S
3086 contains the first component of a composition. */
3089 x_draw_glyph_string_background (s
, force_p
)
3090 struct glyph_string
*s
;
3093 /* Nothing to do if background has already been drawn or if it
3094 shouldn't be drawn in the first place. */
3095 if (!s
->background_filled_p
)
3097 int box_line_width
= max (s
->face
->box_line_width
, 0);
3101 /* Fill background with a stipple pattern. */
3102 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3103 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3104 s
->y
+ box_line_width
,
3105 s
->background_width
,
3106 s
->height
- 2 * box_line_width
);
3107 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3108 s
->background_filled_p
= 1;
3110 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3111 || s
->font_not_found_p
3112 || s
->extends_to_end_of_line_p
3115 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3116 s
->background_width
,
3117 s
->height
- 2 * box_line_width
);
3118 s
->background_filled_p
= 1;
3124 /* Draw the foreground of glyph string S. */
3127 x_draw_glyph_string_foreground (s
)
3128 struct glyph_string
*s
;
3132 /* If first glyph of S has a left box line, start drawing the text
3133 of S to the right of that box line. */
3134 if (s
->face
->box
!= FACE_NO_BOX
3135 && s
->first_glyph
->left_box_line_p
)
3136 x
= s
->x
+ abs (s
->face
->box_line_width
);
3140 /* Draw characters of S as rectangles if S's font could not be
3142 if (s
->font_not_found_p
)
3144 for (i
= 0; i
< s
->nchars
; ++i
)
3146 struct glyph
*g
= s
->first_glyph
+ i
;
3147 XDrawRectangle (s
->display
, s
->window
,
3148 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3150 x
+= g
->pixel_width
;
3155 char *char1b
= (char *) s
->char2b
;
3156 int boff
= s
->font_info
->baseline_offset
;
3158 if (s
->font_info
->vertical_centering
)
3159 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3161 /* If we can use 8-bit functions, condense S->char2b. */
3163 for (i
= 0; i
< s
->nchars
; ++i
)
3164 char1b
[i
] = s
->char2b
[i
].byte2
;
3166 /* Draw text with XDrawString if background has already been
3167 filled. Otherwise, use XDrawImageString. (Note that
3168 XDrawImageString is usually faster than XDrawString.) Always
3169 use XDrawImageString when drawing the cursor so that there is
3170 no chance that characters under a box cursor are invisible. */
3171 if (s
->for_overlaps_p
3172 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3174 /* Draw characters with 16-bit or 8-bit functions. */
3176 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3177 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3179 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3180 s
->ybase
- boff
, char1b
, s
->nchars
);
3185 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3186 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3188 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3189 s
->ybase
- boff
, char1b
, s
->nchars
);
3194 /* Draw the foreground of composite glyph string S. */
3197 x_draw_composite_glyph_string_foreground (s
)
3198 struct glyph_string
*s
;
3202 /* If first glyph of S has a left box line, start drawing the text
3203 of S to the right of that box line. */
3204 if (s
->face
->box
!= FACE_NO_BOX
3205 && s
->first_glyph
->left_box_line_p
)
3206 x
= s
->x
+ abs (s
->face
->box_line_width
);
3210 /* S is a glyph string for a composition. S->gidx is the index of
3211 the first character drawn for glyphs of this composition.
3212 S->gidx == 0 means we are drawing the very first character of
3213 this composition. */
3215 /* Draw a rectangle for the composition if the font for the very
3216 first character of the composition could not be loaded. */
3217 if (s
->font_not_found_p
)
3220 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3221 s
->width
- 1, s
->height
- 1);
3225 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3226 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3227 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3228 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3234 #ifdef USE_X_TOOLKIT
3236 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3237 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
3238 XrmValue
*, XrmValue
*, XtPointer
*));
3239 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
3240 XrmValue
*, Cardinal
*));
3243 /* Return the frame on which widget WIDGET is used.. Abort if frame
3244 cannot be determined. */
3246 static struct frame
*
3247 x_frame_of_widget (widget
)
3250 struct x_display_info
*dpyinfo
;
3254 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3256 /* Find the top-level shell of the widget. Note that this function
3257 can be called when the widget is not yet realized, so XtWindow
3258 (widget) == 0. That's the reason we can't simply use
3259 x_any_window_to_frame. */
3260 while (!XtIsTopLevelShell (widget
))
3261 widget
= XtParent (widget
);
3263 /* Look for a frame with that top-level widget. Allocate the color
3264 on that frame to get the right gamma correction value. */
3265 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3266 if (GC_FRAMEP (XCAR (tail
))
3267 && (f
= XFRAME (XCAR (tail
)),
3268 (f
->output_data
.nothing
!= 1
3269 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3270 && f
->output_data
.x
->widget
== widget
)
3277 /* Allocate the color COLOR->pixel on the screen and display of
3278 widget WIDGET in colormap CMAP. If an exact match cannot be
3279 allocated, try the nearest color available. Value is non-zero
3280 if successful. This is called from lwlib. */
3283 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3288 struct frame
*f
= x_frame_of_widget (widget
);
3289 return x_alloc_nearest_color (f
, cmap
, color
);
3293 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3294 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3295 If this produces the same color as PIXEL, try a color where all RGB
3296 values have DELTA added. Return the allocated color in *PIXEL.
3297 DISPLAY is the X display, CMAP is the colormap to operate on.
3298 Value is non-zero if successful. */
3301 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
3305 unsigned long *pixel
;
3309 struct frame
*f
= x_frame_of_widget (widget
);
3310 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
3314 /* Structure specifying which arguments should be passed by Xt to
3315 cvt_string_to_pixel. We want the widget's screen and colormap. */
3317 static XtConvertArgRec cvt_string_to_pixel_args
[] =
3319 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
3321 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
3326 /* The address of this variable is returned by
3327 cvt_string_to_pixel. */
3329 static Pixel cvt_string_to_pixel_value
;
3332 /* Convert a color name to a pixel color.
3334 DPY is the display we are working on.
3336 ARGS is an array of *NARGS XrmValue structures holding additional
3337 information about the widget for which the conversion takes place.
3338 The contents of this array are determined by the specification
3339 in cvt_string_to_pixel_args.
3341 FROM is a pointer to an XrmValue which points to the color name to
3342 convert. TO is an XrmValue in which to return the pixel color.
3344 CLOSURE_RET is a pointer to user-data, in which we record if
3345 we allocated the color or not.
3347 Value is True if successful, False otherwise. */
3350 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
3354 XrmValue
*from
, *to
;
3355 XtPointer
*closure_ret
;
3365 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
3366 "wrongParameters", "cvt_string_to_pixel",
3368 "Screen and colormap args required", NULL
, NULL
);
3372 screen
= *(Screen
**) args
[0].addr
;
3373 cmap
= *(Colormap
*) args
[1].addr
;
3374 color_name
= (String
) from
->addr
;
3376 if (strcmp (color_name
, XtDefaultBackground
) == 0)
3378 *closure_ret
= (XtPointer
) False
;
3379 pixel
= WhitePixelOfScreen (screen
);
3381 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
3383 *closure_ret
= (XtPointer
) False
;
3384 pixel
= BlackPixelOfScreen (screen
);
3386 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
3387 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
3389 pixel
= color
.pixel
;
3390 *closure_ret
= (XtPointer
) True
;
3395 Cardinal nparams
= 1;
3397 params
[0] = color_name
;
3398 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
3399 "badValue", "cvt_string_to_pixel",
3400 "XtToolkitError", "Invalid color `%s'",
3405 if (to
->addr
!= NULL
)
3407 if (to
->size
< sizeof (Pixel
))
3409 to
->size
= sizeof (Pixel
);
3413 *(Pixel
*) to
->addr
= pixel
;
3417 cvt_string_to_pixel_value
= pixel
;
3418 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
3421 to
->size
= sizeof (Pixel
);
3426 /* Free a pixel color which was previously allocated via
3427 cvt_string_to_pixel. This is registered as the destructor
3428 for this type of resource via XtSetTypeConverter.
3430 APP is the application context in which we work.
3432 TO is a pointer to an XrmValue holding the color to free.
3433 CLOSURE is the value we stored in CLOSURE_RET for this color
3434 in cvt_string_to_pixel.
3436 ARGS and NARGS are like for cvt_string_to_pixel. */
3439 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
3448 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
3450 "Screen and colormap arguments required",
3453 else if (closure
!= NULL
)
3455 /* We did allocate the pixel, so free it. */
3456 Screen
*screen
= *(Screen
**) args
[0].addr
;
3457 Colormap cmap
= *(Colormap
*) args
[1].addr
;
3458 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
3459 (Pixel
*) to
->addr
, 1);
3464 #endif /* USE_X_TOOLKIT */
3467 /* Value is an array of XColor structures for the contents of the
3468 color map of display DPY. Set *NCELLS to the size of the array.
3469 Note that this probably shouldn't be called for large color maps,
3470 say a 24-bit TrueColor map. */
3472 static const XColor
*
3473 x_color_cells (dpy
, ncells
)
3477 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
3479 if (dpyinfo
->color_cells
== NULL
)
3481 Screen
*screen
= dpyinfo
->screen
;
3484 dpyinfo
->ncolor_cells
3485 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
3486 dpyinfo
->color_cells
3487 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
3488 * sizeof *dpyinfo
->color_cells
);
3490 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
3491 dpyinfo
->color_cells
[i
].pixel
= i
;
3493 XQueryColors (dpy
, dpyinfo
->cmap
,
3494 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
3497 *ncells
= dpyinfo
->ncolor_cells
;
3498 return dpyinfo
->color_cells
;
3502 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3503 colors in COLORS. Use cached information, if available. */
3506 x_query_colors (f
, colors
, ncolors
)
3511 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3513 if (dpyinfo
->color_cells
)
3516 for (i
= 0; i
< ncolors
; ++i
)
3518 unsigned long pixel
= colors
[i
].pixel
;
3519 xassert (pixel
< dpyinfo
->ncolor_cells
);
3520 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
3521 colors
[i
] = dpyinfo
->color_cells
[pixel
];
3525 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
3529 /* On frame F, translate pixel color to RGB values for the color in
3530 COLOR. Use cached information, if available. */
3533 x_query_color (f
, color
)
3537 x_query_colors (f
, color
, 1);
3541 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3542 exact match can't be allocated, try the nearest color available.
3543 Value is non-zero if successful. Set *COLOR to the color
3547 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
3554 rc
= XAllocColor (dpy
, cmap
, color
);
3557 /* If we got to this point, the colormap is full, so we're going
3558 to try to get the next closest color. The algorithm used is
3559 a least-squares matching, which is what X uses for closest
3560 color matching with StaticColor visuals. */
3562 unsigned long nearest_delta
= ~0;
3564 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
3566 for (nearest
= i
= 0; i
< ncells
; ++i
)
3568 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3569 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3570 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3571 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3573 if (delta
< nearest_delta
)
3576 nearest_delta
= delta
;
3580 color
->red
= cells
[nearest
].red
;
3581 color
->green
= cells
[nearest
].green
;
3582 color
->blue
= cells
[nearest
].blue
;
3583 rc
= XAllocColor (dpy
, cmap
, color
);
3587 /* If allocation succeeded, and the allocated pixel color is not
3588 equal to a cached pixel color recorded earlier, there was a
3589 change in the colormap, so clear the color cache. */
3590 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
3591 XColor
*cached_color
;
3593 if (dpyinfo
->color_cells
3594 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
3595 (cached_color
->red
!= color
->red
3596 || cached_color
->blue
!= color
->blue
3597 || cached_color
->green
!= color
->green
)))
3599 xfree (dpyinfo
->color_cells
);
3600 dpyinfo
->color_cells
= NULL
;
3601 dpyinfo
->ncolor_cells
= 0;
3605 #ifdef DEBUG_X_COLORS
3607 register_color (color
->pixel
);
3608 #endif /* DEBUG_X_COLORS */
3614 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3615 exact match can't be allocated, try the nearest color available.
3616 Value is non-zero if successful. Set *COLOR to the color
3620 x_alloc_nearest_color (f
, cmap
, color
)
3625 gamma_correct (f
, color
);
3626 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
3630 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3631 It's necessary to do this instead of just using PIXEL directly to
3632 get color reference counts right. */
3635 x_copy_color (f
, pixel
)
3637 unsigned long pixel
;
3641 color
.pixel
= pixel
;
3643 x_query_color (f
, &color
);
3644 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3646 #ifdef DEBUG_X_COLORS
3647 register_color (pixel
);
3653 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3654 It's necessary to do this instead of just using PIXEL directly to
3655 get color reference counts right. */
3658 x_copy_dpy_color (dpy
, cmap
, pixel
)
3661 unsigned long pixel
;
3665 color
.pixel
= pixel
;
3667 XQueryColor (dpy
, cmap
, &color
);
3668 XAllocColor (dpy
, cmap
, &color
);
3670 #ifdef DEBUG_X_COLORS
3671 register_color (pixel
);
3677 /* Brightness beyond which a color won't have its highlight brightness
3680 Nominally, highlight colors for `3d' faces are calculated by
3681 brightening an object's color by a constant scale factor, but this
3682 doesn't yield good results for dark colors, so for colors who's
3683 brightness is less than this value (on a scale of 0-65535) have an
3684 use an additional additive factor.
3686 The value here is set so that the default menu-bar/mode-line color
3687 (grey75) will not have its highlights changed at all. */
3688 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3691 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3692 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3693 If this produces the same color as PIXEL, try a color where all RGB
3694 values have DELTA added. Return the allocated color in *PIXEL.
3695 DISPLAY is the X display, CMAP is the colormap to operate on.
3696 Value is non-zero if successful. */
3699 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3703 unsigned long *pixel
;
3711 /* Get RGB color values. */
3712 color
.pixel
= *pixel
;
3713 x_query_color (f
, &color
);
3715 /* Change RGB values by specified FACTOR. Avoid overflow! */
3716 xassert (factor
>= 0);
3717 new.red
= min (0xffff, factor
* color
.red
);
3718 new.green
= min (0xffff, factor
* color
.green
);
3719 new.blue
= min (0xffff, factor
* color
.blue
);
3721 /* Calculate brightness of COLOR. */
3722 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
3724 /* We only boost colors that are darker than
3725 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3726 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3727 /* Make an additive adjustment to NEW, because it's dark enough so
3728 that scaling by FACTOR alone isn't enough. */
3730 /* How far below the limit this color is (0 - 1, 1 being darker). */
3731 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3732 /* The additive adjustment. */
3733 int min_delta
= delta
* dimness
* factor
/ 2;
3737 new.red
= max (0, new.red
- min_delta
);
3738 new.green
= max (0, new.green
- min_delta
);
3739 new.blue
= max (0, new.blue
- min_delta
);
3743 new.red
= min (0xffff, min_delta
+ new.red
);
3744 new.green
= min (0xffff, min_delta
+ new.green
);
3745 new.blue
= min (0xffff, min_delta
+ new.blue
);
3749 /* Try to allocate the color. */
3750 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3753 if (new.pixel
== *pixel
)
3755 /* If we end up with the same color as before, try adding
3756 delta to the RGB values. */
3757 x_free_colors (f
, &new.pixel
, 1);
3759 new.red
= min (0xffff, delta
+ color
.red
);
3760 new.green
= min (0xffff, delta
+ color
.green
);
3761 new.blue
= min (0xffff, delta
+ color
.blue
);
3762 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3773 /* Set up the foreground color for drawing relief lines of glyph
3774 string S. RELIEF is a pointer to a struct relief containing the GC
3775 with which lines will be drawn. Use a color that is FACTOR or
3776 DELTA lighter or darker than the relief's background which is found
3777 in S->f->output_data.x->relief_background. If such a color cannot
3778 be allocated, use DEFAULT_PIXEL, instead. */
3781 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3783 struct relief
*relief
;
3786 unsigned long default_pixel
;
3789 struct x_output
*di
= f
->output_data
.x
;
3790 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3791 unsigned long pixel
;
3792 unsigned long background
= di
->relief_background
;
3793 Colormap cmap
= FRAME_X_COLORMAP (f
);
3794 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3795 Display
*dpy
= FRAME_X_DISPLAY (f
);
3797 xgcv
.graphics_exposures
= False
;
3798 xgcv
.line_width
= 1;
3800 /* Free previously allocated color. The color cell will be reused
3801 when it has been freed as many times as it was allocated, so this
3802 doesn't affect faces using the same colors. */
3804 && relief
->allocated_p
)
3806 x_free_colors (f
, &relief
->pixel
, 1);
3807 relief
->allocated_p
= 0;
3810 /* Allocate new color. */
3811 xgcv
.foreground
= default_pixel
;
3813 if (dpyinfo
->n_planes
!= 1
3814 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3816 relief
->allocated_p
= 1;
3817 xgcv
.foreground
= relief
->pixel
= pixel
;
3820 if (relief
->gc
== 0)
3822 xgcv
.stipple
= dpyinfo
->gray
;
3824 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3827 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3831 /* Set up colors for the relief lines around glyph string S. */
3834 x_setup_relief_colors (s
)
3835 struct glyph_string
*s
;
3837 struct x_output
*di
= s
->f
->output_data
.x
;
3838 unsigned long color
;
3840 if (s
->face
->use_box_color_for_shadows_p
)
3841 color
= s
->face
->box_color
;
3842 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3844 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3845 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3850 /* Get the background color of the face. */
3851 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3852 color
= xgcv
.background
;
3855 if (di
->white_relief
.gc
== 0
3856 || color
!= di
->relief_background
)
3858 di
->relief_background
= color
;
3859 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3860 WHITE_PIX_DEFAULT (s
->f
));
3861 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3862 BLACK_PIX_DEFAULT (s
->f
));
3867 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3868 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3869 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3870 relief. LEFT_P non-zero means draw a relief on the left side of
3871 the rectangle. RIGHT_P non-zero means draw a relief on the right
3872 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3876 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3877 raised_p
, left_p
, right_p
, clip_rect
)
3879 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3880 XRectangle
*clip_rect
;
3882 Display
*dpy
= FRAME_X_DISPLAY (f
);
3883 Window window
= FRAME_X_WINDOW (f
);
3888 gc
= f
->output_data
.x
->white_relief
.gc
;
3890 gc
= f
->output_data
.x
->black_relief
.gc
;
3891 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
3894 for (i
= 0; i
< width
; ++i
)
3895 XDrawLine (dpy
, window
, gc
,
3896 left_x
+ i
* left_p
, top_y
+ i
,
3897 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3901 for (i
= 0; i
< width
; ++i
)
3902 XDrawLine (dpy
, window
, gc
,
3903 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3905 XSetClipMask (dpy
, gc
, None
);
3907 gc
= f
->output_data
.x
->black_relief
.gc
;
3909 gc
= f
->output_data
.x
->white_relief
.gc
;
3910 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
3913 for (i
= 0; i
< width
; ++i
)
3914 XDrawLine (dpy
, window
, gc
,
3915 left_x
+ i
* left_p
, bottom_y
- i
,
3916 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3920 for (i
= 0; i
< width
; ++i
)
3921 XDrawLine (dpy
, window
, gc
,
3922 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3924 XSetClipMask (dpy
, gc
, None
);
3928 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3929 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3930 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3931 left side of the rectangle. RIGHT_P non-zero means draw a line
3932 on the right side of the rectangle. CLIP_RECT is the clipping
3933 rectangle to use when drawing. */
3936 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3937 left_p
, right_p
, clip_rect
)
3938 struct glyph_string
*s
;
3939 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3940 XRectangle
*clip_rect
;
3944 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3945 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3946 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3949 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3950 left_x
, top_y
, right_x
- left_x
+ 1, width
);
3954 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3955 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
3958 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3959 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
3963 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3964 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
3966 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3967 XSetClipMask (s
->display
, s
->gc
, None
);
3971 /* Draw a box around glyph string S. */
3974 x_draw_glyph_string_box (s
)
3975 struct glyph_string
*s
;
3977 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3978 int left_p
, right_p
;
3979 struct glyph
*last_glyph
;
3980 XRectangle clip_rect
;
3982 last_x
= window_box_right (s
->w
, s
->area
);
3983 if (s
->row
->full_width_p
3984 && !s
->w
->pseudo_window_p
)
3986 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
3987 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3988 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3991 /* The glyph that may have a right box line. */
3992 last_glyph
= (s
->cmp
|| s
->img
3994 : s
->first_glyph
+ s
->nchars
- 1);
3996 width
= abs (s
->face
->box_line_width
);
3997 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3999 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
4001 : min (last_x
, s
->x
+ s
->background_width
) - 1);
4003 bottom_y
= top_y
+ s
->height
- 1;
4005 left_p
= (s
->first_glyph
->left_box_line_p
4006 || (s
->hl
== DRAW_MOUSE_FACE
4008 || s
->prev
->hl
!= s
->hl
)));
4009 right_p
= (last_glyph
->right_box_line_p
4010 || (s
->hl
== DRAW_MOUSE_FACE
4012 || s
->next
->hl
!= s
->hl
)));
4014 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4016 if (s
->face
->box
== FACE_SIMPLE_BOX
)
4017 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4018 left_p
, right_p
, &clip_rect
);
4021 x_setup_relief_colors (s
);
4022 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
4023 width
, raised_p
, left_p
, right_p
, &clip_rect
);
4028 /* Draw foreground of image glyph string S. */
4031 x_draw_image_foreground (s
)
4032 struct glyph_string
*s
;
4035 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4037 /* If first glyph of S has a left box line, start drawing it to the
4038 right of that line. */
4039 if (s
->face
->box
!= FACE_NO_BOX
4040 && s
->first_glyph
->left_box_line_p
)
4041 x
= s
->x
+ abs (s
->face
->box_line_width
);
4045 /* If there is a margin around the image, adjust x- and y-position
4047 x
+= s
->img
->hmargin
;
4048 y
+= s
->img
->vmargin
;
4054 /* We can't set both a clip mask and use XSetClipRectangles
4055 because the latter also sets a clip mask. We also can't
4056 trust on the shape extension to be available
4057 (XShapeCombineRegion). So, compute the rectangle to draw
4059 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4062 XRectangle clip_rect
, image_rect
, r
;
4064 xgcv
.clip_mask
= s
->img
->mask
;
4065 xgcv
.clip_x_origin
= x
;
4066 xgcv
.clip_y_origin
= y
;
4067 xgcv
.function
= GXcopy
;
4068 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4070 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4073 image_rect
.width
= s
->img
->width
;
4074 image_rect
.height
= s
->img
->height
;
4075 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4076 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4077 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4081 XRectangle clip_rect
, image_rect
, r
;
4083 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4086 image_rect
.width
= s
->img
->width
;
4087 image_rect
.height
= s
->img
->height
;
4088 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4089 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4090 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4092 /* When the image has a mask, we can expect that at
4093 least part of a mouse highlight or a block cursor will
4094 be visible. If the image doesn't have a mask, make
4095 a block cursor visible by drawing a rectangle around
4096 the image. I believe it's looking better if we do
4097 nothing here for mouse-face. */
4098 if (s
->hl
== DRAW_CURSOR
)
4099 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
4100 s
->img
->width
- 1, s
->img
->height
- 1);
4104 /* Draw a rectangle if image could not be loaded. */
4105 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
4106 s
->img
->width
- 1, s
->img
->height
- 1);
4110 /* Draw a relief around the image glyph string S. */
4113 x_draw_image_relief (s
)
4114 struct glyph_string
*s
;
4116 int x0
, y0
, x1
, y1
, thick
, raised_p
;
4119 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4121 /* If first glyph of S has a left box line, start drawing it to the
4122 right of that line. */
4123 if (s
->face
->box
!= FACE_NO_BOX
4124 && s
->first_glyph
->left_box_line_p
)
4125 x
= s
->x
+ abs (s
->face
->box_line_width
);
4129 /* If there is a margin around the image, adjust x- and y-position
4131 x
+= s
->img
->hmargin
;
4132 y
+= s
->img
->vmargin
;
4134 if (s
->hl
== DRAW_IMAGE_SUNKEN
4135 || s
->hl
== DRAW_IMAGE_RAISED
)
4137 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
4138 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
4142 thick
= abs (s
->img
->relief
);
4143 raised_p
= s
->img
->relief
> 0;
4148 x1
= x
+ s
->img
->width
+ thick
- 1;
4149 y1
= y
+ s
->img
->height
+ thick
- 1;
4151 x_setup_relief_colors (s
);
4152 x_get_glyph_string_clip_rect (s
, &r
);
4153 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
4157 /* Draw the foreground of image glyph string S to PIXMAP. */
4160 x_draw_image_foreground_1 (s
, pixmap
)
4161 struct glyph_string
*s
;
4165 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
4167 /* If first glyph of S has a left box line, start drawing it to the
4168 right of that line. */
4169 if (s
->face
->box
!= FACE_NO_BOX
4170 && s
->first_glyph
->left_box_line_p
)
4171 x
= abs (s
->face
->box_line_width
);
4175 /* If there is a margin around the image, adjust x- and y-position
4177 x
+= s
->img
->hmargin
;
4178 y
+= s
->img
->vmargin
;
4184 /* We can't set both a clip mask and use XSetClipRectangles
4185 because the latter also sets a clip mask. We also can't
4186 trust on the shape extension to be available
4187 (XShapeCombineRegion). So, compute the rectangle to draw
4189 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4193 xgcv
.clip_mask
= s
->img
->mask
;
4194 xgcv
.clip_x_origin
= x
;
4195 xgcv
.clip_y_origin
= y
;
4196 xgcv
.function
= GXcopy
;
4197 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4199 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4200 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4201 XSetClipMask (s
->display
, s
->gc
, None
);
4205 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4206 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4208 /* When the image has a mask, we can expect that at
4209 least part of a mouse highlight or a block cursor will
4210 be visible. If the image doesn't have a mask, make
4211 a block cursor visible by drawing a rectangle around
4212 the image. I believe it's looking better if we do
4213 nothing here for mouse-face. */
4214 if (s
->hl
== DRAW_CURSOR
)
4215 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
4216 s
->img
->width
- 1, s
->img
->height
- 1);
4220 /* Draw a rectangle if image could not be loaded. */
4221 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
4222 s
->img
->width
- 1, s
->img
->height
- 1);
4226 /* Draw part of the background of glyph string S. X, Y, W, and H
4227 give the rectangle to draw. */
4230 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
4231 struct glyph_string
*s
;
4236 /* Fill background with a stipple pattern. */
4237 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4238 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
4239 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4242 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
4246 /* Draw image glyph string S.
4249 s->x +-------------------------
4252 | +-------------------------
4255 | | +-------------------
4261 x_draw_image_glyph_string (s
)
4262 struct glyph_string
*s
;
4265 int box_line_hwidth
= abs (s
->face
->box_line_width
);
4266 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
4268 Pixmap pixmap
= None
;
4270 height
= s
->height
- 2 * box_line_vwidth
;
4272 /* Fill background with face under the image. Do it only if row is
4273 taller than image or if image has a clip mask to reduce
4275 s
->stippled_p
= s
->face
->stipple
!= 0;
4276 if (height
> s
->img
->height
4280 || s
->img
->pixmap
== 0
4281 || s
->width
!= s
->background_width
)
4283 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
4284 x
= s
->x
+ box_line_hwidth
;
4288 y
= s
->y
+ box_line_vwidth
;
4292 /* Create a pixmap as large as the glyph string. Fill it
4293 with the background color. Copy the image to it, using
4294 its mask. Copy the temporary pixmap to the display. */
4295 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
4296 int depth
= DefaultDepthOfScreen (screen
);
4298 /* Create a pixmap as large as the glyph string. */
4299 pixmap
= XCreatePixmap (s
->display
, s
->window
,
4300 s
->background_width
,
4303 /* Don't clip in the following because we're working on the
4305 XSetClipMask (s
->display
, s
->gc
, None
);
4307 /* Fill the pixmap with the background color/stipple. */
4310 /* Fill background with a stipple pattern. */
4311 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4312 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4313 0, 0, s
->background_width
, s
->height
);
4314 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4319 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
4321 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
4322 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4323 0, 0, s
->background_width
, s
->height
);
4324 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4328 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
4330 s
->background_filled_p
= 1;
4333 /* Draw the foreground. */
4336 x_draw_image_foreground_1 (s
, pixmap
);
4337 x_set_glyph_string_clipping (s
);
4338 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
4339 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
4340 XFreePixmap (s
->display
, pixmap
);
4343 x_draw_image_foreground (s
);
4345 /* If we must draw a relief around the image, do it. */
4347 || s
->hl
== DRAW_IMAGE_RAISED
4348 || s
->hl
== DRAW_IMAGE_SUNKEN
)
4349 x_draw_image_relief (s
);
4353 /* Draw stretch glyph string S. */
4356 x_draw_stretch_glyph_string (s
)
4357 struct glyph_string
*s
;
4359 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4360 s
->stippled_p
= s
->face
->stipple
!= 0;
4362 if (s
->hl
== DRAW_CURSOR
4363 && !x_stretch_cursor_p
)
4365 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4366 as wide as the stretch glyph. */
4367 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
4370 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
4372 /* Clear rest using the GC of the original non-cursor face. */
4373 if (width
< s
->background_width
)
4375 int x
= s
->x
+ width
, y
= s
->y
;
4376 int w
= s
->background_width
- width
, h
= s
->height
;
4380 if (s
->row
->mouse_face_p
4381 && cursor_in_mouse_face_p (s
->w
))
4383 x_set_mouse_face_gc (s
);
4389 x_get_glyph_string_clip_rect (s
, &r
);
4390 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
4392 if (s
->face
->stipple
)
4394 /* Fill background with a stipple pattern. */
4395 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
4396 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4397 XSetFillStyle (s
->display
, gc
, FillSolid
);
4402 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
4403 XSetForeground (s
->display
, gc
, xgcv
.background
);
4404 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4405 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
4409 else if (!s
->background_filled_p
)
4410 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
4413 s
->background_filled_p
= 1;
4417 /* Draw glyph string S. */
4420 x_draw_glyph_string (s
)
4421 struct glyph_string
*s
;
4423 int relief_drawn_p
= 0;
4425 /* If S draws into the background of its successor, draw the
4426 background of the successor first so that S can draw into it.
4427 This makes S->next use XDrawString instead of XDrawImageString. */
4428 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
4430 xassert (s
->next
->img
== NULL
);
4431 x_set_glyph_string_gc (s
->next
);
4432 x_set_glyph_string_clipping (s
->next
);
4433 x_draw_glyph_string_background (s
->next
, 1);
4436 /* Set up S->gc, set clipping and draw S. */
4437 x_set_glyph_string_gc (s
);
4439 /* Draw relief (if any) in advance for char/composition so that the
4440 glyph string can be drawn over it. */
4441 if (!s
->for_overlaps_p
4442 && s
->face
->box
!= FACE_NO_BOX
4443 && (s
->first_glyph
->type
== CHAR_GLYPH
4444 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4447 x_set_glyph_string_clipping (s
);
4448 x_draw_glyph_string_background (s
, 1);
4449 x_draw_glyph_string_box (s
);
4450 x_set_glyph_string_clipping (s
);
4454 x_set_glyph_string_clipping (s
);
4456 switch (s
->first_glyph
->type
)
4459 x_draw_image_glyph_string (s
);
4463 x_draw_stretch_glyph_string (s
);
4467 if (s
->for_overlaps_p
)
4468 s
->background_filled_p
= 1;
4470 x_draw_glyph_string_background (s
, 0);
4471 x_draw_glyph_string_foreground (s
);
4474 case COMPOSITE_GLYPH
:
4475 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4476 s
->background_filled_p
= 1;
4478 x_draw_glyph_string_background (s
, 1);
4479 x_draw_composite_glyph_string_foreground (s
);
4486 if (!s
->for_overlaps_p
)
4488 /* Draw underline. */
4489 if (s
->face
->underline_p
)
4491 unsigned long tem
, h
;
4494 /* Get the underline thickness. Default is 1 pixel. */
4495 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4498 /* Get the underline position. This is the recommended
4499 vertical offset in pixels from the baseline to the top of
4500 the underline. This is a signed value according to the
4501 specs, and its default is
4503 ROUND ((maximum descent) / 2), with
4504 ROUND(x) = floor (x + 0.5) */
4506 if (x_use_underline_position_properties
4507 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4508 y
= s
->ybase
+ (long) tem
;
4509 else if (s
->face
->font
)
4510 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4512 y
= s
->y
+ s
->height
- h
;
4514 if (s
->face
->underline_defaulted_p
)
4515 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4516 s
->x
, y
, s
->width
, h
);
4520 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4521 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4522 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4523 s
->x
, y
, s
->width
, h
);
4524 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4528 /* Draw overline. */
4529 if (s
->face
->overline_p
)
4531 unsigned long dy
= 0, h
= 1;
4533 if (s
->face
->overline_color_defaulted_p
)
4534 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4539 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4540 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4541 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4543 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4547 /* Draw strike-through. */
4548 if (s
->face
->strike_through_p
)
4550 unsigned long h
= 1;
4551 unsigned long dy
= (s
->height
- h
) / 2;
4553 if (s
->face
->strike_through_color_defaulted_p
)
4554 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4559 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4560 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4561 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4563 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4567 /* Draw relief if not yet drawn. */
4568 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4569 x_draw_glyph_string_box (s
);
4572 /* Reset clipping. */
4573 XSetClipMask (s
->display
, s
->gc
, None
);
4577 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4578 struct face
**, int));
4581 /* Fill glyph string S with composition components specified by S->cmp.
4583 FACES is an array of faces for all components of this composition.
4584 S->gidx is the index of the first component for S.
4585 OVERLAPS_P non-zero means S should draw the foreground only, and
4586 use its physical height for clipping.
4588 Value is the index of a component not in S. */
4591 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4592 struct glyph_string
*s
;
4593 struct face
**faces
;
4600 s
->for_overlaps_p
= overlaps_p
;
4602 s
->face
= faces
[s
->gidx
];
4603 s
->font
= s
->face
->font
;
4604 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4606 /* For all glyphs of this composition, starting at the offset
4607 S->gidx, until we reach the end of the definition or encounter a
4608 glyph that requires the different face, add it to S. */
4610 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4613 /* All glyph strings for the same composition has the same width,
4614 i.e. the width set for the first component of the composition. */
4616 s
->width
= s
->first_glyph
->pixel_width
;
4618 /* If the specified font could not be loaded, use the frame's
4619 default font, but record the fact that we couldn't load it in
4620 the glyph string so that we can draw rectangles for the
4621 characters of the glyph string. */
4622 if (s
->font
== NULL
)
4624 s
->font_not_found_p
= 1;
4625 s
->font
= FRAME_FONT (s
->f
);
4628 /* Adjust base line for subscript/superscript text. */
4629 s
->ybase
+= s
->first_glyph
->voffset
;
4631 xassert (s
->face
&& s
->face
->gc
);
4633 /* This glyph string must always be drawn with 16-bit functions. */
4636 return s
->gidx
+ s
->nchars
;
4640 /* Fill glyph string S from a sequence of character glyphs.
4642 FACE_ID is the face id of the string. START is the index of the
4643 first glyph to consider, END is the index of the last + 1.
4644 OVERLAPS_P non-zero means S should draw the foreground only, and
4645 use its physical height for clipping.
4647 Value is the index of the first glyph not in S. */
4650 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4651 struct glyph_string
*s
;
4653 int start
, end
, overlaps_p
;
4655 struct glyph
*glyph
, *last
;
4657 int glyph_not_available_p
;
4659 xassert (s
->f
== XFRAME (s
->w
->frame
));
4660 xassert (s
->nchars
== 0);
4661 xassert (start
>= 0 && end
> start
);
4663 s
->for_overlaps_p
= overlaps_p
,
4664 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4665 last
= s
->row
->glyphs
[s
->area
] + end
;
4666 voffset
= glyph
->voffset
;
4668 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4671 && glyph
->type
== CHAR_GLYPH
4672 && glyph
->voffset
== voffset
4673 /* Same face id implies same font, nowadays. */
4674 && glyph
->face_id
== face_id
4675 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
4679 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4680 s
->char2b
+ s
->nchars
,
4682 s
->two_byte_p
= two_byte_p
;
4684 xassert (s
->nchars
<= end
- start
);
4685 s
->width
+= glyph
->pixel_width
;
4689 s
->font
= s
->face
->font
;
4690 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4692 /* If the specified font could not be loaded, use the frame's font,
4693 but record the fact that we couldn't load it in
4694 S->font_not_found_p so that we can draw rectangles for the
4695 characters of the glyph string. */
4696 if (s
->font
== NULL
|| glyph_not_available_p
)
4698 s
->font_not_found_p
= 1;
4699 s
->font
= FRAME_FONT (s
->f
);
4702 /* Adjust base line for subscript/superscript text. */
4703 s
->ybase
+= voffset
;
4705 xassert (s
->face
&& s
->face
->gc
);
4706 return glyph
- s
->row
->glyphs
[s
->area
];
4710 /* Fill glyph string S from image glyph S->first_glyph. */
4713 x_fill_image_glyph_string (s
)
4714 struct glyph_string
*s
;
4716 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4717 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
4719 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
4720 s
->font
= s
->face
->font
;
4721 s
->width
= s
->first_glyph
->pixel_width
;
4723 /* Adjust base line for subscript/superscript text. */
4724 s
->ybase
+= s
->first_glyph
->voffset
;
4728 /* Fill glyph string S from a sequence of stretch glyphs.
4730 ROW is the glyph row in which the glyphs are found, AREA is the
4731 area within the row. START is the index of the first glyph to
4732 consider, END is the index of the last + 1.
4734 Value is the index of the first glyph not in S. */
4737 x_fill_stretch_glyph_string (s
, row
, area
, start
, end
)
4738 struct glyph_string
*s
;
4739 struct glyph_row
*row
;
4740 enum glyph_row_area area
;
4743 struct glyph
*glyph
, *last
;
4744 int voffset
, face_id
;
4746 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4748 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4749 last
= s
->row
->glyphs
[s
->area
] + end
;
4750 face_id
= glyph
->face_id
;
4751 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
4752 s
->font
= s
->face
->font
;
4753 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4754 s
->width
= glyph
->pixel_width
;
4755 voffset
= glyph
->voffset
;
4759 && glyph
->type
== STRETCH_GLYPH
4760 && glyph
->voffset
== voffset
4761 && glyph
->face_id
== face_id
);
4763 s
->width
+= glyph
->pixel_width
;
4765 /* Adjust base line for subscript/superscript text. */
4766 s
->ybase
+= voffset
;
4768 /* The case that face->gc == 0 is handled when drawing the glyph
4769 string by calling PREPARE_FACE_FOR_DISPLAY. */
4771 return glyph
- s
->row
->glyphs
[s
->area
];
4775 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4776 of XChar2b structures for S; it can't be allocated in
4777 x_init_glyph_string because it must be allocated via `alloca'. W
4778 is the window on which S is drawn. ROW and AREA are the glyph row
4779 and area within the row from which S is constructed. START is the
4780 index of the first glyph structure covered by S. HL is a
4781 face-override for drawing S. */
4784 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4785 struct glyph_string
*s
;
4788 struct glyph_row
*row
;
4789 enum glyph_row_area area
;
4791 enum draw_glyphs_face hl
;
4793 bzero (s
, sizeof *s
);
4795 s
->f
= XFRAME (w
->frame
);
4796 s
->display
= FRAME_X_DISPLAY (s
->f
);
4797 s
->window
= FRAME_X_WINDOW (s
->f
);
4802 s
->first_glyph
= row
->glyphs
[area
] + start
;
4803 s
->height
= row
->height
;
4804 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4806 /* Display the internal border below the tool-bar window. */
4807 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4808 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4810 s
->ybase
= s
->y
+ row
->ascent
;
4814 /* Set background width of glyph string S. START is the index of the
4815 first glyph following S. LAST_X is the right-most x-position + 1
4816 in the drawing area. */
4819 x_set_glyph_string_background_width (s
, start
, last_x
)
4820 struct glyph_string
*s
;
4824 /* If the face of this glyph string has to be drawn to the end of
4825 the drawing area, set S->extends_to_end_of_line_p. */
4826 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4828 if (start
== s
->row
->used
[s
->area
]
4829 && s
->area
== TEXT_AREA
4830 && ((s
->hl
== DRAW_NORMAL_TEXT
4831 && (s
->row
->fill_line_p
4832 || s
->face
->background
!= default_face
->background
4833 || s
->face
->stipple
!= default_face
->stipple
4834 || s
->row
->mouse_face_p
))
4835 || s
->hl
== DRAW_MOUSE_FACE
4836 || ((s
->hl
== DRAW_IMAGE_RAISED
|| s
->hl
== DRAW_IMAGE_SUNKEN
)
4837 && s
->row
->fill_line_p
)))
4838 s
->extends_to_end_of_line_p
= 1;
4840 /* If S extends its face to the end of the line, set its
4841 background_width to the distance to the right edge of the drawing
4843 if (s
->extends_to_end_of_line_p
)
4844 s
->background_width
= last_x
- s
->x
+ 1;
4846 s
->background_width
= s
->width
;
4850 /* Add a glyph string for a stretch glyph to the list of strings
4851 between HEAD and TAIL. START is the index of the stretch glyph in
4852 row area AREA of glyph row ROW. END is the index of the last glyph
4853 in that glyph row area. X is the current output position assigned
4854 to the new glyph string constructed. HL overrides that face of the
4855 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4856 is the right-most x-position of the drawing area. */
4858 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4859 and below -- keep them on one line. */
4860 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4863 s = (struct glyph_string *) alloca (sizeof *s); \
4864 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4865 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4866 x_append_glyph_string (&HEAD, &TAIL, s); \
4872 /* Add a glyph string for an image glyph to the list of strings
4873 between HEAD and TAIL. START is the index of the image glyph in
4874 row area AREA of glyph row ROW. END is the index of the last glyph
4875 in that glyph row area. X is the current output position assigned
4876 to the new glyph string constructed. HL overrides that face of the
4877 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4878 is the right-most x-position of the drawing area. */
4880 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4883 s = (struct glyph_string *) alloca (sizeof *s); \
4884 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4885 x_fill_image_glyph_string (s); \
4886 x_append_glyph_string (&HEAD, &TAIL, s); \
4893 /* Add a glyph string for a sequence of character glyphs to the list
4894 of strings between HEAD and TAIL. START is the index of the first
4895 glyph in row area AREA of glyph row ROW that is part of the new
4896 glyph string. END is the index of the last glyph in that glyph row
4897 area. X is the current output position assigned to the new glyph
4898 string constructed. HL overrides that face of the glyph; e.g. it
4899 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4900 right-most x-position of the drawing area. */
4902 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4908 c = (ROW)->glyphs[AREA][START].u.ch; \
4909 face_id = (ROW)->glyphs[AREA][START].face_id; \
4911 s = (struct glyph_string *) alloca (sizeof *s); \
4912 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4913 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4914 x_append_glyph_string (&HEAD, &TAIL, s); \
4916 START = x_fill_glyph_string (s, face_id, START, END, \
4922 /* Add a glyph string for a composite sequence to the list of strings
4923 between HEAD and TAIL. START is the index of the first glyph in
4924 row area AREA of glyph row ROW that is part of the new glyph
4925 string. END is the index of the last glyph in that glyph row area.
4926 X is the current output position assigned to the new glyph string
4927 constructed. HL overrides that face of the glyph; e.g. it is
4928 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4929 x-position of the drawing area. */
4931 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4933 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4934 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4935 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4936 struct composition *cmp = composition_table[cmp_id]; \
4937 int glyph_len = cmp->glyph_len; \
4939 struct face **faces; \
4940 struct glyph_string *first_s = NULL; \
4943 base_face = base_face->ascii_face; \
4944 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4945 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4946 /* At first, fill in `char2b' and `faces'. */ \
4947 for (n = 0; n < glyph_len; n++) \
4949 int c = COMPOSITION_GLYPH (cmp, n); \
4950 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4951 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4952 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4953 this_face_id, char2b + n, 1); \
4956 /* Make glyph_strings for each glyph sequence that is drawable by \
4957 the same face, and append them to HEAD/TAIL. */ \
4958 for (n = 0; n < cmp->glyph_len;) \
4960 s = (struct glyph_string *) alloca (sizeof *s); \
4961 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4962 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4970 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4978 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4979 of AREA of glyph row ROW on window W between indices START and END.
4980 HL overrides the face for drawing glyph strings, e.g. it is
4981 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4982 x-positions of the drawing area.
4984 This is an ugly monster macro construct because we must use alloca
4985 to allocate glyph strings (because x_draw_glyphs can be called
4988 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4991 HEAD = TAIL = NULL; \
4992 while (START < END) \
4994 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4995 switch (first_glyph->type) \
4998 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4999 TAIL, HL, X, LAST_X, \
5003 case COMPOSITE_GLYPH: \
5004 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5005 HEAD, TAIL, HL, X, LAST_X,\
5009 case STRETCH_GLYPH: \
5010 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5011 HEAD, TAIL, HL, X, LAST_X); \
5015 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5016 TAIL, HL, X, LAST_X); \
5023 x_set_glyph_string_background_width (s, START, LAST_X); \
5030 /* Draw glyphs between START and END in AREA of ROW on window W,
5031 starting at x-position X. X is relative to AREA in W. HL is a
5032 face-override with the following meaning:
5034 DRAW_NORMAL_TEXT draw normally
5035 DRAW_CURSOR draw in cursor face
5036 DRAW_MOUSE_FACE draw in mouse face.
5037 DRAW_INVERSE_VIDEO draw in mode line face
5038 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5039 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5041 If OVERLAPS_P is non-zero, draw only the foreground of characters
5042 and clip to the physical height of ROW.
5044 Value is the x-position reached, relative to AREA of W. */
5047 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, overlaps_p
)
5050 struct glyph_row
*row
;
5051 enum glyph_row_area area
;
5053 enum draw_glyphs_face hl
;
5056 struct glyph_string
*head
, *tail
;
5057 struct glyph_string
*s
;
5058 int last_x
, area_width
;
5062 /* Let's rather be paranoid than getting a SEGV. */
5063 end
= min (end
, row
->used
[area
]);
5064 start
= max (0, start
);
5065 start
= min (end
, start
);
5067 /* Translate X to frame coordinates. Set last_x to the right
5068 end of the drawing area. */
5069 if (row
->full_width_p
)
5071 /* X is relative to the left edge of W, without scroll bars
5073 struct frame
*f
= XFRAME (w
->frame
);
5074 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
5077 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5078 last_x
= window_left_x
+ area_width
;
5080 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5082 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5083 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5089 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5090 last_x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5094 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
5095 area_width
= window_box_width (w
, area
);
5096 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
5099 /* Build a doubly-linked list of glyph_string structures between
5100 head and tail from what we have to draw. Note that the macro
5101 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5102 the reason we use a separate variable `i'. */
5104 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
5107 x_reached
= tail
->x
+ tail
->background_width
;
5111 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5112 the row, redraw some glyphs in front or following the glyph
5113 strings built above. */
5114 if (head
&& !overlaps_p
&& row
->contains_overlapping_glyphs_p
)
5117 struct glyph_string
*h
, *t
;
5119 /* Compute overhangs for all glyph strings. */
5120 for (s
= head
; s
; s
= s
->next
)
5121 x_compute_glyph_string_overhangs (s
);
5123 /* Prepend glyph strings for glyphs in front of the first glyph
5124 string that are overwritten because of the first glyph
5125 string's left overhang. The background of all strings
5126 prepended must be drawn because the first glyph string
5128 i
= x_left_overwritten (head
);
5132 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
5133 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5136 x_compute_overhangs_and_x (t
, head
->x
, 1);
5137 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5140 /* Prepend glyph strings for glyphs in front of the first glyph
5141 string that overwrite that glyph string because of their
5142 right overhang. For these strings, only the foreground must
5143 be drawn, because it draws over the glyph string at `head'.
5144 The background must not be drawn because this would overwrite
5145 right overhangs of preceding glyphs for which no glyph
5147 i
= x_left_overwriting (head
);
5150 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
5151 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5153 for (s
= h
; s
; s
= s
->next
)
5154 s
->background_filled_p
= 1;
5155 x_compute_overhangs_and_x (t
, head
->x
, 1);
5156 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5159 /* Append glyphs strings for glyphs following the last glyph
5160 string tail that are overwritten by tail. The background of
5161 these strings has to be drawn because tail's foreground draws
5163 i
= x_right_overwritten (tail
);
5166 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5167 DRAW_NORMAL_TEXT
, x
, last_x
,
5169 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5170 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5173 /* Append glyph strings for glyphs following the last glyph
5174 string tail that overwrite tail. The foreground of such
5175 glyphs has to be drawn because it writes into the background
5176 of tail. The background must not be drawn because it could
5177 paint over the foreground of following glyphs. */
5178 i
= x_right_overwriting (tail
);
5181 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5182 DRAW_NORMAL_TEXT
, x
, last_x
,
5184 for (s
= h
; s
; s
= s
->next
)
5185 s
->background_filled_p
= 1;
5186 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5187 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5191 /* Draw all strings. */
5192 for (s
= head
; s
; s
= s
->next
)
5193 x_draw_glyph_string (s
);
5195 if (area
== TEXT_AREA
5196 && !row
->full_width_p
5197 /* When drawing overlapping rows, only the glyph strings'
5198 foreground is drawn, which doesn't erase a cursor
5202 int x0
= head
? head
->x
: x
;
5203 int x1
= tail
? tail
->x
+ tail
->background_width
: x
;
5205 x0
= FRAME_TO_WINDOW_PIXEL_X (w
, x0
);
5206 x1
= FRAME_TO_WINDOW_PIXEL_X (w
, x1
);
5208 if (XFASTINT (w
->left_margin_width
) != 0)
5210 int left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5211 x0
-= left_area_width
;
5212 x1
-= left_area_width
;
5215 notice_overwritten_cursor (w
, area
, x0
, x1
,
5216 row
->y
, MATRIX_ROW_BOTTOM_Y (row
));
5219 /* Value is the x-position up to which drawn, relative to AREA of W.
5220 This doesn't include parts drawn because of overhangs. */
5221 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
5222 if (!row
->full_width_p
)
5224 if (area
> LEFT_MARGIN_AREA
&& XFASTINT (w
->left_margin_width
) != 0)
5225 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
5226 if (area
> TEXT_AREA
)
5227 x_reached
-= window_box_width (w
, TEXT_AREA
);
5234 /* Fix the display of area AREA of overlapping row ROW in window W. */
5237 x_fix_overlapping_area (w
, row
, area
)
5239 struct glyph_row
*row
;
5240 enum glyph_row_area area
;
5246 if (area
== LEFT_MARGIN_AREA
)
5248 else if (area
== TEXT_AREA
)
5249 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5251 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5252 + window_box_width (w
, TEXT_AREA
));
5254 for (i
= 0; i
< row
->used
[area
];)
5256 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
5258 int start
= i
, start_x
= x
;
5262 x
+= row
->glyphs
[area
][i
].pixel_width
;
5265 while (i
< row
->used
[area
]
5266 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
5268 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
5269 DRAW_NORMAL_TEXT
, 1);
5273 x
+= row
->glyphs
[area
][i
].pixel_width
;
5282 /* Output LEN glyphs starting at START at the nominal cursor position.
5283 Advance the nominal cursor over the text. The global variable
5284 updated_window contains the window being updated, updated_row is
5285 the glyph row being updated, and updated_area is the area of that
5286 row being updated. */
5289 x_write_glyphs (start
, len
)
5290 struct glyph
*start
;
5295 xassert (updated_window
&& updated_row
);
5300 hpos
= start
- updated_row
->glyphs
[updated_area
];
5301 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
5302 updated_row
, updated_area
,
5304 DRAW_NORMAL_TEXT
, 0);
5308 /* Advance the output cursor. */
5309 output_cursor
.hpos
+= len
;
5310 output_cursor
.x
= x
;
5314 /* Insert LEN glyphs from START at the nominal cursor position. */
5317 x_insert_glyphs (start
, len
)
5318 struct glyph
*start
;
5323 int line_height
, shift_by_width
, shifted_region_width
;
5324 struct glyph_row
*row
;
5325 struct glyph
*glyph
;
5326 int frame_x
, frame_y
, hpos
;
5328 xassert (updated_window
&& updated_row
);
5331 f
= XFRAME (WINDOW_FRAME (w
));
5333 /* Get the height of the line we are in. */
5335 line_height
= row
->height
;
5337 /* Get the width of the glyphs to insert. */
5339 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
5340 shift_by_width
+= glyph
->pixel_width
;
5342 /* Get the width of the region to shift right. */
5343 shifted_region_width
= (window_box_width (w
, updated_area
)
5348 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
5349 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
5350 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5351 f
->output_data
.x
->normal_gc
,
5353 shifted_region_width
, line_height
,
5354 frame_x
+ shift_by_width
, frame_y
);
5356 /* Write the glyphs. */
5357 hpos
= start
- row
->glyphs
[updated_area
];
5358 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
5359 DRAW_NORMAL_TEXT
, 0);
5361 /* Advance the output cursor. */
5362 output_cursor
.hpos
+= len
;
5363 output_cursor
.x
+= shift_by_width
;
5368 /* Delete N glyphs at the nominal cursor position. Not implemented
5379 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5380 If they are <= 0, this is probably an error. */
5383 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
5390 xassert (width
> 0 && height
> 0);
5391 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
5395 /* Erase the current text line from the nominal cursor position
5396 (inclusive) to pixel column TO_X (exclusive). The idea is that
5397 everything from TO_X onward is already erased.
5399 TO_X is a pixel position relative to updated_area of
5400 updated_window. TO_X == -1 means clear to the end of this area. */
5403 x_clear_end_of_line (to_x
)
5407 struct window
*w
= updated_window
;
5408 int max_x
, min_y
, max_y
;
5409 int from_x
, from_y
, to_y
;
5411 xassert (updated_window
&& updated_row
);
5412 f
= XFRAME (w
->frame
);
5414 if (updated_row
->full_width_p
)
5416 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5417 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5418 && !w
->pseudo_window_p
)
5419 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5422 max_x
= window_box_width (w
, updated_area
);
5423 max_y
= window_text_bottom_y (w
);
5425 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5426 of window. For TO_X > 0, truncate to end of drawing area. */
5432 to_x
= min (to_x
, max_x
);
5434 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
5436 /* Notice if the cursor will be cleared by this operation. */
5437 if (!updated_row
->full_width_p
)
5438 notice_overwritten_cursor (w
, updated_area
,
5439 output_cursor
.x
, -1,
5441 MATRIX_ROW_BOTTOM_Y (updated_row
));
5443 from_x
= output_cursor
.x
;
5445 /* Translate to frame coordinates. */
5446 if (updated_row
->full_width_p
)
5448 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
5449 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
5453 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
5454 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
5457 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
5458 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
5459 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
5461 /* Prevent inadvertently clearing to end of the X window. */
5462 if (to_x
> from_x
&& to_y
> from_y
)
5465 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5466 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
5473 /* Clear entire frame. If updating_frame is non-null, clear that
5474 frame. Otherwise clear the selected frame. */
5484 f
= SELECTED_FRAME ();
5486 /* Clearing the frame will erase any cursor, so mark them all as no
5488 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5489 output_cursor
.hpos
= output_cursor
.vpos
= 0;
5490 output_cursor
.x
= -1;
5492 /* We don't set the output cursor here because there will always
5493 follow an explicit cursor_to. */
5495 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5497 /* We have to clear the scroll bars, too. If we have changed
5498 colors or something like that, then they should be notified. */
5499 x_scroll_bar_clear (f
);
5501 XFlush (FRAME_X_DISPLAY (f
));
5507 /* Invert the middle quarter of the frame for .15 sec. */
5509 /* We use the select system call to do the waiting, so we have to make
5510 sure it's available. If it isn't, we just won't do visual bells. */
5512 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5515 /* Subtract the `struct timeval' values X and Y, storing the result in
5516 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5519 timeval_subtract (result
, x
, y
)
5520 struct timeval
*result
, x
, y
;
5522 /* Perform the carry for the later subtraction by updating y. This
5523 is safer because on some systems the tv_sec member is unsigned. */
5524 if (x
.tv_usec
< y
.tv_usec
)
5526 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
5527 y
.tv_usec
-= 1000000 * nsec
;
5531 if (x
.tv_usec
- y
.tv_usec
> 1000000)
5533 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
5534 y
.tv_usec
+= 1000000 * nsec
;
5538 /* Compute the time remaining to wait. tv_usec is certainly
5540 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5541 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5543 /* Return indication of whether the result should be considered
5545 return x
.tv_sec
< y
.tv_sec
;
5557 /* Create a GC that will use the GXxor function to flip foreground
5558 pixels into background pixels. */
5562 values
.function
= GXxor
;
5563 values
.foreground
= (f
->output_data
.x
->foreground_pixel
5564 ^ f
->output_data
.x
->background_pixel
);
5566 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5567 GCFunction
| GCForeground
, &values
);
5571 /* Get the height not including a menu bar widget. */
5572 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
5573 /* Height of each line to flash. */
5574 int flash_height
= FRAME_LINE_HEIGHT (f
);
5575 /* These will be the left and right margins of the rectangles. */
5576 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
5577 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
5581 /* Don't flash the area between a scroll bar and the frame
5582 edge it is next to. */
5583 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
5585 case vertical_scroll_bar_left
:
5586 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5589 case vertical_scroll_bar_right
:
5590 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5597 width
= flash_right
- flash_left
;
5599 /* If window is tall, flash top and bottom line. */
5600 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5602 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5604 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5605 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5606 width
, flash_height
);
5607 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5609 (height
- flash_height
5610 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5611 width
, flash_height
);
5614 /* If it is short, flash it all. */
5615 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5616 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5617 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5622 struct timeval wakeup
;
5624 EMACS_GET_TIME (wakeup
);
5626 /* Compute time to wait until, propagating carry from usecs. */
5627 wakeup
.tv_usec
+= 150000;
5628 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5629 wakeup
.tv_usec
%= 1000000;
5631 /* Keep waiting until past the time wakeup or any input gets
5633 while (! detect_input_pending ())
5635 struct timeval current
;
5636 struct timeval timeout
;
5638 EMACS_GET_TIME (current
);
5640 /* Break if result would be negative. */
5641 if (timeval_subtract (¤t
, wakeup
, current
))
5644 /* How long `select' should wait. */
5646 timeout
.tv_usec
= 10000;
5648 /* Try to wait that long--but we might wake up sooner. */
5649 select (0, NULL
, NULL
, NULL
, &timeout
);
5653 /* If window is tall, flash top and bottom line. */
5654 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5656 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5658 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5659 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5660 width
, flash_height
);
5661 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5663 (height
- flash_height
5664 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5665 width
, flash_height
);
5668 /* If it is short, flash it all. */
5669 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5670 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5671 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5673 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5681 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5684 /* Make audible bell. */
5689 struct frame
*f
= SELECTED_FRAME ();
5691 if (FRAME_X_DISPLAY (f
))
5693 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5700 XBell (FRAME_X_DISPLAY (f
), 0);
5701 XFlush (FRAME_X_DISPLAY (f
));
5708 /* Specify how many text lines, from the top of the window,
5709 should be affected by insert-lines and delete-lines operations.
5710 This, and those operations, are used only within an update
5711 that is bounded by calls to x_update_begin and x_update_end. */
5714 XTset_terminal_window (n
)
5717 /* This function intentionally left blank. */
5722 /***********************************************************************
5724 ***********************************************************************/
5726 /* Perform an insert-lines or delete-lines operation, inserting N
5727 lines or deleting -N lines at vertical position VPOS. */
5730 x_ins_del_lines (vpos
, n
)
5737 /* Scroll part of the display as described by RUN. */
5740 x_scroll_run (w
, run
)
5744 struct frame
*f
= XFRAME (w
->frame
);
5745 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5747 /* Get frame-relative bounding box of the text display area of W,
5748 without mode lines. Include in this box the left and right
5750 window_box (w
, -1, &x
, &y
, &width
, &height
);
5751 width
+= FRAME_X_FRINGE_WIDTH (f
);
5752 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
5754 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5755 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5756 bottom_y
= y
+ height
;
5760 /* Scrolling up. Make sure we don't copy part of the mode
5761 line at the bottom. */
5762 if (from_y
+ run
->height
> bottom_y
)
5763 height
= bottom_y
- from_y
;
5765 height
= run
->height
;
5769 /* Scolling down. Make sure we don't copy over the mode line.
5771 if (to_y
+ run
->height
> bottom_y
)
5772 height
= bottom_y
- to_y
;
5774 height
= run
->height
;
5779 /* Cursor off. Will be switched on again in x_update_window_end. */
5783 XCopyArea (FRAME_X_DISPLAY (f
),
5784 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5785 f
->output_data
.x
->normal_gc
,
5795 /***********************************************************************
5797 ***********************************************************************/
5799 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5800 corner of the exposed rectangle. W and H are width and height of
5801 the exposed area. All are pixel values. W or H zero means redraw
5802 the entire frame. */
5805 expose_frame (f
, x
, y
, w
, h
)
5810 int mouse_face_overwritten_p
= 0;
5812 TRACE ((stderr
, "expose_frame "));
5814 /* No need to redraw if frame will be redrawn soon. */
5815 if (FRAME_GARBAGED_P (f
))
5817 TRACE ((stderr
, " garbaged\n"));
5821 /* If basic faces haven't been realized yet, there is no point in
5822 trying to redraw anything. This can happen when we get an expose
5823 event while Emacs is starting, e.g. by moving another window. */
5824 if (FRAME_FACE_CACHE (f
) == NULL
5825 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5827 TRACE ((stderr
, " no faces\n"));
5831 if (w
== 0 || h
== 0)
5834 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5835 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5845 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5846 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
5848 if (WINDOWP (f
->tool_bar_window
))
5849 mouse_face_overwritten_p
5850 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
5852 #ifndef USE_X_TOOLKIT
5853 if (WINDOWP (f
->menu_bar_window
))
5854 mouse_face_overwritten_p
5855 |= expose_window (XWINDOW (f
->menu_bar_window
), &r
);
5856 #endif /* not USE_X_TOOLKIT */
5858 /* Some window managers support a focus-follows-mouse style with
5859 delayed raising of frames. Imagine a partially obscured frame,
5860 and moving the mouse into partially obscured mouse-face on that
5861 frame. The visible part of the mouse-face will be highlighted,
5862 then the WM raises the obscured frame. With at least one WM, KDE
5863 2.1, Emacs is not getting any event for the raising of the frame
5864 (even tried with SubstructureRedirectMask), only Expose events.
5865 These expose events will draw text normally, i.e. not
5866 highlighted. Which means we must redo the highlight here.
5867 Subsume it under ``we love X''. --gerd 2001-08-15 */
5868 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
5870 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5871 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5873 int x
= dpyinfo
->mouse_face_mouse_x
;
5874 int y
= dpyinfo
->mouse_face_mouse_y
;
5875 clear_mouse_face (dpyinfo
);
5876 note_mouse_highlight (f
, x
, y
);
5882 /* Redraw (parts) of all windows in the window tree rooted at W that
5883 intersect R. R contains frame pixel coordinates. Value is
5884 non-zero if the exposure overwrites mouse-face. */
5887 expose_window_tree (w
, r
)
5891 struct frame
*f
= XFRAME (w
->frame
);
5892 int mouse_face_overwritten_p
= 0;
5894 while (w
&& !FRAME_GARBAGED_P (f
))
5896 if (!NILP (w
->hchild
))
5897 mouse_face_overwritten_p
5898 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
5899 else if (!NILP (w
->vchild
))
5900 mouse_face_overwritten_p
5901 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
5903 mouse_face_overwritten_p
|= expose_window (w
, r
);
5905 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
5908 return mouse_face_overwritten_p
;
5912 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5913 which intersects rectangle R. R is in window-relative coordinates. */
5916 expose_area (w
, row
, r
, area
)
5918 struct glyph_row
*row
;
5920 enum glyph_row_area area
;
5922 struct glyph
*first
= row
->glyphs
[area
];
5923 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5925 int first_x
, start_x
, x
;
5927 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5928 /* If row extends face to end of line write the whole line. */
5929 x_draw_glyphs (w
, 0, row
, area
, 0, row
->used
[area
],
5930 DRAW_NORMAL_TEXT
, 0);
5933 /* Set START_X to the window-relative start position for drawing glyphs of
5934 AREA. The first glyph of the text area can be partially visible.
5935 The first glyphs of other areas cannot. */
5936 if (area
== LEFT_MARGIN_AREA
)
5938 else if (area
== TEXT_AREA
)
5939 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5941 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5942 + window_box_width (w
, TEXT_AREA
));
5945 /* Find the first glyph that must be redrawn. */
5947 && x
+ first
->pixel_width
< r
->x
)
5949 x
+= first
->pixel_width
;
5953 /* Find the last one. */
5957 && x
< r
->x
+ r
->width
)
5959 x
+= last
->pixel_width
;
5965 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
5966 first
- row
->glyphs
[area
],
5967 last
- row
->glyphs
[area
],
5968 DRAW_NORMAL_TEXT
, 0);
5973 /* Redraw the parts of the glyph row ROW on window W intersecting
5974 rectangle R. R is in window-relative coordinates. Value is
5975 non-zero if mouse-face was overwritten. */
5978 expose_line (w
, row
, r
)
5980 struct glyph_row
*row
;
5983 xassert (row
->enabled_p
);
5985 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5986 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5987 DRAW_NORMAL_TEXT
, 0);
5990 if (row
->used
[LEFT_MARGIN_AREA
])
5991 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5992 if (row
->used
[TEXT_AREA
])
5993 expose_area (w
, row
, r
, TEXT_AREA
);
5994 if (row
->used
[RIGHT_MARGIN_AREA
])
5995 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5996 x_draw_row_fringe_bitmaps (w
, row
);
5999 return row
->mouse_face_p
;
6003 /* Return non-zero if W's cursor intersects rectangle R. */
6006 x_phys_cursor_in_rect_p (w
, r
)
6010 XRectangle cr
, result
;
6011 struct glyph
*cursor_glyph
;
6013 cursor_glyph
= get_phys_cursor_glyph (w
);
6016 cr
.x
= w
->phys_cursor
.x
;
6017 cr
.y
= w
->phys_cursor
.y
;
6018 cr
.width
= cursor_glyph
->pixel_width
;
6019 cr
.height
= w
->phys_cursor_height
;
6020 return x_intersect_rectangles (&cr
, r
, &result
);
6027 /* Redraw the part of window W intersection rectangle FR. Pixel
6028 coordinates in FR are frame-relative. Call this function with
6029 input blocked. Value is non-zero if the exposure overwrites
6033 expose_window (w
, fr
)
6037 struct frame
*f
= XFRAME (w
->frame
);
6039 int mouse_face_overwritten_p
= 0;
6041 /* If window is not yet fully initialized, do nothing. This can
6042 happen when toolkit scroll bars are used and a window is split.
6043 Reconfiguring the scroll bar will generate an expose for a newly
6045 if (w
->current_matrix
== NULL
)
6048 /* When we're currently updating the window, display and current
6049 matrix usually don't agree. Arrange for a thorough display
6051 if (w
== updated_window
)
6053 SET_FRAME_GARBAGED (f
);
6057 /* Frame-relative pixel rectangle of W. */
6058 wr
.x
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
6059 wr
.y
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
6060 wr
.width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
6061 wr
.height
= XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
6063 if (x_intersect_rectangles (fr
, &wr
, &r
))
6065 int yb
= window_text_bottom_y (w
);
6066 struct glyph_row
*row
;
6067 int cursor_cleared_p
;
6069 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
6070 r
.x
, r
.y
, r
.width
, r
.height
));
6072 /* Convert to window coordinates. */
6073 r
.x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.x
);
6074 r
.y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.y
);
6076 /* Turn off the cursor. */
6077 if (!w
->pseudo_window_p
6078 && x_phys_cursor_in_rect_p (w
, &r
))
6081 cursor_cleared_p
= 1;
6084 cursor_cleared_p
= 0;
6086 /* Find the first row intersecting the rectangle R. */
6087 for (row
= w
->current_matrix
->rows
;
6092 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
6094 if ((y0
>= r
.y
&& y0
< r
.y
+ r
.height
)
6095 || (y1
> r
.y
&& y1
< r
.y
+ r
.height
)
6096 || (r
.y
>= y0
&& r
.y
< y1
)
6097 || (r
.y
+ r
.height
> y0
&& r
.y
+ r
.height
< y1
))
6099 if (expose_line (w
, row
, &r
))
6100 mouse_face_overwritten_p
= 1;
6107 /* Display the mode line if there is one. */
6108 if (WINDOW_WANTS_MODELINE_P (w
)
6109 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
6111 && row
->y
< r
.y
+ r
.height
)
6113 if (expose_line (w
, row
, &r
))
6114 mouse_face_overwritten_p
= 1;
6117 if (!w
->pseudo_window_p
)
6119 /* Draw border between windows. */
6120 x_draw_vertical_border (w
);
6122 /* Turn the cursor on again. */
6123 if (cursor_cleared_p
)
6124 x_update_window_cursor (w
, 1);
6128 return mouse_face_overwritten_p
;
6132 /* Determine the intersection of two rectangles R1 and R2. Return
6133 the intersection in *RESULT. Value is non-zero if RESULT is not
6137 x_intersect_rectangles (r1
, r2
, result
)
6138 XRectangle
*r1
, *r2
, *result
;
6140 XRectangle
*left
, *right
;
6141 XRectangle
*upper
, *lower
;
6142 int intersection_p
= 0;
6144 /* Rearrange so that R1 is the left-most rectangle. */
6146 left
= r1
, right
= r2
;
6148 left
= r2
, right
= r1
;
6150 /* X0 of the intersection is right.x0, if this is inside R1,
6151 otherwise there is no intersection. */
6152 if (right
->x
<= left
->x
+ left
->width
)
6154 result
->x
= right
->x
;
6156 /* The right end of the intersection is the minimum of the
6157 the right ends of left and right. */
6158 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
6161 /* Same game for Y. */
6163 upper
= r1
, lower
= r2
;
6165 upper
= r2
, lower
= r1
;
6167 /* The upper end of the intersection is lower.y0, if this is inside
6168 of upper. Otherwise, there is no intersection. */
6169 if (lower
->y
<= upper
->y
+ upper
->height
)
6171 result
->y
= lower
->y
;
6173 /* The lower end of the intersection is the minimum of the lower
6174 ends of upper and lower. */
6175 result
->height
= (min (lower
->y
+ lower
->height
,
6176 upper
->y
+ upper
->height
)
6182 return intersection_p
;
6193 /* We used to only do this if Vx_no_window_manager was non-nil, but
6194 the ICCCM (section 4.1.6) says that the window's border pixmap
6195 and border pixel are window attributes which are "private to the
6196 client", so we can always change it to whatever we want. */
6198 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6199 f
->output_data
.x
->border_pixel
);
6201 x_update_cursor (f
, 1);
6205 frame_unhighlight (f
)
6208 /* We used to only do this if Vx_no_window_manager was non-nil, but
6209 the ICCCM (section 4.1.6) says that the window's border pixmap
6210 and border pixel are window attributes which are "private to the
6211 client", so we can always change it to whatever we want. */
6213 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6214 f
->output_data
.x
->border_tile
);
6216 x_update_cursor (f
, 1);
6219 /* The focus has changed. Update the frames as necessary to reflect
6220 the new situation. Note that we can't change the selected frame
6221 here, because the Lisp code we are interrupting might become confused.
6222 Each event gets marked with the frame in which it occurred, so the
6223 Lisp code can tell when the switch took place by examining the events. */
6226 x_new_focus_frame (dpyinfo
, frame
)
6227 struct x_display_info
*dpyinfo
;
6228 struct frame
*frame
;
6230 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
6232 if (frame
!= dpyinfo
->x_focus_frame
)
6234 /* Set this before calling other routines, so that they see
6235 the correct value of x_focus_frame. */
6236 dpyinfo
->x_focus_frame
= frame
;
6238 if (old_focus
&& old_focus
->auto_lower
)
6239 x_lower_frame (old_focus
);
6242 selected_frame
= frame
;
6243 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
6245 Fselect_window (selected_frame
->selected_window
);
6246 choose_minibuf_frame ();
6249 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
6250 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
6252 pending_autoraise_frame
= 0;
6255 x_frame_rehighlight (dpyinfo
);
6258 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6261 x_mouse_leave (dpyinfo
)
6262 struct x_display_info
*dpyinfo
;
6264 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
6267 /* The focus has changed, or we have redirected a frame's focus to
6268 another frame (this happens when a frame uses a surrogate
6269 mini-buffer frame). Shift the highlight as appropriate.
6271 The FRAME argument doesn't necessarily have anything to do with which
6272 frame is being highlighted or un-highlighted; we only use it to find
6273 the appropriate X display info. */
6276 XTframe_rehighlight (frame
)
6277 struct frame
*frame
;
6279 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
6283 x_frame_rehighlight (dpyinfo
)
6284 struct x_display_info
*dpyinfo
;
6286 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
6288 if (dpyinfo
->x_focus_frame
)
6290 dpyinfo
->x_highlight_frame
6291 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
6292 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
6293 : dpyinfo
->x_focus_frame
);
6294 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
6296 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
6297 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
6301 dpyinfo
->x_highlight_frame
= 0;
6303 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
6306 frame_unhighlight (old_highlight
);
6307 if (dpyinfo
->x_highlight_frame
)
6308 frame_highlight (dpyinfo
->x_highlight_frame
);
6314 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6316 /* Initialize mode_switch_bit and modifier_meaning. */
6318 x_find_modifier_meanings (dpyinfo
)
6319 struct x_display_info
*dpyinfo
;
6321 int min_code
, max_code
;
6324 XModifierKeymap
*mods
;
6326 dpyinfo
->meta_mod_mask
= 0;
6327 dpyinfo
->shift_lock_mask
= 0;
6328 dpyinfo
->alt_mod_mask
= 0;
6329 dpyinfo
->super_mod_mask
= 0;
6330 dpyinfo
->hyper_mod_mask
= 0;
6333 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
6335 min_code
= dpyinfo
->display
->min_keycode
;
6336 max_code
= dpyinfo
->display
->max_keycode
;
6339 syms
= XGetKeyboardMapping (dpyinfo
->display
,
6340 min_code
, max_code
- min_code
+ 1,
6342 mods
= XGetModifierMapping (dpyinfo
->display
);
6344 /* Scan the modifier table to see which modifier bits the Meta and
6345 Alt keysyms are on. */
6347 int row
, col
; /* The row and column in the modifier table. */
6349 for (row
= 3; row
< 8; row
++)
6350 for (col
= 0; col
< mods
->max_keypermod
; col
++)
6353 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
6355 /* Zeroes are used for filler. Skip them. */
6359 /* Are any of this keycode's keysyms a meta key? */
6363 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
6365 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
6371 dpyinfo
->meta_mod_mask
|= (1 << row
);
6376 dpyinfo
->alt_mod_mask
|= (1 << row
);
6381 dpyinfo
->hyper_mod_mask
|= (1 << row
);
6386 dpyinfo
->super_mod_mask
|= (1 << row
);
6390 /* Ignore this if it's not on the lock modifier. */
6391 if ((1 << row
) == LockMask
)
6392 dpyinfo
->shift_lock_mask
= LockMask
;
6400 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6401 if (! dpyinfo
->meta_mod_mask
)
6403 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
6404 dpyinfo
->alt_mod_mask
= 0;
6407 /* If some keys are both alt and meta,
6408 make them just meta, not alt. */
6409 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
6411 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
6414 XFree ((char *) syms
);
6415 XFreeModifiermap (mods
);
6418 /* Convert between the modifier bits X uses and the modifier bits
6422 x_x_to_emacs_modifiers (dpyinfo
, state
)
6423 struct x_display_info
*dpyinfo
;
6426 EMACS_UINT mod_meta
= meta_modifier
;
6427 EMACS_UINT mod_alt
= alt_modifier
;
6428 EMACS_UINT mod_hyper
= hyper_modifier
;
6429 EMACS_UINT mod_super
= super_modifier
;
6432 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
6433 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
6434 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
6435 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
6436 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
6437 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
6438 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
6439 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
6442 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
6443 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
6444 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
6445 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
6446 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
6447 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
6451 x_emacs_to_x_modifiers (dpyinfo
, state
)
6452 struct x_display_info
*dpyinfo
;
6455 EMACS_UINT mod_meta
= meta_modifier
;
6456 EMACS_UINT mod_alt
= alt_modifier
;
6457 EMACS_UINT mod_hyper
= hyper_modifier
;
6458 EMACS_UINT mod_super
= super_modifier
;
6462 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
6463 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
6464 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
6465 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
6466 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
6467 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
6468 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
6469 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
6472 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
6473 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
6474 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
6475 | ((state
& shift_modifier
) ? ShiftMask
: 0)
6476 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
6477 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
6480 /* Convert a keysym to its name. */
6483 x_get_keysym_name (keysym
)
6489 value
= XKeysymToString (keysym
);
6497 /* Mouse clicks and mouse movement. Rah. */
6499 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6500 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6501 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6502 not force the value into range. */
6505 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
6507 register int pix_x
, pix_y
;
6508 register int *x
, *y
;
6512 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6513 even for negative values. */
6515 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
6517 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
6519 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
6520 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
6524 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
6525 bounds
->height
= f
->output_data
.x
->line_height
;
6526 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
6527 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
6534 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
6535 pix_x
= FRAME_WINDOW_WIDTH (f
);
6539 else if (pix_y
> f
->height
)
6548 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6549 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6550 can't tell the positions because W's display is not up to date,
6554 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
6557 int *frame_x
, *frame_y
;
6561 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
6562 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
6564 if (display_completed
)
6566 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6567 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
6568 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
6574 *frame_x
+= glyph
->pixel_width
;
6582 *frame_y
= *frame_x
= 0;
6586 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6587 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6592 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6594 If the event is a button press, then note that we have grabbed
6598 construct_mouse_click (result
, event
, f
)
6599 struct input_event
*result
;
6600 XButtonEvent
*event
;
6603 /* Make the event type no_event; we'll change that when we decide
6605 result
->kind
= mouse_click
;
6606 result
->code
= event
->button
- Button1
;
6607 result
->timestamp
= event
->time
;
6608 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6610 | (event
->type
== ButtonRelease
6614 XSETINT (result
->x
, event
->x
);
6615 XSETINT (result
->y
, event
->y
);
6616 XSETFRAME (result
->frame_or_window
, f
);
6622 /* Function to report a mouse movement to the mainstream Emacs code.
6623 The input handler calls this.
6625 We have received a mouse movement event, which is given in *event.
6626 If the mouse is over a different glyph than it was last time, tell
6627 the mainstream emacs code by setting mouse_moved. If not, ask for
6628 another motion event, so we can check again the next time it moves. */
6630 static XMotionEvent last_mouse_motion_event
;
6631 static Lisp_Object last_mouse_motion_frame
;
6634 note_mouse_movement (frame
, event
)
6636 XMotionEvent
*event
;
6638 last_mouse_movement_time
= event
->time
;
6639 last_mouse_motion_event
= *event
;
6640 XSETFRAME (last_mouse_motion_frame
, frame
);
6642 if (x_autoselect_window_p
)
6646 static Lisp_Object last_window
;
6648 window
= window_from_coordinates (frame
, event
->x
, event
->y
, &area
, 0);
6650 /* Window will be selected only when it is not selected now and
6651 last mouse movement event was not in it. Minubuffer window
6652 will be selected iff it is active. */
6653 if (!EQ (window
, last_window
)
6654 && !EQ (window
, selected_window
)
6655 && (!MINI_WINDOW_P (XWINDOW (window
))
6656 || (EQ (window
, minibuf_window
) && minibuf_level
> 0)))
6657 Fselect_window (window
);
6662 if (event
->window
!= FRAME_X_WINDOW (frame
))
6664 frame
->mouse_moved
= 1;
6665 last_mouse_scroll_bar
= Qnil
;
6666 note_mouse_highlight (frame
, -1, -1);
6669 /* Has the mouse moved off the glyph it was on at the last sighting? */
6670 else if (event
->x
< last_mouse_glyph
.x
6671 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6672 || event
->y
< last_mouse_glyph
.y
6673 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6675 frame
->mouse_moved
= 1;
6676 last_mouse_scroll_bar
= Qnil
;
6677 note_mouse_highlight (frame
, event
->x
, event
->y
);
6682 /************************************************************************
6684 ************************************************************************/
6686 /* Find the glyph under window-relative coordinates X/Y in window W.
6687 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6688 strings. Return in *HPOS and *VPOS the row and column number of
6689 the glyph found. Return in *AREA the glyph area containing X.
6690 Value is a pointer to the glyph found or null if X/Y is not on
6691 text, or we can't tell because W's current matrix is not up to
6694 static struct glyph
*
6695 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
6698 int *hpos
, *vpos
, *area
;
6701 struct glyph
*glyph
, *end
;
6702 struct glyph_row
*row
= NULL
;
6703 int x0
, i
, left_area_width
;
6705 /* Find row containing Y. Give up if some row is not enabled. */
6706 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6708 row
= MATRIX_ROW (w
->current_matrix
, i
);
6709 if (!row
->enabled_p
)
6711 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6718 /* Give up if Y is not in the window. */
6719 if (i
== w
->current_matrix
->nrows
)
6722 /* Get the glyph area containing X. */
6723 if (w
->pseudo_window_p
)
6730 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6731 if (x
< left_area_width
)
6733 *area
= LEFT_MARGIN_AREA
;
6736 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6739 x0
= row
->x
+ left_area_width
;
6743 *area
= RIGHT_MARGIN_AREA
;
6744 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6748 /* Find glyph containing X. */
6749 glyph
= row
->glyphs
[*area
];
6750 end
= glyph
+ row
->used
[*area
];
6753 if (x
< x0
+ glyph
->pixel_width
)
6755 if (w
->pseudo_window_p
)
6757 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
6761 x0
+= glyph
->pixel_width
;
6768 *hpos
= glyph
- row
->glyphs
[*area
];
6773 /* Convert frame-relative x/y to coordinates relative to window W.
6774 Takes pseudo-windows into account. */
6777 frame_to_window_pixel_xy (w
, x
, y
)
6781 if (w
->pseudo_window_p
)
6783 /* A pseudo-window is always full-width, and starts at the
6784 left edge of the frame, plus a frame border. */
6785 struct frame
*f
= XFRAME (w
->frame
);
6786 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6787 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6791 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6792 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6797 /* Take proper action when mouse has moved to the mode or header line of
6798 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6799 mode line. X is relative to the start of the text display area of
6800 W, so the width of fringes and scroll bars must be subtracted
6801 to get a position relative to the start of the mode line. */
6804 note_mode_line_highlight (w
, x
, mode_line_p
)
6808 struct frame
*f
= XFRAME (w
->frame
);
6809 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6810 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6811 struct glyph_row
*row
;
6814 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6816 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6820 struct glyph
*glyph
, *end
;
6821 Lisp_Object help
, map
;
6824 /* Find the glyph under X. */
6825 glyph
= row
->glyphs
[TEXT_AREA
];
6826 end
= glyph
+ row
->used
[TEXT_AREA
];
6827 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6828 + FRAME_X_LEFT_FRINGE_WIDTH (f
));
6831 && x
>= x0
+ glyph
->pixel_width
)
6833 x0
+= glyph
->pixel_width
;
6838 && STRINGP (glyph
->object
)
6839 && XSTRING (glyph
->object
)->intervals
6840 && glyph
->charpos
>= 0
6841 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6843 /* If we're on a string with `help-echo' text property,
6844 arrange for the help to be displayed. This is done by
6845 setting the global variable help_echo to the help string. */
6846 help
= Fget_text_property (make_number (glyph
->charpos
),
6847 Qhelp_echo
, glyph
->object
);
6851 XSETWINDOW (help_echo_window
, w
);
6852 help_echo_object
= glyph
->object
;
6853 help_echo_pos
= glyph
->charpos
;
6856 /* Change the mouse pointer according to what is under X/Y. */
6857 map
= Fget_text_property (make_number (glyph
->charpos
),
6858 Qlocal_map
, glyph
->object
);
6860 cursor
= f
->output_data
.x
->nontext_cursor
;
6863 map
= Fget_text_property (make_number (glyph
->charpos
),
6864 Qkeymap
, glyph
->object
);
6866 cursor
= f
->output_data
.x
->nontext_cursor
;
6871 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6875 /* Take proper action when the mouse has moved to position X, Y on
6876 frame F as regards highlighting characters that have mouse-face
6877 properties. Also de-highlighting chars where the mouse was before.
6878 X and Y can be negative or out of range. */
6881 note_mouse_highlight (f
, x
, y
)
6885 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6889 Cursor cursor
= None
;
6892 /* When a menu is active, don't highlight because this looks odd. */
6893 #ifdef USE_X_TOOLKIT
6894 if (popup_activated ())
6898 if (NILP (Vmouse_highlight
)
6899 || !f
->glyphs_initialized_p
)
6902 dpyinfo
->mouse_face_mouse_x
= x
;
6903 dpyinfo
->mouse_face_mouse_y
= y
;
6904 dpyinfo
->mouse_face_mouse_frame
= f
;
6906 if (dpyinfo
->mouse_face_defer
)
6911 dpyinfo
->mouse_face_deferred_gc
= 1;
6915 /* Which window is that in? */
6916 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6918 /* If we were displaying active text in another window, clear that. */
6919 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6920 clear_mouse_face (dpyinfo
);
6922 /* Not on a window -> return. */
6923 if (!WINDOWP (window
))
6926 /* Convert to window-relative pixel coordinates. */
6927 w
= XWINDOW (window
);
6928 frame_to_window_pixel_xy (w
, &x
, &y
);
6930 /* Handle tool-bar window differently since it doesn't display a
6932 if (EQ (window
, f
->tool_bar_window
))
6934 note_tool_bar_highlight (f
, x
, y
);
6938 /* Mouse is on the mode or header line? */
6939 if (portion
== 1 || portion
== 3)
6941 note_mode_line_highlight (w
, x
, portion
== 1);
6946 cursor
= f
->output_data
.x
->horizontal_drag_cursor
;
6948 cursor
= f
->output_data
.x
->text_cursor
;
6950 /* Are we in a window whose display is up to date?
6951 And verify the buffer's text has not changed. */
6952 b
= XBUFFER (w
->buffer
);
6953 if (/* Within text portion of the window. */
6955 && EQ (w
->window_end_valid
, w
->buffer
)
6956 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
6957 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
6959 int hpos
, vpos
, pos
, i
, area
;
6960 struct glyph
*glyph
;
6962 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
6963 Lisp_Object
*overlay_vec
= NULL
;
6965 struct buffer
*obuf
;
6966 int obegv
, ozv
, same_region
;
6968 /* Find the glyph under X/Y. */
6969 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
6971 /* Clear mouse face if X/Y not over text. */
6973 || area
!= TEXT_AREA
6974 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6976 if (clear_mouse_face (dpyinfo
))
6981 pos
= glyph
->charpos
;
6982 object
= glyph
->object
;
6983 if (!STRINGP (object
) && !BUFFERP (object
))
6986 /* If we get an out-of-range value, return now; avoid an error. */
6987 if (BUFFERP (object
) && pos
> BUF_Z (b
))
6990 /* Make the window's buffer temporarily current for
6991 overlays_at and compute_char_face. */
6992 obuf
= current_buffer
;
6999 /* Is this char mouse-active or does it have help-echo? */
7000 position
= make_number (pos
);
7002 if (BUFFERP (object
))
7004 /* Put all the overlays we want in a vector in overlay_vec.
7005 Store the length in len. If there are more than 10, make
7006 enough space for all, and try again. */
7008 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7009 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
7010 if (noverlays
> len
)
7013 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7014 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
7017 /* Sort overlays into increasing priority order. */
7018 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
7023 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
7024 && vpos
>= dpyinfo
->mouse_face_beg_row
7025 && vpos
<= dpyinfo
->mouse_face_end_row
7026 && (vpos
> dpyinfo
->mouse_face_beg_row
7027 || hpos
>= dpyinfo
->mouse_face_beg_col
)
7028 && (vpos
< dpyinfo
->mouse_face_end_row
7029 || hpos
< dpyinfo
->mouse_face_end_col
7030 || dpyinfo
->mouse_face_past_end
));
7035 /* Check mouse-face highlighting. */
7037 /* If there exists an overlay with mouse-face overlapping
7038 the one we are currently highlighting, we have to
7039 check if we enter the overlapping overlay, and then
7040 highlight only that. */
7041 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
7042 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
7044 /* Find the highest priority overlay that has a mouse-face
7047 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
7049 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
7050 if (!NILP (mouse_face
))
7051 overlay
= overlay_vec
[i
];
7054 /* If we're actually highlighting the same overlay as
7055 before, there's no need to do that again. */
7057 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
7058 goto check_help_echo
;
7060 dpyinfo
->mouse_face_overlay
= overlay
;
7062 /* Clear the display of the old active region, if any. */
7063 if (clear_mouse_face (dpyinfo
))
7066 /* If no overlay applies, get a text property. */
7068 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
7070 /* Handle the overlay case. */
7071 if (!NILP (overlay
))
7073 /* Find the range of text around this char that
7074 should be active. */
7075 Lisp_Object before
, after
;
7078 before
= Foverlay_start (overlay
);
7079 after
= Foverlay_end (overlay
);
7080 /* Record this as the current active region. */
7081 fast_find_position (w
, XFASTINT (before
),
7082 &dpyinfo
->mouse_face_beg_col
,
7083 &dpyinfo
->mouse_face_beg_row
,
7084 &dpyinfo
->mouse_face_beg_x
,
7085 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7087 dpyinfo
->mouse_face_past_end
7088 = !fast_find_position (w
, XFASTINT (after
),
7089 &dpyinfo
->mouse_face_end_col
,
7090 &dpyinfo
->mouse_face_end_row
,
7091 &dpyinfo
->mouse_face_end_x
,
7092 &dpyinfo
->mouse_face_end_y
, Qnil
);
7093 dpyinfo
->mouse_face_window
= window
;
7094 dpyinfo
->mouse_face_face_id
7095 = face_at_buffer_position (w
, pos
, 0, 0,
7096 &ignore
, pos
+ 1, 1);
7098 /* Display it as active. */
7099 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7102 /* Handle the text property case. */
7103 else if (!NILP (mouse_face
) && BUFFERP (object
))
7105 /* Find the range of text around this char that
7106 should be active. */
7107 Lisp_Object before
, after
, beginning
, end
;
7110 beginning
= Fmarker_position (w
->start
);
7111 end
= make_number (BUF_Z (XBUFFER (object
))
7112 - XFASTINT (w
->window_end_pos
));
7114 = Fprevious_single_property_change (make_number (pos
+ 1),
7118 = Fnext_single_property_change (position
, Qmouse_face
,
7121 /* Record this as the current active region. */
7122 fast_find_position (w
, XFASTINT (before
),
7123 &dpyinfo
->mouse_face_beg_col
,
7124 &dpyinfo
->mouse_face_beg_row
,
7125 &dpyinfo
->mouse_face_beg_x
,
7126 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7127 dpyinfo
->mouse_face_past_end
7128 = !fast_find_position (w
, XFASTINT (after
),
7129 &dpyinfo
->mouse_face_end_col
,
7130 &dpyinfo
->mouse_face_end_row
,
7131 &dpyinfo
->mouse_face_end_x
,
7132 &dpyinfo
->mouse_face_end_y
, Qnil
);
7133 dpyinfo
->mouse_face_window
= window
;
7135 if (BUFFERP (object
))
7136 dpyinfo
->mouse_face_face_id
7137 = face_at_buffer_position (w
, pos
, 0, 0,
7138 &ignore
, pos
+ 1, 1);
7140 /* Display it as active. */
7141 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7144 else if (!NILP (mouse_face
) && STRINGP (object
))
7149 b
= Fprevious_single_property_change (make_number (pos
+ 1),
7152 e
= Fnext_single_property_change (position
, Qmouse_face
,
7155 b
= make_number (0);
7157 e
= make_number (XSTRING (object
)->size
- 1);
7158 fast_find_string_pos (w
, XINT (b
), object
,
7159 &dpyinfo
->mouse_face_beg_col
,
7160 &dpyinfo
->mouse_face_beg_row
,
7161 &dpyinfo
->mouse_face_beg_x
,
7162 &dpyinfo
->mouse_face_beg_y
, 0);
7163 fast_find_string_pos (w
, XINT (e
), object
,
7164 &dpyinfo
->mouse_face_end_col
,
7165 &dpyinfo
->mouse_face_end_row
,
7166 &dpyinfo
->mouse_face_end_x
,
7167 &dpyinfo
->mouse_face_end_y
, 1);
7168 dpyinfo
->mouse_face_past_end
= 0;
7169 dpyinfo
->mouse_face_window
= window
;
7170 dpyinfo
->mouse_face_face_id
7171 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
7173 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7176 else if (STRINGP (object
) && NILP (mouse_face
))
7178 /* A string which doesn't have mouse-face, but
7179 the text ``under'' it might have. */
7180 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
7181 int start
= MATRIX_ROW_START_CHARPOS (r
);
7183 pos
= string_buffer_position (w
, object
, start
);
7185 mouse_face
= get_char_property_and_overlay (make_number (pos
),
7189 if (!NILP (mouse_face
) && !NILP (overlay
))
7191 Lisp_Object before
= Foverlay_start (overlay
);
7192 Lisp_Object after
= Foverlay_end (overlay
);
7195 /* Note that we might not be able to find position
7196 BEFORE in the glyph matrix if the overlay is
7197 entirely covered by a `display' property. In
7198 this case, we overshoot. So let's stop in
7199 the glyph matrix before glyphs for OBJECT. */
7200 fast_find_position (w
, XFASTINT (before
),
7201 &dpyinfo
->mouse_face_beg_col
,
7202 &dpyinfo
->mouse_face_beg_row
,
7203 &dpyinfo
->mouse_face_beg_x
,
7204 &dpyinfo
->mouse_face_beg_y
,
7207 dpyinfo
->mouse_face_past_end
7208 = !fast_find_position (w
, XFASTINT (after
),
7209 &dpyinfo
->mouse_face_end_col
,
7210 &dpyinfo
->mouse_face_end_row
,
7211 &dpyinfo
->mouse_face_end_x
,
7212 &dpyinfo
->mouse_face_end_y
,
7214 dpyinfo
->mouse_face_window
= window
;
7215 dpyinfo
->mouse_face_face_id
7216 = face_at_buffer_position (w
, pos
, 0, 0,
7217 &ignore
, pos
+ 1, 1);
7219 /* Display it as active. */
7220 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7228 /* Look for a `help-echo' property. */
7230 Lisp_Object help
, overlay
;
7232 /* Check overlays first. */
7233 help
= overlay
= Qnil
;
7234 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
7236 overlay
= overlay_vec
[i
];
7237 help
= Foverlay_get (overlay
, Qhelp_echo
);
7243 help_echo_window
= window
;
7244 help_echo_object
= overlay
;
7245 help_echo_pos
= pos
;
7249 Lisp_Object object
= glyph
->object
;
7250 int charpos
= glyph
->charpos
;
7252 /* Try text properties. */
7253 if (STRINGP (object
)
7255 && charpos
< XSTRING (object
)->size
)
7257 help
= Fget_text_property (make_number (charpos
),
7258 Qhelp_echo
, object
);
7261 /* If the string itself doesn't specify a help-echo,
7262 see if the buffer text ``under'' it does. */
7264 = MATRIX_ROW (w
->current_matrix
, vpos
);
7265 int start
= MATRIX_ROW_START_CHARPOS (r
);
7266 int pos
= string_buffer_position (w
, object
, start
);
7269 help
= Fget_char_property (make_number (pos
),
7270 Qhelp_echo
, w
->buffer
);
7279 else if (BUFFERP (object
)
7282 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
7288 help_echo_window
= window
;
7289 help_echo_object
= object
;
7290 help_echo_pos
= charpos
;
7297 current_buffer
= obuf
;
7303 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7307 redo_mouse_highlight ()
7309 if (!NILP (last_mouse_motion_frame
)
7310 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
7311 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
7312 last_mouse_motion_event
.x
,
7313 last_mouse_motion_event
.y
);
7318 /***********************************************************************
7320 ***********************************************************************/
7322 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
7323 struct glyph
**, int *, int *, int *));
7325 /* Tool-bar item index of the item on which a mouse button was pressed
7328 static int last_tool_bar_item
;
7331 /* Get information about the tool-bar item at position X/Y on frame F.
7332 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7333 the current matrix of the tool-bar window of F, or NULL if not
7334 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7335 item in F->tool_bar_items. Value is
7337 -1 if X/Y is not on a tool-bar item
7338 0 if X/Y is on the same item that was highlighted before.
7342 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
7345 struct glyph
**glyph
;
7346 int *hpos
, *vpos
, *prop_idx
;
7348 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7349 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7352 /* Find the glyph under X/Y. */
7353 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
7357 /* Get the start of this tool-bar item's properties in
7358 f->tool_bar_items. */
7359 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
7362 /* Is mouse on the highlighted item? */
7363 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
7364 && *vpos
>= dpyinfo
->mouse_face_beg_row
7365 && *vpos
<= dpyinfo
->mouse_face_end_row
7366 && (*vpos
> dpyinfo
->mouse_face_beg_row
7367 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
7368 && (*vpos
< dpyinfo
->mouse_face_end_row
7369 || *hpos
< dpyinfo
->mouse_face_end_col
7370 || dpyinfo
->mouse_face_past_end
))
7377 /* Handle mouse button event on the tool-bar of frame F, at
7378 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7382 x_handle_tool_bar_click (f
, button_event
)
7384 XButtonEvent
*button_event
;
7386 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7387 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7388 int hpos
, vpos
, prop_idx
;
7389 struct glyph
*glyph
;
7390 Lisp_Object enabled_p
;
7391 int x
= button_event
->x
;
7392 int y
= button_event
->y
;
7394 /* If not on the highlighted tool-bar item, return. */
7395 frame_to_window_pixel_xy (w
, &x
, &y
);
7396 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
7399 /* If item is disabled, do nothing. */
7400 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7401 if (NILP (enabled_p
))
7404 if (button_event
->type
== ButtonPress
)
7406 /* Show item in pressed state. */
7407 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
7408 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
7409 last_tool_bar_item
= prop_idx
;
7413 Lisp_Object key
, frame
;
7414 struct input_event event
;
7416 /* Show item in released state. */
7417 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
7418 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
7420 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
7422 XSETFRAME (frame
, f
);
7423 event
.kind
= TOOL_BAR_EVENT
;
7424 event
.frame_or_window
= frame
;
7426 kbd_buffer_store_event (&event
);
7428 event
.kind
= TOOL_BAR_EVENT
;
7429 event
.frame_or_window
= frame
;
7431 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
7432 button_event
->state
);
7433 kbd_buffer_store_event (&event
);
7434 last_tool_bar_item
= -1;
7439 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7440 tool-bar window-relative coordinates X/Y. Called from
7441 note_mouse_highlight. */
7444 note_tool_bar_highlight (f
, x
, y
)
7448 Lisp_Object window
= f
->tool_bar_window
;
7449 struct window
*w
= XWINDOW (window
);
7450 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7452 struct glyph
*glyph
;
7453 struct glyph_row
*row
;
7455 Lisp_Object enabled_p
;
7457 enum draw_glyphs_face draw
;
7458 int mouse_down_p
, rc
;
7460 /* Function note_mouse_highlight is called with negative x(y
7461 values when mouse moves outside of the frame. */
7462 if (x
<= 0 || y
<= 0)
7464 clear_mouse_face (dpyinfo
);
7468 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
7471 /* Not on tool-bar item. */
7472 clear_mouse_face (dpyinfo
);
7478 clear_mouse_face (dpyinfo
);
7480 /* Mouse is down, but on different tool-bar item? */
7481 mouse_down_p
= (dpyinfo
->grabbed
7482 && f
== last_mouse_frame
7483 && FRAME_LIVE_P (f
));
7485 && last_tool_bar_item
!= prop_idx
)
7488 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
7489 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
7491 /* If tool-bar item is not enabled, don't highlight it. */
7492 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7493 if (!NILP (enabled_p
))
7495 /* Compute the x-position of the glyph. In front and past the
7496 image is a space. We include this is the highlighted area. */
7497 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
7498 for (i
= x
= 0; i
< hpos
; ++i
)
7499 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
7501 /* Record this as the current active region. */
7502 dpyinfo
->mouse_face_beg_col
= hpos
;
7503 dpyinfo
->mouse_face_beg_row
= vpos
;
7504 dpyinfo
->mouse_face_beg_x
= x
;
7505 dpyinfo
->mouse_face_beg_y
= row
->y
;
7506 dpyinfo
->mouse_face_past_end
= 0;
7508 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
7509 dpyinfo
->mouse_face_end_row
= vpos
;
7510 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
7511 dpyinfo
->mouse_face_end_y
= row
->y
;
7512 dpyinfo
->mouse_face_window
= window
;
7513 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
7515 /* Display it as active. */
7516 show_mouse_face (dpyinfo
, draw
);
7517 dpyinfo
->mouse_face_image_state
= draw
;
7522 /* Set help_echo to a help string to display for this tool-bar item.
7523 XTread_socket does the rest. */
7524 help_echo_object
= help_echo_window
= Qnil
;
7526 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
7527 if (NILP (help_echo
))
7528 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
7533 /* Find the glyph matrix position of buffer position CHARPOS in window
7534 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7535 current glyphs must be up to date. If CHARPOS is above window
7536 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7537 of last line in W. In the row containing CHARPOS, stop before glyphs
7538 having STOP as object. */
7540 #if 0 /* This is a version of fast_find_position that's more correct
7541 in the presence of hscrolling, for example. I didn't install
7542 it right away because the problem fixed is minor, it failed
7543 in 20.x as well, and I think it's too risky to install
7544 so near the release of 21.1. 2001-09-25 gerd. */
7547 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
7550 int *hpos
, *vpos
, *x
, *y
;
7553 struct glyph_row
*row
, *first
;
7554 struct glyph
*glyph
, *end
;
7555 int i
, past_end
= 0;
7557 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7558 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
7561 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
7563 *x
= *y
= *hpos
= *vpos
= 0;
7568 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
7575 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7577 glyph
= row
->glyphs
[TEXT_AREA
];
7578 end
= glyph
+ row
->used
[TEXT_AREA
];
7580 /* Skip over glyphs not having an object at the start of the row.
7581 These are special glyphs like truncation marks on terminal
7583 if (row
->displays_text_p
)
7585 && INTEGERP (glyph
->object
)
7586 && !EQ (stop
, glyph
->object
)
7587 && glyph
->charpos
< 0)
7589 *x
+= glyph
->pixel_width
;
7594 && !INTEGERP (glyph
->object
)
7595 && !EQ (stop
, glyph
->object
)
7596 && (!BUFFERP (glyph
->object
)
7597 || glyph
->charpos
< charpos
))
7599 *x
+= glyph
->pixel_width
;
7603 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
7610 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
7613 int *hpos
, *vpos
, *x
, *y
;
7618 int maybe_next_line_p
= 0;
7619 int line_start_position
;
7620 int yb
= window_text_bottom_y (w
);
7621 struct glyph_row
*row
, *best_row
;
7622 int row_vpos
, best_row_vpos
;
7625 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7626 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7630 if (row
->used
[TEXT_AREA
])
7631 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
7633 line_start_position
= 0;
7635 if (line_start_position
> pos
)
7637 /* If the position sought is the end of the buffer,
7638 don't include the blank lines at the bottom of the window. */
7639 else if (line_start_position
== pos
7640 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
7642 maybe_next_line_p
= 1;
7645 else if (line_start_position
> 0)
7648 best_row_vpos
= row_vpos
;
7651 if (row
->y
+ row
->height
>= yb
)
7658 /* Find the right column within BEST_ROW. */
7660 current_x
= best_row
->x
;
7661 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
7663 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
7664 int charpos
= glyph
->charpos
;
7666 if (BUFFERP (glyph
->object
))
7671 *vpos
= best_row_vpos
;
7676 else if (charpos
> pos
)
7679 else if (EQ (glyph
->object
, stop
))
7684 current_x
+= glyph
->pixel_width
;
7687 /* If we're looking for the end of the buffer,
7688 and we didn't find it in the line we scanned,
7689 use the start of the following line. */
7690 if (maybe_next_line_p
)
7695 current_x
= best_row
->x
;
7698 *vpos
= best_row_vpos
;
7699 *hpos
= lastcol
+ 1;
7708 /* Find the position of the glyph for position POS in OBJECT in
7709 window W's current matrix, and return in *X, *Y the pixel
7710 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7712 RIGHT_P non-zero means return the position of the right edge of the
7713 glyph, RIGHT_P zero means return the left edge position.
7715 If no glyph for POS exists in the matrix, return the position of
7716 the glyph with the next smaller position that is in the matrix, if
7717 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7718 exists in the matrix, return the position of the glyph with the
7719 next larger position in OBJECT.
7721 Value is non-zero if a glyph was found. */
7724 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
7728 int *hpos
, *vpos
, *x
, *y
;
7731 int yb
= window_text_bottom_y (w
);
7732 struct glyph_row
*r
;
7733 struct glyph
*best_glyph
= NULL
;
7734 struct glyph_row
*best_row
= NULL
;
7737 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7738 r
->enabled_p
&& r
->y
< yb
;
7741 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
7742 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
7745 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
7746 if (EQ (g
->object
, object
))
7748 if (g
->charpos
== pos
)
7755 else if (best_glyph
== NULL
7756 || ((abs (g
->charpos
- pos
)
7757 < abs (best_glyph
->charpos
- pos
))
7760 : g
->charpos
> pos
)))
7774 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
7778 *x
+= best_glyph
->pixel_width
;
7783 *vpos
= best_row
- w
->current_matrix
->rows
;
7786 return best_glyph
!= NULL
;
7790 /* Display the active region described by mouse_face_*
7791 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7794 show_mouse_face (dpyinfo
, draw
)
7795 struct x_display_info
*dpyinfo
;
7796 enum draw_glyphs_face draw
;
7798 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
7799 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7801 if (/* If window is in the process of being destroyed, don't bother
7803 w
->current_matrix
!= NULL
7804 /* Don't update mouse highlight if hidden */
7805 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
7806 /* Recognize when we are called to operate on rows that don't exist
7807 anymore. This can happen when a window is split. */
7808 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
7810 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
7811 struct glyph_row
*row
, *first
, *last
;
7813 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
7814 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
7816 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
7818 int start_hpos
, end_hpos
, start_x
;
7820 /* For all but the first row, the highlight starts at column 0. */
7823 start_hpos
= dpyinfo
->mouse_face_beg_col
;
7824 start_x
= dpyinfo
->mouse_face_beg_x
;
7833 end_hpos
= dpyinfo
->mouse_face_end_col
;
7835 end_hpos
= row
->used
[TEXT_AREA
];
7837 if (end_hpos
> start_hpos
)
7839 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
7840 start_hpos
, end_hpos
, draw
, 0);
7843 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
7847 /* When we've written over the cursor, arrange for it to
7848 be displayed again. */
7849 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
7850 x_display_cursor (w
, 1,
7851 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
7852 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
7855 /* Change the mouse cursor. */
7856 if (draw
== DRAW_NORMAL_TEXT
)
7857 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7858 f
->output_data
.x
->text_cursor
);
7859 else if (draw
== DRAW_MOUSE_FACE
)
7860 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7861 f
->output_data
.x
->cross_cursor
);
7863 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7864 f
->output_data
.x
->nontext_cursor
);
7867 /* Clear out the mouse-highlighted active region.
7868 Redraw it un-highlighted first. Value is non-zero if mouse
7869 face was actually drawn unhighlighted. */
7872 clear_mouse_face (dpyinfo
)
7873 struct x_display_info
*dpyinfo
;
7877 if (!NILP (dpyinfo
->mouse_face_window
))
7879 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
7883 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7884 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7885 dpyinfo
->mouse_face_window
= Qnil
;
7886 dpyinfo
->mouse_face_overlay
= Qnil
;
7891 /* Clear any mouse-face on window W. This function is part of the
7892 redisplay interface, and is called from try_window_id and similar
7893 functions to ensure the mouse-highlight is off. */
7896 x_clear_mouse_face (w
)
7899 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
7903 XSETWINDOW (window
, w
);
7904 if (EQ (window
, dpyinfo
->mouse_face_window
))
7905 clear_mouse_face (dpyinfo
);
7910 /* Just discard the mouse face information for frame F, if any.
7911 This is used when the size of F is changed. */
7914 cancel_mouse_face (f
)
7918 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7920 window
= dpyinfo
->mouse_face_window
;
7921 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
7923 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7924 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7925 dpyinfo
->mouse_face_window
= Qnil
;
7930 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
7933 /* Try to determine frame pixel position and size of the glyph under
7934 frame pixel coordinates X/Y on frame F . Return the position and
7935 size in *RECT. Value is non-zero if we could compute these
7939 glyph_rect (f
, x
, y
, rect
)
7945 int part
, found
= 0;
7947 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
7950 struct window
*w
= XWINDOW (window
);
7951 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7952 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
7954 frame_to_window_pixel_xy (w
, &x
, &y
);
7956 for (; !found
&& r
< end
&& r
->enabled_p
; ++r
)
7959 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
7960 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
7963 for (gx
= r
->x
; !found
&& g
< end
; gx
+= g
->pixel_width
, ++g
)
7966 rect
->width
= g
->pixel_width
;
7967 rect
->height
= r
->height
;
7968 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
7969 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
7979 /* Return the current position of the mouse.
7980 *FP should be a frame which indicates which display to ask about.
7982 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7983 and *PART to the frame, window, and scroll bar part that the mouse
7984 is over. Set *X and *Y to the portion and whole of the mouse's
7985 position on the scroll bar.
7987 If the mouse movement started elsewhere, set *FP to the frame the
7988 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7991 Set *TIME to the server time-stamp for the time at which the mouse
7992 was at this position.
7994 Don't store anything if we don't have a valid set of values to report.
7996 This clears the mouse_moved flag, so we can wait for the next mouse
8000 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
8003 Lisp_Object
*bar_window
;
8004 enum scroll_bar_part
*part
;
8006 unsigned long *time
;
8012 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
8013 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
8019 Window dummy_window
;
8022 Lisp_Object frame
, tail
;
8024 /* Clear the mouse-moved flag for every frame on this display. */
8025 FOR_EACH_FRAME (tail
, frame
)
8026 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
8027 XFRAME (frame
)->mouse_moved
= 0;
8029 last_mouse_scroll_bar
= Qnil
;
8031 /* Figure out which root window we're on. */
8032 XQueryPointer (FRAME_X_DISPLAY (*fp
),
8033 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
8035 /* The root window which contains the pointer. */
8038 /* Trash which we can't trust if the pointer is on
8039 a different screen. */
8042 /* The position on that root window. */
8045 /* More trash we can't trust. */
8048 /* Modifier keys and pointer buttons, about which
8050 (unsigned int *) &dummy
);
8052 /* Now we have a position on the root; find the innermost window
8053 containing the pointer. */
8057 int parent_x
= 0, parent_y
= 0;
8062 /* XTranslateCoordinates can get errors if the window
8063 structure is changing at the same time this function
8064 is running. So at least we must not crash from them. */
8066 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
8068 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
8069 && FRAME_LIVE_P (last_mouse_frame
))
8071 /* If mouse was grabbed on a frame, give coords for that frame
8072 even if the mouse is now outside it. */
8073 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
8075 /* From-window, to-window. */
8076 root
, FRAME_X_WINDOW (last_mouse_frame
),
8078 /* From-position, to-position. */
8079 root_x
, root_y
, &win_x
, &win_y
,
8083 f1
= last_mouse_frame
;
8089 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
8091 /* From-window, to-window. */
8094 /* From-position, to-position. */
8095 root_x
, root_y
, &win_x
, &win_y
,
8100 if (child
== None
|| child
== win
)
8108 /* Now we know that:
8109 win is the innermost window containing the pointer
8110 (XTC says it has no child containing the pointer),
8111 win_x and win_y are the pointer's position in it
8112 (XTC did this the last time through), and
8113 parent_x and parent_y are the pointer's position in win's parent.
8114 (They are what win_x and win_y were when win was child.
8115 If win is the root window, it has no parent, and
8116 parent_{x,y} are invalid, but that's okay, because we'll
8117 never use them in that case.) */
8119 /* Is win one of our frames? */
8120 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
8122 #ifdef USE_X_TOOLKIT
8123 /* If we end up with the menu bar window, say it's not
8126 && f1
->output_data
.x
->menubar_widget
8127 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
8129 #endif /* USE_X_TOOLKIT */
8132 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
8135 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
8137 /* If not, is it one of our scroll bars? */
8140 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
8144 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8150 if (f1
== 0 && insist
> 0)
8151 f1
= SELECTED_FRAME ();
8155 /* Ok, we found a frame. Store all the values.
8156 last_mouse_glyph is a rectangle used to reduce the
8157 generation of mouse events. To not miss any motion
8158 events, we must divide the frame into rectangles of the
8159 size of the smallest character that could be displayed
8160 on it, i.e. into the same rectangles that matrices on
8161 the frame are divided into. */
8163 int width
, height
, gx
, gy
;
8166 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
8167 last_mouse_glyph
= rect
;
8170 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
8171 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
8175 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8176 round down even for negative values. */
8181 gx
= (gx
+ width
- 1) / width
* width
;
8182 gy
= (gy
+ height
- 1) / height
* height
;
8184 last_mouse_glyph
.width
= width
;
8185 last_mouse_glyph
.height
= height
;
8186 last_mouse_glyph
.x
= gx
;
8187 last_mouse_glyph
.y
= gy
;
8193 XSETINT (*x
, win_x
);
8194 XSETINT (*y
, win_y
);
8195 *time
= last_mouse_movement_time
;
8204 #ifdef USE_X_TOOLKIT
8206 /* Atimer callback function for TIMER. Called every 0.1s to process
8207 Xt timeouts, if needed. We must avoid calling XtAppPending as
8208 much as possible because that function does an implicit XFlush
8209 that slows us down. */
8212 x_process_timeouts (timer
)
8213 struct atimer
*timer
;
8215 if (toolkit_scroll_bar_interaction
|| popup_activated_flag
)
8218 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
8219 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
8224 #endif /* USE_X_TOOLKIT */
8227 /* Scroll bar support. */
8229 /* Given an X window ID, find the struct scroll_bar which manages it.
8230 This can be called in GC, so we have to make sure to strip off mark
8233 static struct scroll_bar
*
8234 x_window_to_scroll_bar (window_id
)
8239 for (tail
= Vframe_list
;
8240 XGCTYPE (tail
) == Lisp_Cons
;
8243 Lisp_Object frame
, bar
, condemned
;
8245 frame
= XCAR (tail
);
8246 /* All elements of Vframe_list should be frames. */
8247 if (! GC_FRAMEP (frame
))
8250 /* Scan this frame's scroll bar list for a scroll bar with the
8252 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
8253 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
8254 /* This trick allows us to search both the ordinary and
8255 condemned scroll bar lists with one loop. */
8256 ! GC_NILP (bar
) || (bar
= condemned
,
8259 bar
= XSCROLL_BAR (bar
)->next
)
8260 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
8261 return XSCROLL_BAR (bar
);
8268 #if defined USE_LUCID
8270 /* Return the Lucid menu bar WINDOW is part of. Return null
8271 if WINDOW is not part of a menu bar. */
8274 x_window_to_menu_bar (window
)
8279 for (tail
= Vframe_list
;
8280 XGCTYPE (tail
) == Lisp_Cons
;
8283 Lisp_Object frame
= XCAR (tail
);
8284 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
8286 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
8293 #endif /* USE_LUCID */
8296 /************************************************************************
8298 ************************************************************************/
8300 #ifdef USE_TOOLKIT_SCROLL_BARS
8302 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
8303 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
8304 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
8305 struct scroll_bar
*));
8306 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
8310 /* Id of action hook installed for scroll bars. */
8312 static XtActionHookId action_hook_id
;
8314 /* Lisp window being scrolled. Set when starting to interact with
8315 a toolkit scroll bar, reset to nil when ending the interaction. */
8317 static Lisp_Object window_being_scrolled
;
8319 /* Last scroll bar part sent in xm_scroll_callback. */
8321 static int last_scroll_bar_part
;
8323 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8324 that movements of 1/20 of the screen size are mapped to up/down. */
8326 static Boolean xaw3d_arrow_scroll
;
8328 /* Whether the drag scrolling maintains the mouse at the top of the
8329 thumb. If not, resizing the thumb needs to be done more carefully
8330 to avoid jerkyness. */
8332 static Boolean xaw3d_pick_top
;
8335 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8336 bars are used.. The hook is responsible for detecting when
8337 the user ends an interaction with the scroll bar, and generates
8338 a `end-scroll' scroll_bar_click' event if so. */
8341 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
8344 XtPointer client_data
;
8348 Cardinal
*num_params
;
8354 scroll_bar_p
= XmIsScrollBar (widget
);
8355 end_action
= "Release";
8356 #else /* !USE_MOTIF i.e. use Xaw */
8357 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
8358 end_action
= "EndScroll";
8359 #endif /* USE_MOTIF */
8362 && strcmp (action_name
, end_action
) == 0
8363 && WINDOWP (window_being_scrolled
))
8367 x_send_scroll_bar_event (window_being_scrolled
,
8368 scroll_bar_end_scroll
, 0, 0);
8369 w
= XWINDOW (window_being_scrolled
);
8370 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
8371 window_being_scrolled
= Qnil
;
8372 last_scroll_bar_part
= -1;
8374 /* Xt timeouts no longer needed. */
8375 toolkit_scroll_bar_interaction
= 0;
8379 /* A vector of windows used for communication between
8380 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8382 static struct window
**scroll_bar_windows
;
8383 static int scroll_bar_windows_size
;
8386 /* Send a client message with message type Xatom_Scrollbar for a
8387 scroll action to the frame of WINDOW. PART is a value identifying
8388 the part of the scroll bar that was clicked on. PORTION is the
8389 amount to scroll of a whole of WHOLE. */
8392 x_send_scroll_bar_event (window
, part
, portion
, whole
)
8394 int part
, portion
, whole
;
8397 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
8398 struct window
*w
= XWINDOW (window
);
8399 struct frame
*f
= XFRAME (w
->frame
);
8404 /* Construct a ClientMessage event to send to the frame. */
8405 ev
->type
= ClientMessage
;
8406 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
8407 ev
->display
= FRAME_X_DISPLAY (f
);
8408 ev
->window
= FRAME_X_WINDOW (f
);
8411 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8412 not enough to store a pointer or Lisp_Object on a 64 bit system.
8413 So, store the window in scroll_bar_windows and pass the index
8414 into that array in the event. */
8415 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
8416 if (scroll_bar_windows
[i
] == NULL
)
8419 if (i
== scroll_bar_windows_size
)
8421 int new_size
= max (10, 2 * scroll_bar_windows_size
);
8422 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
8423 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
8425 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
8427 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
8428 scroll_bar_windows_size
= new_size
;
8431 scroll_bar_windows
[i
] = w
;
8432 ev
->data
.l
[0] = (long) i
;
8433 ev
->data
.l
[1] = (long) part
;
8434 ev
->data
.l
[2] = (long) 0;
8435 ev
->data
.l
[3] = (long) portion
;
8436 ev
->data
.l
[4] = (long) whole
;
8438 /* Make Xt timeouts work while the scroll bar is active. */
8439 toolkit_scroll_bar_interaction
= 1;
8441 /* Setting the event mask to zero means that the message will
8442 be sent to the client that created the window, and if that
8443 window no longer exists, no event will be sent. */
8444 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
8449 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8453 x_scroll_bar_to_input_event (event
, ievent
)
8455 struct input_event
*ievent
;
8457 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
8462 w
= scroll_bar_windows
[ev
->data
.l
[0]];
8463 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
8465 XSETWINDOW (window
, w
);
8466 f
= XFRAME (w
->frame
);
8468 ievent
->kind
= scroll_bar_click
;
8469 ievent
->frame_or_window
= window
;
8471 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
8472 ievent
->part
= ev
->data
.l
[1];
8473 ievent
->code
= ev
->data
.l
[2];
8474 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
8475 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
8476 ievent
->modifiers
= 0;
8482 /* Minimum and maximum values used for Motif scroll bars. */
8485 #define XM_SB_MAX 10000000
8486 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8489 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8490 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8491 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8494 xm_scroll_callback (widget
, client_data
, call_data
)
8496 XtPointer client_data
, call_data
;
8498 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8499 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
8500 int part
= -1, whole
= 0, portion
= 0;
8504 case XmCR_DECREMENT
:
8505 bar
->dragging
= Qnil
;
8506 part
= scroll_bar_up_arrow
;
8509 case XmCR_INCREMENT
:
8510 bar
->dragging
= Qnil
;
8511 part
= scroll_bar_down_arrow
;
8514 case XmCR_PAGE_DECREMENT
:
8515 bar
->dragging
= Qnil
;
8516 part
= scroll_bar_above_handle
;
8519 case XmCR_PAGE_INCREMENT
:
8520 bar
->dragging
= Qnil
;
8521 part
= scroll_bar_below_handle
;
8525 bar
->dragging
= Qnil
;
8526 part
= scroll_bar_to_top
;
8529 case XmCR_TO_BOTTOM
:
8530 bar
->dragging
= Qnil
;
8531 part
= scroll_bar_to_bottom
;
8537 int dragging_down_p
= (INTEGERP (bar
->dragging
)
8538 && XINT (bar
->dragging
) <= cs
->value
);
8540 /* Get the slider size. */
8542 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
8545 /* At the max position of the scroll bar, do a line-wise
8546 movement. Without doing anything, we would be called with
8547 the same cs->value again and again. If we want to make
8548 sure that we can reach the end of the buffer, we have to do
8551 Implementation note: setting bar->dragging always to
8552 cs->value gives a smoother movement at the max position.
8553 Setting it to nil when doing line-wise movement gives
8554 a better slider behavior. */
8556 if (cs
->value
+ slider_size
== XM_SB_MAX
8558 && last_scroll_bar_part
== scroll_bar_down_arrow
))
8560 part
= scroll_bar_down_arrow
;
8561 bar
->dragging
= Qnil
;
8565 whole
= XM_SB_RANGE
;
8566 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
8567 part
= scroll_bar_handle
;
8568 bar
->dragging
= make_number (cs
->value
);
8573 case XmCR_VALUE_CHANGED
:
8579 window_being_scrolled
= bar
->window
;
8580 last_scroll_bar_part
= part
;
8581 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
8586 #else /* !USE_MOTIF, i.e. Xaw. */
8589 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8590 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8591 scroll bar struct. CALL_DATA is a pointer to a float saying where
8595 xaw_jump_callback (widget
, client_data
, call_data
)
8597 XtPointer client_data
, call_data
;
8599 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8600 float top
= *(float *) call_data
;
8602 int whole
, portion
, height
;
8605 /* Get the size of the thumb, a value between 0 and 1. */
8607 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
8611 portion
= shown
< 1 ? top
* whole
: 0;
8613 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
8614 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8615 the bottom, so we force the scrolling whenever we see that we're
8616 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8617 we try to ensure that we always stay two pixels away from the
8619 part
= scroll_bar_down_arrow
;
8621 part
= scroll_bar_handle
;
8623 window_being_scrolled
= bar
->window
;
8624 bar
->dragging
= make_number (portion
);
8625 last_scroll_bar_part
= part
;
8626 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
8630 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8631 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8632 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8633 the scroll bar. CALL_DATA is an integer specifying the action that
8634 has taken place. It's magnitude is in the range 0..height of the
8635 scroll bar. Negative values mean scroll towards buffer start.
8636 Values < height of scroll bar mean line-wise movement. */
8639 xaw_scroll_callback (widget
, client_data
, call_data
)
8641 XtPointer client_data
, call_data
;
8643 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8644 int position
= (int) call_data
;
8648 /* Get the height of the scroll bar. */
8650 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
8653 if (abs (position
) >= height
)
8654 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
8656 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8657 it maps line-movement to call_data = max(5, height/20). */
8658 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
8659 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
8661 part
= scroll_bar_move_ratio
;
8663 window_being_scrolled
= bar
->window
;
8664 bar
->dragging
= Qnil
;
8665 last_scroll_bar_part
= part
;
8666 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
8670 #endif /* not USE_MOTIF */
8673 /* Create the widget for scroll bar BAR on frame F. Record the widget
8674 and X window of the scroll bar in BAR. */
8677 x_create_toolkit_scroll_bar (f
, bar
)
8679 struct scroll_bar
*bar
;
8685 char *scroll_bar_name
= "verticalScrollBar";
8686 unsigned long pixel
;
8691 /* Set resources. Create the widget. */
8692 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8693 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
8694 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
8695 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
8696 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
8697 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
8698 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
8700 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8703 XtSetArg (av
[ac
], XmNforeground
, pixel
);
8707 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8710 XtSetArg (av
[ac
], XmNbackground
, pixel
);
8714 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
8715 scroll_bar_name
, av
, ac
);
8717 /* Add one callback for everything that can happen. */
8718 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
8720 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
8722 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
8724 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
8726 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
8728 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
8730 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
8733 /* Realize the widget. Only after that is the X window created. */
8734 XtRealizeWidget (widget
);
8736 /* Set the cursor to an arrow. I didn't find a resource to do that.
8737 And I'm wondering why it hasn't an arrow cursor by default. */
8738 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
8739 f
->output_data
.x
->nontext_cursor
);
8741 #else /* !USE_MOTIF i.e. use Xaw */
8743 /* Set resources. Create the widget. The background of the
8744 Xaw3d scroll bar widget is a little bit light for my taste.
8745 We don't alter it here to let users change it according
8746 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8747 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8748 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
8749 /* For smoother scrolling with Xaw3d -sm */
8750 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8752 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8755 XtSetArg (av
[ac
], XtNforeground
, pixel
);
8759 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8762 XtSetArg (av
[ac
], XtNbackground
, pixel
);
8766 /* Top/bottom shadow colors. */
8768 /* Allocate them, if necessary. */
8769 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
8771 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8772 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
8773 &pixel
, 1.2, 0x8000))
8775 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
8777 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
8779 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8780 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
8781 &pixel
, 0.6, 0x4000))
8783 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
8786 /* Tell the toolkit about them. */
8787 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
8788 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
8789 /* We tried to allocate a color for the top/bottom shadow, and
8790 failed, so tell Xaw3d to use dithering instead. */
8792 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
8796 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8797 be more consistent with other emacs 3d colors, and since Xaw3d is
8798 not good at dealing with allocation failure. */
8800 /* This tells Xaw3d to use real colors instead of dithering for
8802 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
8805 /* Specify the colors. */
8806 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
8809 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
8812 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
8815 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
8820 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
8821 f
->output_data
.x
->edit_widget
, av
, ac
);
8825 char *val
= initial
;
8826 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
8827 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
8829 { /* ARROW_SCROLL */
8830 xaw3d_arrow_scroll
= True
;
8831 /* Isn't that just a personal preference ? -sm */
8832 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
8836 /* Define callbacks. */
8837 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
8838 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
8841 /* Realize the widget. Only after that is the X window created. */
8842 XtRealizeWidget (widget
);
8844 #endif /* !USE_MOTIF */
8846 /* Install an action hook that let's us detect when the user
8847 finishes interacting with a scroll bar. */
8848 if (action_hook_id
== 0)
8849 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
8851 /* Remember X window and widget in the scroll bar vector. */
8852 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
8853 xwindow
= XtWindow (widget
);
8854 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
8860 /* Set the thumb size and position of scroll bar BAR. We are currently
8861 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8864 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
8865 struct scroll_bar
*bar
;
8866 int portion
, position
, whole
;
8868 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8869 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
8876 top
= (float) position
/ whole
;
8877 shown
= (float) portion
/ whole
;
8886 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8887 is the scroll bar's maximum and MIN is the scroll bar's minimum
8889 size
= shown
* XM_SB_RANGE
;
8890 size
= min (size
, XM_SB_RANGE
);
8891 size
= max (size
, 1);
8893 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8894 value
= top
* XM_SB_RANGE
;
8895 value
= min (value
, XM_SB_MAX
- size
);
8896 value
= max (value
, XM_SB_MIN
);
8898 if (NILP (bar
->dragging
))
8899 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
8900 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
8901 /* This has the negative side effect that the slider value is
8902 not what it would be if we scrolled here using line-wise or
8903 page-wise movement. */
8904 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
8907 /* If currently dragging, only update the slider size.
8908 This reduces flicker effects. */
8909 int old_value
, old_size
, increment
, page_increment
;
8911 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
8912 &increment
, &page_increment
);
8913 XmScrollBarSetValues (widget
, old_value
,
8914 min (size
, XM_SB_RANGE
- old_value
),
8918 #else /* !USE_MOTIF i.e. use Xaw */
8920 float old_top
, old_shown
;
8922 XtVaGetValues (widget
,
8923 XtNtopOfThumb
, &old_top
,
8924 XtNshown
, &old_shown
,
8928 /* Massage the top+shown values. */
8929 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
8930 top
= max (0, min (1, top
));
8933 /* Keep two pixels available for moving the thumb down. */
8934 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
8936 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8937 check that your system's configuration file contains a define
8938 for `NARROWPROTO'. See s/freebsd.h for an example. */
8939 if (top
!= old_top
|| shown
!= old_shown
)
8941 if (NILP (bar
->dragging
))
8942 XawScrollbarSetThumb (widget
, top
, shown
);
8946 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
8947 int scroll_mode
= 0;
8949 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8950 if (xaw3d_arrow_scroll
)
8952 /* Xaw3d stupidly ignores resize requests while dragging
8953 so we have to make it believe it's not in dragging mode. */
8954 scroll_mode
= sb
->scrollbar
.scroll_mode
;
8955 if (scroll_mode
== 2)
8956 sb
->scrollbar
.scroll_mode
= 0;
8959 /* Try to make the scrolling a tad smoother. */
8960 if (!xaw3d_pick_top
)
8961 shown
= min (shown
, old_shown
);
8963 XawScrollbarSetThumb (widget
, top
, shown
);
8966 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
8967 sb
->scrollbar
.scroll_mode
= scroll_mode
;
8972 #endif /* !USE_MOTIF */
8977 #endif /* USE_TOOLKIT_SCROLL_BARS */
8981 /************************************************************************
8982 Scroll bars, general
8983 ************************************************************************/
8985 /* Create a scroll bar and return the scroll bar vector for it. W is
8986 the Emacs window on which to create the scroll bar. TOP, LEFT,
8987 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8990 static struct scroll_bar
*
8991 x_scroll_bar_create (w
, top
, left
, width
, height
)
8993 int top
, left
, width
, height
;
8995 struct frame
*f
= XFRAME (w
->frame
);
8996 struct scroll_bar
*bar
8997 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
9001 #ifdef USE_TOOLKIT_SCROLL_BARS
9002 x_create_toolkit_scroll_bar (f
, bar
);
9003 #else /* not USE_TOOLKIT_SCROLL_BARS */
9005 XSetWindowAttributes a
;
9009 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
9010 if (a
.background_pixel
== -1)
9011 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
9013 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
9014 | ButtonMotionMask
| PointerMotionHintMask
9016 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
9018 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
9020 /* Clear the area of W that will serve as a scroll bar. This is
9021 for the case that a window has been split horizontally. In
9022 this case, no clear_frame is generated to reduce flickering. */
9023 if (width
> 0 && height
> 0)
9024 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9026 window_box_height (w
), False
);
9028 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9029 /* Position and size of scroll bar. */
9030 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9032 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9034 /* Border width, depth, class, and visual. */
9041 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
9043 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9045 XSETWINDOW (bar
->window
, w
);
9046 XSETINT (bar
->top
, top
);
9047 XSETINT (bar
->left
, left
);
9048 XSETINT (bar
->width
, width
);
9049 XSETINT (bar
->height
, height
);
9050 XSETINT (bar
->start
, 0);
9051 XSETINT (bar
->end
, 0);
9052 bar
->dragging
= Qnil
;
9054 /* Add bar to its frame's list of scroll bars. */
9055 bar
->next
= FRAME_SCROLL_BARS (f
);
9057 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
9058 if (!NILP (bar
->next
))
9059 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
9061 /* Map the window/widget. */
9062 #ifdef USE_TOOLKIT_SCROLL_BARS
9064 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
9065 XtConfigureWidget (scroll_bar
,
9066 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9068 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9069 max (height
, 1), 0);
9070 XtMapWidget (scroll_bar
);
9072 #else /* not USE_TOOLKIT_SCROLL_BARS */
9073 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
9074 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9081 /* Draw BAR's handle in the proper position.
9083 If the handle is already drawn from START to END, don't bother
9084 redrawing it, unless REBUILD is non-zero; in that case, always
9085 redraw it. (REBUILD is handy for drawing the handle after expose
9088 Normally, we want to constrain the start and end of the handle to
9089 fit inside its rectangle, but if the user is dragging the scroll
9090 bar handle, we want to let them drag it down all the way, so that
9091 the bar's top is as far down as it goes; otherwise, there's no way
9092 to move to the very end of the buffer. */
9094 #ifndef USE_TOOLKIT_SCROLL_BARS
9097 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
9098 struct scroll_bar
*bar
;
9102 int dragging
= ! NILP (bar
->dragging
);
9103 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9104 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9105 GC gc
= f
->output_data
.x
->normal_gc
;
9107 /* If the display is already accurate, do nothing. */
9109 && start
== XINT (bar
->start
)
9110 && end
== XINT (bar
->end
))
9116 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
9117 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9118 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9120 /* Make sure the values are reasonable, and try to preserve
9121 the distance between start and end. */
9123 int length
= end
- start
;
9127 else if (start
> top_range
)
9129 end
= start
+ length
;
9133 else if (end
> top_range
&& ! dragging
)
9137 /* Store the adjusted setting in the scroll bar. */
9138 XSETINT (bar
->start
, start
);
9139 XSETINT (bar
->end
, end
);
9141 /* Clip the end position, just for display. */
9142 if (end
> top_range
)
9145 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9146 below top positions, to make sure the handle is always at least
9147 that many pixels tall. */
9148 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
9150 /* Draw the empty space above the handle. Note that we can't clear
9151 zero-height areas; that means "clear to end of window." */
9153 x_clear_area (FRAME_X_DISPLAY (f
), w
,
9154 /* x, y, width, height, and exposures. */
9155 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9156 VERTICAL_SCROLL_BAR_TOP_BORDER
,
9157 inside_width
, start
,
9160 /* Change to proper foreground color if one is specified. */
9161 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9162 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
9163 f
->output_data
.x
->scroll_bar_foreground_pixel
);
9165 /* Draw the handle itself. */
9166 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
9167 /* x, y, width, height */
9168 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9169 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
9170 inside_width
, end
- start
);
9172 /* Restore the foreground color of the GC if we changed it above. */
9173 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9174 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
9175 f
->output_data
.x
->foreground_pixel
);
9177 /* Draw the empty space below the handle. Note that we can't
9178 clear zero-height areas; that means "clear to end of window." */
9179 if (end
< inside_height
)
9180 x_clear_area (FRAME_X_DISPLAY (f
), w
,
9181 /* x, y, width, height, and exposures. */
9182 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9183 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
9184 inside_width
, inside_height
- end
,
9192 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9194 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9198 x_scroll_bar_remove (bar
)
9199 struct scroll_bar
*bar
;
9201 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9204 #ifdef USE_TOOLKIT_SCROLL_BARS
9205 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
9207 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
9210 /* Disassociate this scroll bar from its window. */
9211 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
9217 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9218 that we are displaying PORTION characters out of a total of WHOLE
9219 characters, starting at POSITION. If WINDOW has no scroll bar,
9223 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
9225 int portion
, whole
, position
;
9227 struct frame
*f
= XFRAME (w
->frame
);
9228 struct scroll_bar
*bar
;
9229 int top
, height
, left
, sb_left
, width
, sb_width
;
9230 int window_x
, window_y
, window_width
, window_height
;
9232 /* Get window dimensions. */
9233 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9235 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
9236 height
= window_height
;
9238 /* Compute the left edge of the scroll bar area. */
9239 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9240 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
9242 left
= XFASTINT (w
->left
);
9243 left
*= CANON_X_UNIT (f
);
9244 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
9246 /* Compute the width of the scroll bar which might be less than
9247 the width of the area reserved for the scroll bar. */
9248 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
9249 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
9253 /* Compute the left edge of the scroll bar. */
9254 #ifdef USE_TOOLKIT_SCROLL_BARS
9255 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9256 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
9258 sb_left
= left
+ (width
- sb_width
) / 2;
9260 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9261 sb_left
= left
+ width
- sb_width
;
9266 /* Does the scroll bar exist yet? */
9267 if (NILP (w
->vertical_scroll_bar
))
9269 if (width
> 0 && height
> 0)
9272 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9273 left
, top
, width
, height
, False
);
9277 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
9281 /* It may just need to be moved and resized. */
9282 unsigned int mask
= 0;
9284 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
9288 if (sb_left
!= XINT (bar
->left
))
9290 if (top
!= XINT (bar
->top
))
9292 if (sb_width
!= XINT (bar
->width
))
9294 if (height
!= XINT (bar
->height
))
9297 #ifdef USE_TOOLKIT_SCROLL_BARS
9299 /* Since toolkit scroll bars are smaller than the space reserved
9300 for them on the frame, we have to clear "under" them. */
9301 if (width
> 0 && height
> 0)
9302 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9303 left
, top
, width
, height
, False
);
9305 /* Move/size the scroll bar widget. */
9307 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
9308 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9310 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9311 max (height
, 1), 0);
9313 #else /* not USE_TOOLKIT_SCROLL_BARS */
9315 /* Clear areas not covered by the scroll bar because of
9316 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9317 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
9319 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9320 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9322 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9323 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9324 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9328 /* Clear areas not covered by the scroll bar because it's not as
9329 wide as the area reserved for it . This makes sure a
9330 previous mode line display is cleared after C-x 2 C-x 1, for
9333 int area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
9334 int rest
= area_width
- sb_width
;
9335 if (rest
> 0 && height
> 0)
9337 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
9338 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9339 left
+ area_width
- rest
, top
,
9340 rest
, height
, False
);
9342 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9343 left
, top
, rest
, height
, False
);
9347 /* Move/size the scroll bar window. */
9352 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
9354 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
9356 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
9360 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9362 /* Remember new settings. */
9363 XSETINT (bar
->left
, sb_left
);
9364 XSETINT (bar
->top
, top
);
9365 XSETINT (bar
->width
, sb_width
);
9366 XSETINT (bar
->height
, height
);
9371 #ifdef USE_TOOLKIT_SCROLL_BARS
9372 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
9373 #else /* not USE_TOOLKIT_SCROLL_BARS */
9374 /* Set the scroll bar's current state, unless we're currently being
9376 if (NILP (bar
->dragging
))
9378 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
9381 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
9384 int start
= ((double) position
* top_range
) / whole
;
9385 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
9386 x_scroll_bar_set_handle (bar
, start
, end
, 0);
9389 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9391 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
9395 /* The following three hooks are used when we're doing a thorough
9396 redisplay of the frame. We don't explicitly know which scroll bars
9397 are going to be deleted, because keeping track of when windows go
9398 away is a real pain - "Can you say set-window-configuration, boys
9399 and girls?" Instead, we just assert at the beginning of redisplay
9400 that *all* scroll bars are to be removed, and then save a scroll bar
9401 from the fiery pit when we actually redisplay its window. */
9403 /* Arrange for all scroll bars on FRAME to be removed at the next call
9404 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9405 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9408 XTcondemn_scroll_bars (frame
)
9411 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9412 while (! NILP (FRAME_SCROLL_BARS (frame
)))
9415 bar
= FRAME_SCROLL_BARS (frame
);
9416 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
9417 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
9418 XSCROLL_BAR (bar
)->prev
= Qnil
;
9419 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
9420 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
9421 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
9426 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9427 Note that WINDOW isn't necessarily condemned at all. */
9430 XTredeem_scroll_bar (window
)
9431 struct window
*window
;
9433 struct scroll_bar
*bar
;
9436 /* We can't redeem this window's scroll bar if it doesn't have one. */
9437 if (NILP (window
->vertical_scroll_bar
))
9440 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
9442 /* Unlink it from the condemned list. */
9443 f
= XFRAME (WINDOW_FRAME (window
));
9444 if (NILP (bar
->prev
))
9446 /* If the prev pointer is nil, it must be the first in one of
9448 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
9449 /* It's not condemned. Everything's fine. */
9451 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
9452 window
->vertical_scroll_bar
))
9453 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
9455 /* If its prev pointer is nil, it must be at the front of
9456 one or the other! */
9460 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
9462 if (! NILP (bar
->next
))
9463 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
9465 bar
->next
= FRAME_SCROLL_BARS (f
);
9467 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
9468 if (! NILP (bar
->next
))
9469 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
9472 /* Remove all scroll bars on FRAME that haven't been saved since the
9473 last call to `*condemn_scroll_bars_hook'. */
9476 XTjudge_scroll_bars (f
)
9479 Lisp_Object bar
, next
;
9481 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
9483 /* Clear out the condemned list now so we won't try to process any
9484 more events on the hapless scroll bars. */
9485 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
9487 for (; ! NILP (bar
); bar
= next
)
9489 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
9491 x_scroll_bar_remove (b
);
9494 b
->next
= b
->prev
= Qnil
;
9497 /* Now there should be no references to the condemned scroll bars,
9498 and they should get garbage-collected. */
9502 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9503 is a no-op when using toolkit scroll bars.
9505 This may be called from a signal handler, so we have to ignore GC
9509 x_scroll_bar_expose (bar
, event
)
9510 struct scroll_bar
*bar
;
9513 #ifndef USE_TOOLKIT_SCROLL_BARS
9515 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9516 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9517 GC gc
= f
->output_data
.x
->normal_gc
;
9518 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
9522 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
9524 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9525 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
9527 /* x, y, width, height */
9529 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
9530 XINT (bar
->height
) - 1);
9534 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9537 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9538 is set to something other than no_event, it is enqueued.
9540 This may be called from a signal handler, so we have to ignore GC
9543 #ifndef USE_TOOLKIT_SCROLL_BARS
9546 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
9547 struct scroll_bar
*bar
;
9549 struct input_event
*emacs_event
;
9551 if (! GC_WINDOWP (bar
->window
))
9554 emacs_event
->kind
= scroll_bar_click
;
9555 emacs_event
->code
= event
->xbutton
.button
- Button1
;
9556 emacs_event
->modifiers
9557 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9558 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
9559 event
->xbutton
.state
)
9560 | (event
->type
== ButtonRelease
9563 emacs_event
->frame_or_window
= bar
->window
;
9564 emacs_event
->arg
= Qnil
;
9565 emacs_event
->timestamp
= event
->xbutton
.time
;
9568 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9570 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9573 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9574 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
9577 if (y
> top_range
) y
= top_range
;
9579 if (y
< XINT (bar
->start
))
9580 emacs_event
->part
= scroll_bar_above_handle
;
9581 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
9582 emacs_event
->part
= scroll_bar_handle
;
9584 emacs_event
->part
= scroll_bar_below_handle
;
9586 /* Just because the user has clicked on the handle doesn't mean
9587 they want to drag it. Lisp code needs to be able to decide
9588 whether or not we're dragging. */
9590 /* If the user has just clicked on the handle, record where they're
9592 if (event
->type
== ButtonPress
9593 && emacs_event
->part
== scroll_bar_handle
)
9594 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
9597 /* If the user has released the handle, set it to its final position. */
9598 if (event
->type
== ButtonRelease
9599 && ! NILP (bar
->dragging
))
9601 int new_start
= y
- XINT (bar
->dragging
);
9602 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
9604 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
9605 bar
->dragging
= Qnil
;
9608 /* Same deal here as the other #if 0. */
9610 /* Clicks on the handle are always reported as occurring at the top of
9612 if (emacs_event
->part
== scroll_bar_handle
)
9613 emacs_event
->x
= bar
->start
;
9615 XSETINT (emacs_event
->x
, y
);
9617 XSETINT (emacs_event
->x
, y
);
9620 XSETINT (emacs_event
->y
, top_range
);
9624 /* Handle some mouse motion while someone is dragging the scroll bar.
9626 This may be called from a signal handler, so we have to ignore GC
9630 x_scroll_bar_note_movement (bar
, event
)
9631 struct scroll_bar
*bar
;
9634 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
9636 last_mouse_movement_time
= event
->xmotion
.time
;
9639 XSETVECTOR (last_mouse_scroll_bar
, bar
);
9641 /* If we're dragging the bar, display it. */
9642 if (! GC_NILP (bar
->dragging
))
9644 /* Where should the handle be now? */
9645 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
9647 if (new_start
!= XINT (bar
->start
))
9649 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
9651 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
9656 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9658 /* Return information to the user about the current position of the mouse
9659 on the scroll bar. */
9662 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
9664 Lisp_Object
*bar_window
;
9665 enum scroll_bar_part
*part
;
9667 unsigned long *time
;
9669 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
9670 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9671 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9673 Window dummy_window
;
9675 unsigned int dummy_mask
;
9679 /* Get the mouse's position relative to the scroll bar window, and
9681 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
9683 /* Root, child, root x and root y. */
9684 &dummy_window
, &dummy_window
,
9685 &dummy_coord
, &dummy_coord
,
9687 /* Position relative to scroll bar. */
9690 /* Mouse buttons and modifier keys. */
9697 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9700 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9702 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
9704 if (! NILP (bar
->dragging
))
9705 win_y
-= XINT (bar
->dragging
);
9709 if (win_y
> top_range
)
9713 *bar_window
= bar
->window
;
9715 if (! NILP (bar
->dragging
))
9716 *part
= scroll_bar_handle
;
9717 else if (win_y
< XINT (bar
->start
))
9718 *part
= scroll_bar_above_handle
;
9719 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
9720 *part
= scroll_bar_handle
;
9722 *part
= scroll_bar_below_handle
;
9724 XSETINT (*x
, win_y
);
9725 XSETINT (*y
, top_range
);
9728 last_mouse_scroll_bar
= Qnil
;
9731 *time
= last_mouse_movement_time
;
9737 /* The screen has been cleared so we may have changed foreground or
9738 background colors, and the scroll bars may need to be redrawn.
9739 Clear out the scroll bars, and ask for expose events, so we can
9743 x_scroll_bar_clear (f
)
9746 #ifndef USE_TOOLKIT_SCROLL_BARS
9749 /* We can have scroll bars even if this is 0,
9750 if we just turned off scroll bar mode.
9751 But in that case we should not clear them. */
9752 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
9753 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
9754 bar
= XSCROLL_BAR (bar
)->next
)
9755 XClearArea (FRAME_X_DISPLAY (f
),
9756 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
9758 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9761 /* This processes Expose events from the menu-bar specific X event
9762 loop in xmenu.c. This allows to redisplay the frame if necessary
9763 when handling menu-bar or pop-up items. */
9766 process_expose_from_menu (event
)
9770 struct x_display_info
*dpyinfo
;
9771 int frame_exposed_p
= 0;
9775 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
9776 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9779 if (f
->async_visible
== 0)
9781 f
->async_visible
= 1;
9782 f
->async_iconified
= 0;
9783 f
->output_data
.x
->has_been_visible
= 1;
9784 SET_FRAME_GARBAGED (f
);
9788 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
9789 event
.xexpose
.x
, event
.xexpose
.y
,
9790 event
.xexpose
.width
, event
.xexpose
.height
);
9791 frame_exposed_p
= 1;
9796 struct scroll_bar
*bar
9797 = x_window_to_scroll_bar (event
.xexpose
.window
);
9800 x_scroll_bar_expose (bar
, &event
);
9804 return frame_exposed_p
;
9807 /* Define a queue to save up SelectionRequest events for later handling. */
9809 struct selection_event_queue
9812 struct selection_event_queue
*next
;
9815 static struct selection_event_queue
*queue
;
9817 /* Nonzero means queue up certain events--don't process them yet. */
9819 static int x_queue_selection_requests
;
9821 /* Queue up an X event *EVENT, to be processed later. */
9824 x_queue_event (f
, event
)
9828 struct selection_event_queue
*queue_tmp
9829 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
9831 if (queue_tmp
!= NULL
)
9833 queue_tmp
->event
= *event
;
9834 queue_tmp
->next
= queue
;
9839 /* Take all the queued events and put them back
9840 so that they get processed afresh. */
9843 x_unqueue_events (display
)
9846 while (queue
!= NULL
)
9848 struct selection_event_queue
*queue_tmp
= queue
;
9849 XPutBackEvent (display
, &queue_tmp
->event
);
9850 queue
= queue_tmp
->next
;
9851 xfree ((char *)queue_tmp
);
9855 /* Start queuing SelectionRequest events. */
9858 x_start_queuing_selection_requests (display
)
9861 x_queue_selection_requests
++;
9864 /* Stop queuing SelectionRequest events. */
9867 x_stop_queuing_selection_requests (display
)
9870 x_queue_selection_requests
--;
9871 x_unqueue_events (display
);
9874 /* The main X event-reading loop - XTread_socket. */
9877 /* Time stamp of enter window event. This is only used by XTread_socket,
9878 but we have to put it out here, since static variables within functions
9879 sometimes don't work. */
9881 static Time enter_timestamp
;
9884 /* This holds the state XLookupString needs to implement dead keys
9885 and other tricks known as "compose processing". _X Window System_
9886 says that a portable program can't use this, but Stephen Gildea assures
9887 me that letting the compiler initialize it to zeros will work okay.
9889 This must be defined outside of XTread_socket, for the same reasons
9890 given for enter_timestamp, above. */
9892 static XComposeStatus compose_status
;
9894 /* Record the last 100 characters stored
9895 to help debug the loss-of-chars-during-GC problem. */
9897 static int temp_index
;
9898 static short temp_buffer
[100];
9900 /* Set this to nonzero to fake an "X I/O error"
9901 on a particular display. */
9903 struct x_display_info
*XTread_socket_fake_io_error
;
9905 /* When we find no input here, we occasionally do a no-op command
9906 to verify that the X server is still running and we can still talk with it.
9907 We try all the open displays, one by one.
9908 This variable is used for cycling thru the displays. */
9910 static struct x_display_info
*next_noop_dpyinfo
;
9912 #define SET_SAVED_MENU_EVENT(size) \
9915 if (f->output_data.x->saved_menu_event == 0) \
9916 f->output_data.x->saved_menu_event \
9917 = (XEvent *) xmalloc (sizeof (XEvent)); \
9918 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9919 if (numchars >= 1) \
9921 bufp->kind = menu_bar_activate_event; \
9922 XSETFRAME (bufp->frame_or_window, f); \
9931 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9932 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9934 /* Read events coming from the X server.
9935 This routine is called by the SIGIO handler.
9936 We return as soon as there are no more events to be read.
9938 Events representing keys are stored in buffer BUFP,
9939 which can hold up to NUMCHARS characters.
9940 We return the number of characters stored into the buffer,
9941 thus pretending to be `read'.
9943 EXPECTED is nonzero if the caller knows input is available. */
9946 XTread_socket (sd
, bufp
, numchars
, expected
)
9948 /* register */ struct input_event
*bufp
;
9949 /* register */ int numchars
;
9956 int event_found
= 0;
9957 struct x_display_info
*dpyinfo
;
9958 struct coding_system coding
;
9960 if (interrupt_input_blocked
)
9962 interrupt_input_pending
= 1;
9966 interrupt_input_pending
= 0;
9969 /* So people can tell when we have read the available input. */
9970 input_signal_count
++;
9973 abort (); /* Don't think this happens. */
9977 /* The input should be decoded if it is from XIM. Currently the
9978 locale of XIM is the same as that of the system. So, we can use
9979 Vlocale_coding_system which is initialized properly at Emacs
9981 setup_coding_system (Vlocale_coding_system
, &coding
);
9982 coding
.src_multibyte
= 0;
9983 coding
.dst_multibyte
= 1;
9984 /* The input is converted to events, thus we can't handle
9985 composition. Anyway, there's no XIM that gives us composition
9987 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
9989 /* Find the display we are supposed to read input for.
9990 It's the one communicating on descriptor SD. */
9991 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
9993 #if 0 /* This ought to be unnecessary; let's verify it. */
9995 /* If available, Xlib uses FIOSNBIO to make the socket
9996 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9997 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9998 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9999 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
10000 #endif /* ! defined (FIOSNBIO) */
10003 #if 0 /* This code can't be made to work, with multiple displays,
10004 and appears not to be used on any system any more.
10005 Also keyboard.c doesn't turn O_NDELAY on and off
10006 for X connections. */
10008 #ifndef HAVE_SELECT
10009 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
10011 extern int read_alarm_should_throw
;
10012 read_alarm_should_throw
= 1;
10013 XPeekEvent (dpyinfo
->display
, &event
);
10014 read_alarm_should_throw
= 0;
10016 #endif /* HAVE_SELECT */
10020 /* For debugging, this gives a way to fake an I/O error. */
10021 if (dpyinfo
== XTread_socket_fake_io_error
)
10023 XTread_socket_fake_io_error
= 0;
10024 x_io_error_quitter (dpyinfo
->display
);
10027 while (XPending (dpyinfo
->display
))
10029 XNextEvent (dpyinfo
->display
, &event
);
10033 /* Filter events for the current X input method.
10034 XFilterEvent returns non-zero if the input method has
10035 consumed the event. We pass the frame's X window to
10036 XFilterEvent because that's the one for which the IC
10038 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
10039 event
.xclient
.window
);
10040 if (XFilterEvent (&event
, f1
? FRAME_X_WINDOW (f1
) : None
))
10046 switch (event
.type
)
10048 case ClientMessage
:
10050 if (event
.xclient
.message_type
10051 == dpyinfo
->Xatom_wm_protocols
10052 && event
.xclient
.format
== 32)
10054 if (event
.xclient
.data
.l
[0]
10055 == dpyinfo
->Xatom_wm_take_focus
)
10057 /* Use x_any_window_to_frame because this
10058 could be the shell widget window
10059 if the frame has no title bar. */
10060 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
10062 /* Not quite sure this is needed -pd */
10063 if (f
&& FRAME_XIC (f
))
10064 XSetICFocus (FRAME_XIC (f
));
10066 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10067 instructs the WM to set the input focus automatically for
10068 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10069 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10070 it has set the focus. So, XSetInputFocus below is not
10073 The call to XSetInputFocus below has also caused trouble. In
10074 cases where the XSetInputFocus done by the WM and the one
10075 below are temporally close (on a fast machine), the call
10076 below can generate additional FocusIn events which confuse
10079 /* Since we set WM_TAKE_FOCUS, we must call
10080 XSetInputFocus explicitly. But not if f is null,
10081 since that might be an event for a deleted frame. */
10084 Display
*d
= event
.xclient
.display
;
10085 /* Catch and ignore errors, in case window has been
10086 iconified by a window manager such as GWM. */
10087 int count
= x_catch_errors (d
);
10088 XSetInputFocus (d
, event
.xclient
.window
,
10089 /* The ICCCM says this is
10090 the only valid choice. */
10092 event
.xclient
.data
.l
[1]);
10093 /* This is needed to detect the error
10094 if there is an error. */
10096 x_uncatch_errors (d
, count
);
10098 /* Not certain about handling scroll bars here */
10101 else if (event
.xclient
.data
.l
[0]
10102 == dpyinfo
->Xatom_wm_save_yourself
)
10104 /* Save state modify the WM_COMMAND property to
10105 something which can reinstate us. This notifies
10106 the session manager, who's looking for such a
10107 PropertyNotify. Can restart processing when
10108 a keyboard or mouse event arrives. */
10111 f
= x_top_window_to_frame (dpyinfo
,
10112 event
.xclient
.window
);
10114 /* This is just so we only give real data once
10115 for a single Emacs process. */
10116 if (f
== SELECTED_FRAME ())
10117 XSetCommand (FRAME_X_DISPLAY (f
),
10118 event
.xclient
.window
,
10119 initial_argv
, initial_argc
);
10121 XSetCommand (FRAME_X_DISPLAY (f
),
10122 event
.xclient
.window
,
10126 else if (event
.xclient
.data
.l
[0]
10127 == dpyinfo
->Xatom_wm_delete_window
)
10130 = x_any_window_to_frame (dpyinfo
,
10131 event
.xclient
.window
);
10138 bufp
->kind
= delete_window_event
;
10139 XSETFRAME (bufp
->frame_or_window
, f
);
10148 else if (event
.xclient
.message_type
10149 == dpyinfo
->Xatom_wm_configure_denied
)
10152 else if (event
.xclient
.message_type
10153 == dpyinfo
->Xatom_wm_window_moved
)
10157 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
10159 new_x
= event
.xclient
.data
.s
[0];
10160 new_y
= event
.xclient
.data
.s
[1];
10164 f
->output_data
.x
->left_pos
= new_x
;
10165 f
->output_data
.x
->top_pos
= new_y
;
10168 #ifdef HACK_EDITRES
10169 else if (event
.xclient
.message_type
10170 == dpyinfo
->Xatom_editres
)
10173 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
10174 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
10177 #endif /* HACK_EDITRES */
10178 else if ((event
.xclient
.message_type
10179 == dpyinfo
->Xatom_DONE
)
10180 || (event
.xclient
.message_type
10181 == dpyinfo
->Xatom_PAGE
))
10183 /* Ghostview job completed. Kill it. We could
10184 reply with "Next" if we received "Page", but we
10185 currently never do because we are interested in
10186 images, only, which should have 1 page. */
10187 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
10189 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
10190 x_kill_gs_process (pixmap
, f
);
10191 expose_frame (f
, 0, 0, 0, 0);
10193 #ifdef USE_TOOLKIT_SCROLL_BARS
10194 /* Scroll bar callbacks send a ClientMessage from which
10195 we construct an input_event. */
10196 else if (event
.xclient
.message_type
10197 == dpyinfo
->Xatom_Scrollbar
)
10199 x_scroll_bar_to_input_event (&event
, bufp
);
10200 ++bufp
, ++count
, --numchars
;
10203 #endif /* USE_TOOLKIT_SCROLL_BARS */
10209 case SelectionNotify
:
10210 #ifdef USE_X_TOOLKIT
10211 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
10213 #endif /* not USE_X_TOOLKIT */
10214 x_handle_selection_notify (&event
.xselection
);
10217 case SelectionClear
: /* Someone has grabbed ownership. */
10218 #ifdef USE_X_TOOLKIT
10219 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
10221 #endif /* USE_X_TOOLKIT */
10223 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
10228 bufp
->kind
= selection_clear_event
;
10229 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
10230 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
10231 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
10232 bufp
->frame_or_window
= Qnil
;
10241 case SelectionRequest
: /* Someone wants our selection. */
10242 #ifdef USE_X_TOOLKIT
10243 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
10245 #endif /* USE_X_TOOLKIT */
10246 if (x_queue_selection_requests
)
10247 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
10251 XSelectionRequestEvent
*eventp
10252 = (XSelectionRequestEvent
*) &event
;
10257 bufp
->kind
= selection_request_event
;
10258 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
10259 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
10260 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
10261 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
10262 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
10263 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
10264 bufp
->frame_or_window
= Qnil
;
10273 case PropertyNotify
:
10274 #if 0 /* This is plain wrong. In the case that we are waiting for a
10275 PropertyNotify used as an ACK in incremental selection
10276 transfer, the property will be on the receiver's window. */
10277 #if defined USE_X_TOOLKIT
10278 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
10282 x_handle_property_notify (&event
.xproperty
);
10285 case ReparentNotify
:
10286 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
10290 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
10291 x_real_positions (f
, &x
, &y
);
10292 f
->output_data
.x
->left_pos
= x
;
10293 f
->output_data
.x
->top_pos
= y
;
10298 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
10301 x_check_fullscreen (f
);
10303 if (f
->async_visible
== 0)
10305 f
->async_visible
= 1;
10306 f
->async_iconified
= 0;
10307 f
->output_data
.x
->has_been_visible
= 1;
10308 SET_FRAME_GARBAGED (f
);
10311 expose_frame (x_window_to_frame (dpyinfo
,
10312 event
.xexpose
.window
),
10313 event
.xexpose
.x
, event
.xexpose
.y
,
10314 event
.xexpose
.width
, event
.xexpose
.height
);
10318 #ifndef USE_TOOLKIT_SCROLL_BARS
10319 struct scroll_bar
*bar
;
10321 #if defined USE_LUCID
10322 /* Submenus of the Lucid menu bar aren't widgets
10323 themselves, so there's no way to dispatch events
10324 to them. Recognize this case separately. */
10327 = x_window_to_menu_bar (event
.xexpose
.window
);
10329 xlwmenu_redisplay (widget
);
10331 #endif /* USE_LUCID */
10333 #ifdef USE_TOOLKIT_SCROLL_BARS
10334 /* Dispatch event to the widget. */
10336 #else /* not USE_TOOLKIT_SCROLL_BARS */
10337 bar
= x_window_to_scroll_bar (event
.xexpose
.window
);
10340 x_scroll_bar_expose (bar
, &event
);
10341 #ifdef USE_X_TOOLKIT
10344 #endif /* USE_X_TOOLKIT */
10345 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10349 case GraphicsExpose
: /* This occurs when an XCopyArea's
10350 source area was obscured or not
10352 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
10356 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
10357 event
.xgraphicsexpose
.width
,
10358 event
.xgraphicsexpose
.height
);
10360 #ifdef USE_X_TOOLKIT
10363 #endif /* USE_X_TOOLKIT */
10366 case NoExpose
: /* This occurs when an XCopyArea's
10367 source area was completely
10372 /* Redo the mouse-highlight after the tooltip has gone. */
10373 if (event
.xmap
.window
== tip_window
)
10376 redo_mouse_highlight ();
10379 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
10380 if (f
) /* F may no longer exist if
10381 the frame was deleted. */
10383 /* While a frame is unmapped, display generation is
10384 disabled; you don't want to spend time updating a
10385 display that won't ever be seen. */
10386 f
->async_visible
= 0;
10387 /* We can't distinguish, from the event, whether the window
10388 has become iconified or invisible. So assume, if it
10389 was previously visible, than now it is iconified.
10390 But x_make_frame_invisible clears both
10391 the visible flag and the iconified flag;
10392 and that way, we know the window is not iconified now. */
10393 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
10395 f
->async_iconified
= 1;
10397 bufp
->kind
= iconify_event
;
10398 XSETFRAME (bufp
->frame_or_window
, f
);
10408 if (event
.xmap
.window
== tip_window
)
10409 /* The tooltip has been drawn already. Avoid
10410 the SET_FRAME_GARBAGED below. */
10413 /* We use x_top_window_to_frame because map events can
10414 come for sub-windows and they don't mean that the
10415 frame is visible. */
10416 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
10419 f
->async_visible
= 1;
10420 f
->async_iconified
= 0;
10421 f
->output_data
.x
->has_been_visible
= 1;
10423 /* wait_reading_process_input will notice this and update
10424 the frame's display structures. */
10425 SET_FRAME_GARBAGED (f
);
10429 bufp
->kind
= deiconify_event
;
10430 XSETFRAME (bufp
->frame_or_window
, f
);
10436 else if (! NILP (Vframe_list
)
10437 && ! NILP (XCDR (Vframe_list
)))
10438 /* Force a redisplay sooner or later
10439 to update the frame titles
10440 in case this is the second frame. */
10441 record_asynch_buffer_change ();
10446 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
10448 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10450 dpyinfo
->mouse_face_hidden
= 1;
10451 clear_mouse_face (dpyinfo
);
10454 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10457 /* Scroll bars consume key events, but we want
10458 the keys to go to the scroll bar's frame. */
10459 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
10460 event
.xkey
.window
);
10461 if (widget
&& XmIsScrollBar (widget
))
10463 widget
= XtParent (widget
);
10464 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
10467 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10471 KeySym keysym
, orig_keysym
;
10472 /* al%imercury@uunet.uu.net says that making this 81
10473 instead of 80 fixed a bug whereby meta chars made
10476 It seems that some version of XmbLookupString has
10477 a bug of not returning XBufferOverflow in
10478 status_return even if the input is too long to
10479 fit in 81 bytes. So, we must prepare sufficient
10480 bytes for copy_buffer. 513 bytes (256 chars for
10481 two-byte character set) seems to be a fairly good
10482 approximation. -- 2000.8.10 handa@etl.go.jp */
10483 unsigned char copy_buffer
[513];
10484 unsigned char *copy_bufptr
= copy_buffer
;
10485 int copy_bufsiz
= sizeof (copy_buffer
);
10489 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
10490 extra_keyboard_modifiers
);
10491 modifiers
= event
.xkey
.state
;
10493 /* This will have to go some day... */
10495 /* make_lispy_event turns chars into control chars.
10496 Don't do it here because XLookupString is too eager. */
10497 event
.xkey
.state
&= ~ControlMask
;
10498 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
10499 | dpyinfo
->super_mod_mask
10500 | dpyinfo
->hyper_mod_mask
10501 | dpyinfo
->alt_mod_mask
);
10503 /* In case Meta is ComposeCharacter,
10504 clear its status. According to Markus Ehrnsperger
10505 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10506 this enables ComposeCharacter to work whether or
10507 not it is combined with Meta. */
10508 if (modifiers
& dpyinfo
->meta_mod_mask
)
10509 bzero (&compose_status
, sizeof (compose_status
));
10514 Status status_return
;
10516 nbytes
= XmbLookupString (FRAME_XIC (f
),
10517 &event
.xkey
, copy_bufptr
,
10518 copy_bufsiz
, &keysym
,
10520 if (status_return
== XBufferOverflow
)
10522 copy_bufsiz
= nbytes
+ 1;
10523 copy_bufptr
= (char *) alloca (copy_bufsiz
);
10524 nbytes
= XmbLookupString (FRAME_XIC (f
),
10525 &event
.xkey
, copy_bufptr
,
10526 copy_bufsiz
, &keysym
,
10530 if (status_return
== XLookupNone
)
10532 else if (status_return
== XLookupChars
)
10537 else if (status_return
!= XLookupKeySym
10538 && status_return
!= XLookupBoth
)
10542 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
10543 copy_bufsiz
, &keysym
,
10546 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
10547 copy_bufsiz
, &keysym
,
10551 orig_keysym
= keysym
;
10555 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
10556 || keysym
== XK_Delete
10557 #ifdef XK_ISO_Left_Tab
10558 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
10560 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
10561 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
10562 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
10564 /* This recognizes the "extended function keys".
10565 It seems there's no cleaner way.
10566 Test IsModifierKey to avoid handling mode_switch
10568 || ((unsigned) (keysym
) >= XK_Select
10569 && (unsigned)(keysym
) < XK_KP_Space
)
10571 #ifdef XK_dead_circumflex
10572 || orig_keysym
== XK_dead_circumflex
10574 #ifdef XK_dead_grave
10575 || orig_keysym
== XK_dead_grave
10577 #ifdef XK_dead_tilde
10578 || orig_keysym
== XK_dead_tilde
10580 #ifdef XK_dead_diaeresis
10581 || orig_keysym
== XK_dead_diaeresis
10583 #ifdef XK_dead_macron
10584 || orig_keysym
== XK_dead_macron
10586 #ifdef XK_dead_degree
10587 || orig_keysym
== XK_dead_degree
10589 #ifdef XK_dead_acute
10590 || orig_keysym
== XK_dead_acute
10592 #ifdef XK_dead_cedilla
10593 || orig_keysym
== XK_dead_cedilla
10595 #ifdef XK_dead_breve
10596 || orig_keysym
== XK_dead_breve
10598 #ifdef XK_dead_ogonek
10599 || orig_keysym
== XK_dead_ogonek
10601 #ifdef XK_dead_caron
10602 || orig_keysym
== XK_dead_caron
10604 #ifdef XK_dead_doubleacute
10605 || orig_keysym
== XK_dead_doubleacute
10607 #ifdef XK_dead_abovedot
10608 || orig_keysym
== XK_dead_abovedot
10610 #ifdef XK_dead_abovering
10611 || orig_keysym
== XK_dead_abovering
10613 #ifdef XK_dead_iota
10614 || orig_keysym
== XK_dead_iota
10616 #ifdef XK_dead_belowdot
10617 || orig_keysym
== XK_dead_belowdot
10619 #ifdef XK_dead_voiced_sound
10620 || orig_keysym
== XK_dead_voiced_sound
10622 #ifdef XK_dead_semivoiced_sound
10623 || orig_keysym
== XK_dead_semivoiced_sound
10625 #ifdef XK_dead_hook
10626 || orig_keysym
== XK_dead_hook
10628 #ifdef XK_dead_horn
10629 || orig_keysym
== XK_dead_horn
10631 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
10632 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
10633 /* Any "vendor-specific" key is ok. */
10634 || (orig_keysym
& (1 << 28))
10635 || (keysym
!= NoSymbol
&& nbytes
== 0))
10636 && ! (IsModifierKey (orig_keysym
)
10638 #ifdef XK_Mode_switch
10639 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
10642 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
10644 #endif /* not HAVE_X11R5 */
10647 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
10649 temp_buffer
[temp_index
++] = keysym
;
10650 bufp
->kind
= non_ascii_keystroke
;
10651 bufp
->code
= keysym
;
10652 XSETFRAME (bufp
->frame_or_window
, f
);
10655 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
10657 bufp
->timestamp
= event
.xkey
.time
;
10662 else if (numchars
> nbytes
)
10668 for (i
= 0; i
< nbytes
; i
++)
10670 if (temp_index
== (sizeof temp_buffer
10673 temp_buffer
[temp_index
++] = copy_bufptr
[i
];
10676 if (/* If the event is not from XIM, */
10677 event
.xkey
.keycode
!= 0
10678 /* or the current locale doesn't request
10679 decoding of the input data, ... */
10680 || ! CODING_REQUIRE_DECODING (&coding
))
10682 /* ... we can use the input data as is. */
10687 /* We have to decode the input data. */
10689 = (unsigned char *) malloc (nbytes
);
10690 if (! coding
.destination
)
10692 coding
.dst_bytes
= nbytes
;
10693 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
10694 decode_coding_c_string (&coding
, copy_bufptr
,
10696 nbytes
= coding
.produced
;
10697 nchars
= coding
.produced_char
;
10698 if (copy_bufsiz
< nbytes
)
10700 copy_bufsiz
= nbytes
;
10701 copy_bufptr
= (char *) alloca (nbytes
);
10703 bcopy (coding
.destination
, copy_bufptr
, nbytes
);
10704 free (coding
.destination
);
10707 /* Convert the input data to a sequence of
10708 character events. */
10709 for (i
= 0; i
< nbytes
; i
+= len
)
10711 if (nchars
== nbytes
)
10712 c
= copy_bufptr
[i
], len
= 1;
10714 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
10717 bufp
->kind
= (SINGLE_BYTE_CHAR_P (c
)
10719 : multibyte_char_keystroke
);
10721 XSETFRAME (bufp
->frame_or_window
, f
);
10724 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
10726 bufp
->timestamp
= event
.xkey
.time
;
10731 numchars
-= nchars
;
10733 if (keysym
== NoSymbol
)
10743 /* Don't dispatch this event since XtDispatchEvent calls
10744 XFilterEvent, and two calls in a row may freeze the
10753 /* Don't dispatch this event since XtDispatchEvent calls
10754 XFilterEvent, and two calls in a row may freeze the
10761 /* Here's a possible interpretation of the whole
10762 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10763 you get a FocusIn event, you have to get a FocusOut
10764 event before you relinquish the focus. If you
10765 haven't received a FocusIn event, then a mere
10766 LeaveNotify is enough to free you. */
10770 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10773 if (event
.xcrossing
.focus
)
10775 /* Avoid nasty pop/raise loops. */
10776 if (f
&& (!(f
->auto_raise
)
10777 || !(f
->auto_lower
)
10778 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
10780 x_new_focus_frame (dpyinfo
, f
);
10781 enter_timestamp
= event
.xcrossing
.time
;
10784 else if (f
== dpyinfo
->x_focus_frame
)
10785 x_new_focus_frame (dpyinfo
, 0);
10788 /* EnterNotify counts as mouse movement,
10789 so update things that depend on mouse position. */
10790 if (f
&& !f
->output_data
.x
->hourglass_p
)
10791 note_mouse_movement (f
, &event
.xmotion
);
10796 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
10797 if (event
.xfocus
.detail
!= NotifyPointer
)
10798 dpyinfo
->x_focus_event_frame
= f
;
10801 x_new_focus_frame (dpyinfo
, f
);
10803 /* Don't stop displaying the initial startup message
10804 for a switch-frame event we don't need. */
10805 if (GC_NILP (Vterminal_frame
)
10806 && GC_CONSP (Vframe_list
)
10807 && !GC_NILP (XCDR (Vframe_list
)))
10809 bufp
->kind
= FOCUS_IN_EVENT
;
10810 XSETFRAME (bufp
->frame_or_window
, f
);
10812 ++bufp
, ++count
, --numchars
;
10817 if (f
&& FRAME_XIC (f
))
10818 XSetICFocus (FRAME_XIC (f
));
10824 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10827 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10829 /* If we move outside the frame, then we're
10830 certainly no longer on any text in the frame. */
10831 clear_mouse_face (dpyinfo
);
10832 dpyinfo
->mouse_face_mouse_frame
= 0;
10835 /* Generate a nil HELP_EVENT to cancel a help-echo.
10836 Do it only if there's something to cancel.
10837 Otherwise, the startup message is cleared when
10838 the mouse leaves the frame. */
10839 if (any_help_event_p
)
10844 XSETFRAME (frame
, f
);
10846 n
= gen_help_event (bufp
, numchars
,
10847 Qnil
, frame
, Qnil
, Qnil
, 0);
10848 bufp
+= n
, count
+= n
, numchars
-= n
;
10852 if (event
.xcrossing
.focus
)
10853 x_mouse_leave (dpyinfo
);
10856 if (f
== dpyinfo
->x_focus_event_frame
)
10857 dpyinfo
->x_focus_event_frame
= 0;
10858 if (f
== dpyinfo
->x_focus_frame
)
10859 x_new_focus_frame (dpyinfo
, 0);
10866 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
10867 if (event
.xfocus
.detail
!= NotifyPointer
10868 && f
== dpyinfo
->x_focus_event_frame
)
10869 dpyinfo
->x_focus_event_frame
= 0;
10870 if (f
&& f
== dpyinfo
->x_focus_frame
)
10871 x_new_focus_frame (dpyinfo
, 0);
10874 if (f
&& FRAME_XIC (f
))
10875 XUnsetICFocus (FRAME_XIC (f
));
10882 previous_help_echo
= help_echo
;
10883 help_echo
= help_echo_object
= help_echo_window
= Qnil
;
10884 help_echo_pos
= -1;
10886 if (dpyinfo
->grabbed
&& last_mouse_frame
10887 && FRAME_LIVE_P (last_mouse_frame
))
10888 f
= last_mouse_frame
;
10890 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
10892 if (dpyinfo
->mouse_face_hidden
)
10894 dpyinfo
->mouse_face_hidden
= 0;
10895 clear_mouse_face (dpyinfo
);
10899 note_mouse_movement (f
, &event
.xmotion
);
10902 #ifndef USE_TOOLKIT_SCROLL_BARS
10903 struct scroll_bar
*bar
10904 = x_window_to_scroll_bar (event
.xmotion
.window
);
10907 x_scroll_bar_note_movement (bar
, &event
);
10908 #endif /* USE_TOOLKIT_SCROLL_BARS */
10910 /* If we move outside the frame, then we're
10911 certainly no longer on any text in the frame. */
10912 clear_mouse_face (dpyinfo
);
10915 /* If the contents of the global variable help_echo
10916 has changed, generate a HELP_EVENT. */
10917 if (!NILP (help_echo
)
10918 || !NILP (previous_help_echo
))
10924 XSETFRAME (frame
, f
);
10928 any_help_event_p
= 1;
10929 n
= gen_help_event (bufp
, numchars
, help_echo
, frame
,
10930 help_echo_window
, help_echo_object
,
10932 bufp
+= n
, count
+= n
, numchars
-= n
;
10938 case ConfigureNotify
:
10939 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
10942 #ifndef USE_X_TOOLKIT
10943 /* If there is a pending resize for fullscreen, don't
10944 do this one, the right one will come later.
10945 The toolkit version doesn't seem to need this, but we
10946 need to reset it below. */
10948 ((f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WAIT
)
10949 && FRAME_NEW_WIDTH (f
) != 0);
10950 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
10951 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
10955 /* In the toolkit version, change_frame_size
10956 is called by the code that handles resizing
10957 of the EmacsFrame widget. */
10959 /* Even if the number of character rows and columns has
10960 not changed, the font size may have changed, so we need
10961 to check the pixel dimensions as well. */
10962 if (columns
!= f
->width
10963 || rows
!= f
->height
10964 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
10965 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
10967 change_frame_size (f
, rows
, columns
, 0, 1, 0);
10968 SET_FRAME_GARBAGED (f
);
10969 cancel_mouse_face (f
);
10973 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
10974 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
10976 /* What we have now is the position of Emacs's own window.
10977 Convert that to the position of the window manager window. */
10978 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
10979 &f
->output_data
.x
->top_pos
);
10981 x_check_fullscreen_move(f
);
10982 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WAIT
)
10983 f
->output_data
.x
->want_fullscreen
&=
10984 ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
10986 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
10987 xic_set_statusarea (f
);
10990 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10992 /* Since the WM decorations come below top_pos now,
10993 we must put them below top_pos in the future. */
10994 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10995 x_wm_set_size_hint (f
, (long) 0, 0);
10998 /* Some window managers pass (0,0) as the location of
10999 the window, and the Motif event handler stores it
11000 in the emacs widget, which messes up Motif menus. */
11001 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
11003 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
11004 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
11006 #endif /* USE_MOTIF */
11011 case ButtonRelease
:
11013 /* If we decide we want to generate an event to be seen
11014 by the rest of Emacs, we put it here. */
11015 struct input_event emacs_event
;
11016 int tool_bar_p
= 0;
11018 emacs_event
.kind
= no_event
;
11019 bzero (&compose_status
, sizeof (compose_status
));
11021 if (dpyinfo
->grabbed
11022 && last_mouse_frame
11023 && FRAME_LIVE_P (last_mouse_frame
))
11024 f
= last_mouse_frame
;
11026 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
11030 /* Is this in the tool-bar? */
11031 if (WINDOWP (f
->tool_bar_window
)
11032 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
11034 Lisp_Object window
;
11037 x
= event
.xbutton
.x
;
11038 y
= event
.xbutton
.y
;
11041 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
11042 if (EQ (window
, f
->tool_bar_window
))
11044 x_handle_tool_bar_click (f
, &event
.xbutton
);
11050 if (!dpyinfo
->x_focus_frame
11051 || f
== dpyinfo
->x_focus_frame
)
11052 construct_mouse_click (&emacs_event
, &event
, f
);
11056 #ifndef USE_TOOLKIT_SCROLL_BARS
11057 struct scroll_bar
*bar
11058 = x_window_to_scroll_bar (event
.xbutton
.window
);
11061 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
11062 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11065 if (event
.type
== ButtonPress
)
11067 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
11068 last_mouse_frame
= f
;
11069 /* Ignore any mouse motion that happened
11070 before this event; any subsequent mouse-movement
11071 Emacs events should reflect only motion after
11072 the ButtonPress. */
11074 f
->mouse_moved
= 0;
11077 last_tool_bar_item
= -1;
11081 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
11084 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
11086 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
11092 #ifdef USE_X_TOOLKIT
11093 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
11094 /* For a down-event in the menu bar,
11095 don't pass it to Xt right now.
11096 Instead, save it away
11097 and we will pass it to Xt from kbd_buffer_get_event.
11098 That way, we can run some Lisp code first. */
11099 if (f
&& event
.type
== ButtonPress
11100 /* Verify the event is really within the menu bar
11101 and not just sent to it due to grabbing. */
11102 && event
.xbutton
.x
>= 0
11103 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
11104 && event
.xbutton
.y
>= 0
11105 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
11106 && event
.xbutton
.same_screen
)
11108 SET_SAVED_BUTTON_EVENT
;
11109 XSETFRAME (last_mouse_press_frame
, f
);
11111 else if (event
.type
== ButtonPress
)
11113 last_mouse_press_frame
= Qnil
;
11117 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11118 but I am trying to be cautious. */
11119 else if (event
.type
== ButtonRelease
)
11121 if (!NILP (last_mouse_press_frame
))
11123 f
= XFRAME (last_mouse_press_frame
);
11124 if (f
->output_data
.x
)
11125 SET_SAVED_BUTTON_EVENT
;
11130 #endif /* USE_MOTIF */
11133 #endif /* USE_X_TOOLKIT */
11137 case CirculateNotify
:
11140 case CirculateRequest
:
11143 case VisibilityNotify
:
11146 case MappingNotify
:
11147 /* Someone has changed the keyboard mapping - update the
11149 switch (event
.xmapping
.request
)
11151 case MappingModifier
:
11152 x_find_modifier_meanings (dpyinfo
);
11153 /* This is meant to fall through. */
11154 case MappingKeyboard
:
11155 XRefreshKeyboardMapping (&event
.xmapping
);
11161 #ifdef USE_X_TOOLKIT
11163 XtDispatchEvent (&event
);
11165 #endif /* USE_X_TOOLKIT */
11173 /* On some systems, an X bug causes Emacs to get no more events
11174 when the window is destroyed. Detect that. (1994.) */
11177 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11178 One XNOOP in 100 loops will make Emacs terminate.
11179 B. Bretthauer, 1994 */
11181 if (x_noop_count
>= 100)
11185 if (next_noop_dpyinfo
== 0)
11186 next_noop_dpyinfo
= x_display_list
;
11188 XNoOp (next_noop_dpyinfo
->display
);
11190 /* Each time we get here, cycle through the displays now open. */
11191 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
11195 /* If the focus was just given to an auto-raising frame,
11197 /* ??? This ought to be able to handle more than one such frame. */
11198 if (pending_autoraise_frame
)
11200 x_raise_frame (pending_autoraise_frame
);
11201 pending_autoraise_frame
= 0;
11212 /***********************************************************************
11214 ***********************************************************************/
11216 /* Notice when the text cursor of window W has been completely
11217 overwritten by a drawing operation that outputs glyphs in AREA
11218 starting at X0 and ending at X1 in the line starting at Y0 and
11219 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11220 the rest of the line after X0 has been written. Y coordinates
11221 are window-relative. */
11224 notice_overwritten_cursor (w
, area
, x0
, x1
, y0
, y1
)
11226 enum glyph_row_area area
;
11227 int x0
, y0
, x1
, y1
;
11229 if (area
== TEXT_AREA
11230 && w
->phys_cursor_on_p
11231 && y0
<= w
->phys_cursor
.y
11232 && y1
>= w
->phys_cursor
.y
+ w
->phys_cursor_height
11233 && x0
<= w
->phys_cursor
.x
11234 && (x1
< 0 || x1
> w
->phys_cursor
.x
))
11235 w
->phys_cursor_on_p
= 0;
11239 /* Set clipping for output in glyph row ROW. W is the window in which
11240 we operate. GC is the graphics context to set clipping in.
11241 WHOLE_LINE_P non-zero means include the areas used for truncation
11242 mark display and alike in the clipping rectangle.
11244 ROW may be a text row or, e.g., a mode line. Text rows must be
11245 clipped to the interior of the window dedicated to text display,
11246 mode lines must be clipped to the whole window. */
11249 x_clip_to_row (w
, row
, gc
, whole_line_p
)
11251 struct glyph_row
*row
;
11255 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
11256 XRectangle clip_rect
;
11257 int window_x
, window_y
, window_width
, window_height
;
11259 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
11261 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
11262 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
11263 clip_rect
.y
= max (clip_rect
.y
, window_y
);
11264 clip_rect
.width
= window_width
;
11265 clip_rect
.height
= row
->visible_height
;
11267 /* If clipping to the whole line, including trunc marks, extend
11268 the rectangle to the left and increase its width. */
11271 clip_rect
.x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
11272 clip_rect
.width
+= FRAME_X_FRINGE_WIDTH (f
);
11275 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
11279 /* Draw a hollow box cursor on window W in glyph row ROW. */
11282 x_draw_hollow_cursor (w
, row
)
11284 struct glyph_row
*row
;
11286 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
11287 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11288 Display
*dpy
= FRAME_X_DISPLAY (f
);
11291 struct glyph
*cursor_glyph
;
11294 /* Compute frame-relative coordinates from window-relative
11296 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
11297 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
11298 + row
->ascent
- w
->phys_cursor_ascent
);
11299 h
= row
->height
- 1;
11301 /* Get the glyph the cursor is on. If we can't tell because
11302 the current matrix is invalid or such, give up. */
11303 cursor_glyph
= get_phys_cursor_glyph (w
);
11304 if (cursor_glyph
== NULL
)
11307 /* Compute the width of the rectangle to draw. If on a stretch
11308 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11309 rectangle as wide as the glyph, but use a canonical character
11311 wd
= cursor_glyph
->pixel_width
- 1;
11312 if (cursor_glyph
->type
== STRETCH_GLYPH
11313 && !x_stretch_cursor_p
)
11314 wd
= min (CANON_X_UNIT (f
), wd
);
11316 /* The foreground of cursor_gc is typically the same as the normal
11317 background color, which can cause the cursor box to be invisible. */
11318 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
11319 if (dpyinfo
->scratch_cursor_gc
)
11320 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
11322 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
11323 GCForeground
, &xgcv
);
11324 gc
= dpyinfo
->scratch_cursor_gc
;
11326 /* Set clipping, draw the rectangle, and reset clipping again. */
11327 x_clip_to_row (w
, row
, gc
, 0);
11328 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
11329 XSetClipMask (dpy
, gc
, None
);
11333 /* Draw a bar cursor on window W in glyph row ROW.
11335 Implementation note: One would like to draw a bar cursor with an
11336 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11337 Unfortunately, I didn't find a font yet that has this property set.
11341 x_draw_bar_cursor (w
, row
, width
)
11343 struct glyph_row
*row
;
11346 struct frame
*f
= XFRAME (w
->frame
);
11347 struct glyph
*cursor_glyph
;
11349 /* If cursor is out of bounds, don't draw garbage. This can happen
11350 in mini-buffer windows when switching between echo area glyphs
11351 and mini-buffer. */
11352 cursor_glyph
= get_phys_cursor_glyph (w
);
11353 if (cursor_glyph
== NULL
)
11356 /* If on an image, draw like a normal cursor. That's usually better
11357 visible than drawing a bar, esp. if the image is large so that
11358 the bar might not be in the window. */
11359 if (cursor_glyph
->type
== IMAGE_GLYPH
)
11361 struct glyph_row
*row
;
11362 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
11363 x_draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
11367 Display
*dpy
= FRAME_X_DISPLAY (f
);
11368 Window window
= FRAME_X_WINDOW (f
);
11369 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
11370 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
11371 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
11374 /* If the glyph's background equals the color we normally draw
11375 the bar cursor in, the bar cursor in its normal color is
11376 invisible. Use the glyph's foreground color instead in this
11377 case, on the assumption that the glyph's colors are chosen so
11378 that the glyph is legible. */
11379 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
11380 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
11382 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
11383 xgcv
.graphics_exposures
= 0;
11386 XChangeGC (dpy
, gc
, mask
, &xgcv
);
11389 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
11390 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
11394 width
= f
->output_data
.x
->cursor_width
;
11395 width
= min (cursor_glyph
->pixel_width
, width
);
11397 x_clip_to_row (w
, row
, gc
, 0);
11398 XFillRectangle (dpy
, window
, gc
,
11399 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
11400 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
11401 width
, row
->height
);
11402 XSetClipMask (dpy
, gc
, None
);
11407 /* Clear the cursor of window W to background color, and mark the
11408 cursor as not shown. This is used when the text where the cursor
11409 is is about to be rewritten. */
11415 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
11416 x_update_window_cursor (w
, 0);
11420 /* Draw the cursor glyph of window W in glyph row ROW. See the
11421 comment of x_draw_glyphs for the meaning of HL. */
11424 x_draw_phys_cursor_glyph (w
, row
, hl
)
11426 struct glyph_row
*row
;
11427 enum draw_glyphs_face hl
;
11429 /* If cursor hpos is out of bounds, don't draw garbage. This can
11430 happen in mini-buffer windows when switching between echo area
11431 glyphs and mini-buffer. */
11432 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
11434 int on_p
= w
->phys_cursor_on_p
;
11436 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
11437 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
11439 w
->phys_cursor_on_p
= on_p
;
11441 /* When we erase the cursor, and ROW is overlapped by other
11442 rows, make sure that these overlapping parts of other rows
11444 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
11446 if (row
> w
->current_matrix
->rows
11447 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
11448 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
11450 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
11451 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
11452 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
11458 /* Erase the image of a cursor of window W from the screen. */
11461 x_erase_phys_cursor (w
)
11464 struct frame
*f
= XFRAME (w
->frame
);
11465 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11466 int hpos
= w
->phys_cursor
.hpos
;
11467 int vpos
= w
->phys_cursor
.vpos
;
11468 int mouse_face_here_p
= 0;
11469 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
11470 struct glyph_row
*cursor_row
;
11471 struct glyph
*cursor_glyph
;
11472 enum draw_glyphs_face hl
;
11474 /* No cursor displayed or row invalidated => nothing to do on the
11476 if (w
->phys_cursor_type
== NO_CURSOR
)
11477 goto mark_cursor_off
;
11479 /* VPOS >= active_glyphs->nrows means that window has been resized.
11480 Don't bother to erase the cursor. */
11481 if (vpos
>= active_glyphs
->nrows
)
11482 goto mark_cursor_off
;
11484 /* If row containing cursor is marked invalid, there is nothing we
11486 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
11487 if (!cursor_row
->enabled_p
)
11488 goto mark_cursor_off
;
11490 /* If row is completely invisible, don't attempt to delete a cursor which
11491 isn't there. This can happen if cursor is at top of a window, and
11492 we switch to a buffer with a header line in that window. */
11493 if (cursor_row
->visible_height
<= 0)
11494 goto mark_cursor_off
;
11496 /* This can happen when the new row is shorter than the old one.
11497 In this case, either x_draw_glyphs or clear_end_of_line
11498 should have cleared the cursor. Note that we wouldn't be
11499 able to erase the cursor in this case because we don't have a
11500 cursor glyph at hand. */
11501 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
11502 goto mark_cursor_off
;
11504 /* If the cursor is in the mouse face area, redisplay that when
11505 we clear the cursor. */
11506 if (! NILP (dpyinfo
->mouse_face_window
)
11507 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
11508 && (vpos
> dpyinfo
->mouse_face_beg_row
11509 || (vpos
== dpyinfo
->mouse_face_beg_row
11510 && hpos
>= dpyinfo
->mouse_face_beg_col
))
11511 && (vpos
< dpyinfo
->mouse_face_end_row
11512 || (vpos
== dpyinfo
->mouse_face_end_row
11513 && hpos
< dpyinfo
->mouse_face_end_col
))
11514 /* Don't redraw the cursor's spot in mouse face if it is at the
11515 end of a line (on a newline). The cursor appears there, but
11516 mouse highlighting does not. */
11517 && cursor_row
->used
[TEXT_AREA
] > hpos
)
11518 mouse_face_here_p
= 1;
11520 /* Maybe clear the display under the cursor. */
11521 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
11524 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
11526 cursor_glyph
= get_phys_cursor_glyph (w
);
11527 if (cursor_glyph
== NULL
)
11528 goto mark_cursor_off
;
11530 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
11532 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11534 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
11536 cursor_glyph
->pixel_width
,
11537 cursor_row
->visible_height
,
11541 /* Erase the cursor by redrawing the character underneath it. */
11542 if (mouse_face_here_p
)
11543 hl
= DRAW_MOUSE_FACE
;
11545 hl
= DRAW_NORMAL_TEXT
;
11546 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
11549 w
->phys_cursor_on_p
= 0;
11550 w
->phys_cursor_type
= NO_CURSOR
;
11554 /* Non-zero if physical cursor of window W is within mouse face. */
11557 cursor_in_mouse_face_p (w
)
11560 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
11561 int in_mouse_face
= 0;
11563 if (WINDOWP (dpyinfo
->mouse_face_window
)
11564 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
11566 int hpos
= w
->phys_cursor
.hpos
;
11567 int vpos
= w
->phys_cursor
.vpos
;
11569 if (vpos
>= dpyinfo
->mouse_face_beg_row
11570 && vpos
<= dpyinfo
->mouse_face_end_row
11571 && (vpos
> dpyinfo
->mouse_face_beg_row
11572 || hpos
>= dpyinfo
->mouse_face_beg_col
)
11573 && (vpos
< dpyinfo
->mouse_face_end_row
11574 || hpos
< dpyinfo
->mouse_face_end_col
11575 || dpyinfo
->mouse_face_past_end
))
11579 return in_mouse_face
;
11583 /* Display or clear cursor of window W. If ON is zero, clear the
11584 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11585 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11588 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
11590 int on
, hpos
, vpos
, x
, y
;
11592 struct frame
*f
= XFRAME (w
->frame
);
11593 int new_cursor_type
;
11594 int new_cursor_width
;
11595 struct glyph_matrix
*current_glyphs
;
11596 struct glyph_row
*glyph_row
;
11597 struct glyph
*glyph
;
11598 int cursor_non_selected
;
11600 /* This is pointless on invisible frames, and dangerous on garbaged
11601 windows and frames; in the latter case, the frame or window may
11602 be in the midst of changing its size, and x and y may be off the
11604 if (! FRAME_VISIBLE_P (f
)
11605 || FRAME_GARBAGED_P (f
)
11606 || vpos
>= w
->current_matrix
->nrows
11607 || hpos
>= w
->current_matrix
->matrix_w
)
11610 /* If cursor is off and we want it off, return quickly. */
11611 if (!on
&& !w
->phys_cursor_on_p
)
11614 current_glyphs
= w
->current_matrix
;
11615 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
11616 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
11618 /* If cursor row is not enabled, we don't really know where to
11619 display the cursor. */
11620 if (!glyph_row
->enabled_p
)
11622 w
->phys_cursor_on_p
= 0;
11626 xassert (interrupt_input_blocked
);
11628 /* Set new_cursor_type to the cursor we want to be displayed. In a
11629 mini-buffer window, we want the cursor only to appear if we are
11630 reading input from this window. For the selected window, we want
11631 the cursor type given by the frame parameter. If explicitly
11632 marked off, draw no cursor. In all other cases, we want a hollow
11634 cursor_non_selected
11635 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows
,
11637 new_cursor_width
= -1;
11638 if (cursor_in_echo_area
11639 && FRAME_HAS_MINIBUF_P (f
)
11640 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
11642 if (w
== XWINDOW (echo_area_window
))
11643 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
11644 else if (cursor_non_selected
)
11645 new_cursor_type
= HOLLOW_BOX_CURSOR
;
11647 new_cursor_type
= NO_CURSOR
;
11651 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
11652 || w
!= XWINDOW (f
->selected_window
))
11654 if ((MINI_WINDOW_P (w
) && minibuf_level
== 0)
11655 || !cursor_non_selected
11656 || NILP (XBUFFER (w
->buffer
)->cursor_type
))
11657 new_cursor_type
= NO_CURSOR
;
11659 new_cursor_type
= HOLLOW_BOX_CURSOR
;
11661 else if (w
->cursor_off_p
)
11662 new_cursor_type
= NO_CURSOR
;
11665 struct buffer
*b
= XBUFFER (w
->buffer
);
11667 if (EQ (b
->cursor_type
, Qt
))
11668 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
11670 new_cursor_type
= x_specified_cursor_type (b
->cursor_type
,
11671 &new_cursor_width
);
11675 /* If cursor is currently being shown and we don't want it to be or
11676 it is in the wrong place, or the cursor type is not what we want,
11678 if (w
->phys_cursor_on_p
11680 || w
->phys_cursor
.x
!= x
11681 || w
->phys_cursor
.y
!= y
11682 || new_cursor_type
!= w
->phys_cursor_type
))
11683 x_erase_phys_cursor (w
);
11685 /* If the cursor is now invisible and we want it to be visible,
11687 if (on
&& !w
->phys_cursor_on_p
)
11689 w
->phys_cursor_ascent
= glyph_row
->ascent
;
11690 w
->phys_cursor_height
= glyph_row
->height
;
11692 /* Set phys_cursor_.* before x_draw_.* is called because some
11693 of them may need the information. */
11694 w
->phys_cursor
.x
= x
;
11695 w
->phys_cursor
.y
= glyph_row
->y
;
11696 w
->phys_cursor
.hpos
= hpos
;
11697 w
->phys_cursor
.vpos
= vpos
;
11698 w
->phys_cursor_type
= new_cursor_type
;
11699 w
->phys_cursor_on_p
= 1;
11701 switch (new_cursor_type
)
11703 case HOLLOW_BOX_CURSOR
:
11704 x_draw_hollow_cursor (w
, glyph_row
);
11707 case FILLED_BOX_CURSOR
:
11708 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
11712 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
);
11723 if (w
== XWINDOW (f
->selected_window
))
11724 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
11725 xic_set_preeditarea (w
, x
, y
);
11730 if (updating_frame
!= f
)
11731 XFlush (FRAME_X_DISPLAY (f
));
11736 /* Display the cursor on window W, or clear it. X and Y are window
11737 relative pixel coordinates. HPOS and VPOS are glyph matrix
11738 positions. If W is not the selected window, display a hollow
11739 cursor. ON non-zero means display the cursor at X, Y which
11740 correspond to HPOS, VPOS, otherwise it is cleared. */
11743 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
11745 int on
, hpos
, vpos
, x
, y
;
11748 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
11753 /* Display the cursor on window W, or clear it, according to ON_P.
11754 Don't change the cursor's position. */
11757 x_update_cursor (f
, on_p
)
11760 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
11764 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11765 in the window tree rooted at W. */
11768 x_update_cursor_in_window_tree (w
, on_p
)
11774 if (!NILP (w
->hchild
))
11775 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
11776 else if (!NILP (w
->vchild
))
11777 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
11779 x_update_window_cursor (w
, on_p
);
11781 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
11786 /* Switch the display of W's cursor on or off, according to the value
11790 x_update_window_cursor (w
, on
)
11794 /* Don't update cursor in windows whose frame is in the process
11795 of being deleted. */
11796 if (w
->current_matrix
)
11799 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
11800 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
11810 /* Make the x-window of frame F use the gnu icon bitmap. */
11813 x_bitmap_icon (f
, file
)
11819 if (FRAME_X_WINDOW (f
) == 0)
11822 /* Free up our existing icon bitmap if any. */
11823 if (f
->output_data
.x
->icon_bitmap
> 0)
11824 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
11825 f
->output_data
.x
->icon_bitmap
= 0;
11827 if (STRINGP (file
))
11828 bitmap_id
= x_create_bitmap_from_file (f
, file
);
11831 /* Create the GNU bitmap if necessary. */
11832 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
11833 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
11834 = x_create_bitmap_from_data (f
, gnu_bits
,
11835 gnu_width
, gnu_height
);
11837 /* The first time we create the GNU bitmap,
11838 this increments the ref-count one extra time.
11839 As a result, the GNU bitmap is never freed.
11840 That way, we don't have to worry about allocating it again. */
11841 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
11843 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
11846 x_wm_set_icon_pixmap (f
, bitmap_id
);
11847 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
11853 /* Make the x-window of frame F use a rectangle with text.
11854 Use ICON_NAME as the text. */
11857 x_text_icon (f
, icon_name
)
11861 if (FRAME_X_WINDOW (f
) == 0)
11866 XTextProperty text
;
11867 text
.value
= (unsigned char *) icon_name
;
11868 text
.encoding
= XA_STRING
;
11870 text
.nitems
= strlen (icon_name
);
11871 #ifdef USE_X_TOOLKIT
11872 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11874 #else /* not USE_X_TOOLKIT */
11875 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
11876 #endif /* not USE_X_TOOLKIT */
11878 #else /* not HAVE_X11R4 */
11879 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
11880 #endif /* not HAVE_X11R4 */
11882 if (f
->output_data
.x
->icon_bitmap
> 0)
11883 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
11884 f
->output_data
.x
->icon_bitmap
= 0;
11885 x_wm_set_icon_pixmap (f
, 0);
11890 #define X_ERROR_MESSAGE_SIZE 200
11892 /* If non-nil, this should be a string.
11893 It means catch X errors and store the error message in this string. */
11895 static Lisp_Object x_error_message_string
;
11897 /* An X error handler which stores the error message in
11898 x_error_message_string. This is called from x_error_handler if
11899 x_catch_errors is in effect. */
11902 x_error_catcher (display
, error
)
11904 XErrorEvent
*error
;
11906 XGetErrorText (display
, error
->error_code
,
11907 XSTRING (x_error_message_string
)->data
,
11908 X_ERROR_MESSAGE_SIZE
);
11911 /* Begin trapping X errors for display DPY. Actually we trap X errors
11912 for all displays, but DPY should be the display you are actually
11915 After calling this function, X protocol errors no longer cause
11916 Emacs to exit; instead, they are recorded in the string
11917 stored in x_error_message_string.
11919 Calling x_check_errors signals an Emacs error if an X error has
11920 occurred since the last call to x_catch_errors or x_check_errors.
11922 Calling x_uncatch_errors resumes the normal error handling. */
11924 void x_check_errors ();
11925 static Lisp_Object
x_catch_errors_unwind ();
11928 x_catch_errors (dpy
)
11931 int count
= specpdl_ptr
- specpdl
;
11933 /* Make sure any errors from previous requests have been dealt with. */
11934 XSync (dpy
, False
);
11936 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
11938 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
11939 XSTRING (x_error_message_string
)->data
[0] = 0;
11944 /* Unbind the binding that we made to check for X errors. */
11947 x_catch_errors_unwind (old_val
)
11948 Lisp_Object old_val
;
11950 x_error_message_string
= old_val
;
11954 /* If any X protocol errors have arrived since the last call to
11955 x_catch_errors or x_check_errors, signal an Emacs error using
11956 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11959 x_check_errors (dpy
, format
)
11963 /* Make sure to catch any errors incurred so far. */
11964 XSync (dpy
, False
);
11966 if (XSTRING (x_error_message_string
)->data
[0])
11967 error (format
, XSTRING (x_error_message_string
)->data
);
11970 /* Nonzero if we had any X protocol errors
11971 since we did x_catch_errors on DPY. */
11974 x_had_errors_p (dpy
)
11977 /* Make sure to catch any errors incurred so far. */
11978 XSync (dpy
, False
);
11980 return XSTRING (x_error_message_string
)->data
[0] != 0;
11983 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11986 x_clear_errors (dpy
)
11989 XSTRING (x_error_message_string
)->data
[0] = 0;
11992 /* Stop catching X protocol errors and let them make Emacs die.
11993 DPY should be the display that was passed to x_catch_errors.
11994 COUNT should be the value that was returned by
11995 the corresponding call to x_catch_errors. */
11998 x_uncatch_errors (dpy
, count
)
12002 unbind_to (count
, Qnil
);
12006 static unsigned int x_wire_count
;
12009 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
12014 /* Handle SIGPIPE, which can happen when the connection to a server
12015 simply goes away. SIGPIPE is handled by x_connection_signal.
12016 Don't need to do anything, because the write which caused the
12017 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12018 which will do the appropriate cleanup for us. */
12021 x_connection_signal (signalnum
) /* If we don't have an argument, */
12022 int signalnum
; /* some compilers complain in signal calls. */
12025 /* USG systems forget handlers when they are used;
12026 must reestablish each time */
12027 signal (signalnum
, x_connection_signal
);
12032 /************************************************************************
12034 ************************************************************************/
12036 /* Error message passed to x_connection_closed. */
12038 static char *error_msg
;
12040 /* Function installed as fatal_error_signal_hook in
12041 x_connection_closed. Print the X error message, and exit normally,
12042 instead of dumping core when XtCloseDisplay fails. */
12045 x_fatal_error_signal ()
12047 fprintf (stderr
, "%s\n", error_msg
);
12051 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12052 the text of an error message that lead to the connection loss. */
12055 x_connection_closed (dpy
, error_message
)
12057 char *error_message
;
12059 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
12060 Lisp_Object frame
, tail
;
12063 error_msg
= (char *) alloca (strlen (error_message
) + 1);
12064 strcpy (error_msg
, error_message
);
12065 handling_signal
= 0;
12067 /* Prevent being called recursively because of an error condition
12068 below. Otherwise, we might end up with printing ``can't find per
12069 display information'' in the recursive call instead of printing
12070 the original message here. */
12071 count
= x_catch_errors (dpy
);
12073 /* We have to close the display to inform Xt that it doesn't
12074 exist anymore. If we don't, Xt will continue to wait for
12075 events from the display. As a consequence, a sequence of
12077 M-x make-frame-on-display RET :1 RET
12078 ...kill the new frame, so that we get an IO error...
12079 M-x make-frame-on-display RET :1 RET
12081 will indefinitely wait in Xt for events for display `:1', opened
12082 in the first class to make-frame-on-display.
12084 Closing the display is reported to lead to a bus error on
12085 OpenWindows in certain situations. I suspect that is a bug
12086 in OpenWindows. I don't know how to cicumvent it here. */
12088 #ifdef USE_X_TOOLKIT
12089 /* If DPYINFO is null, this means we didn't open the display
12090 in the first place, so don't try to close it. */
12093 extern void (*fatal_error_signal_hook
) P_ ((void));
12094 fatal_error_signal_hook
= x_fatal_error_signal
;
12095 XtCloseDisplay (dpy
);
12096 fatal_error_signal_hook
= NULL
;
12100 /* Indicate that this display is dead. */
12102 dpyinfo
->display
= 0;
12104 /* First delete frames whose mini-buffers are on frames
12105 that are on the dead display. */
12106 FOR_EACH_FRAME (tail
, frame
)
12108 Lisp_Object minibuf_frame
;
12110 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
12111 if (FRAME_X_P (XFRAME (frame
))
12112 && FRAME_X_P (XFRAME (minibuf_frame
))
12113 && ! EQ (frame
, minibuf_frame
)
12114 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
12115 Fdelete_frame (frame
, Qt
);
12118 /* Now delete all remaining frames on the dead display.
12119 We are now sure none of these is used as the mini-buffer
12120 for another frame that we need to delete. */
12121 FOR_EACH_FRAME (tail
, frame
)
12122 if (FRAME_X_P (XFRAME (frame
))
12123 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
12125 /* Set this to t so that Fdelete_frame won't get confused
12126 trying to find a replacement. */
12127 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
12128 Fdelete_frame (frame
, Qt
);
12132 x_delete_display (dpyinfo
);
12134 x_uncatch_errors (dpy
, count
);
12136 if (x_display_list
== 0)
12138 fprintf (stderr
, "%s\n", error_msg
);
12139 shut_down_emacs (0, 0, Qnil
);
12143 /* Ordinary stack unwind doesn't deal with these. */
12145 sigunblock (sigmask (SIGIO
));
12147 sigunblock (sigmask (SIGALRM
));
12148 TOTALLY_UNBLOCK_INPUT
;
12150 clear_waiting_for_input ();
12151 error ("%s", error_msg
);
12155 /* This is the usual handler for X protocol errors.
12156 It kills all frames on the display that we got the error for.
12157 If that was the only one, it prints an error message and kills Emacs. */
12160 x_error_quitter (display
, error
)
12162 XErrorEvent
*error
;
12164 char buf
[256], buf1
[356];
12166 /* Note that there is no real way portable across R3/R4 to get the
12167 original error handler. */
12169 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
12170 sprintf (buf1
, "X protocol error: %s on protocol request %d",
12171 buf
, error
->request_code
);
12172 x_connection_closed (display
, buf1
);
12176 /* This is the first-level handler for X protocol errors.
12177 It calls x_error_quitter or x_error_catcher. */
12180 x_error_handler (display
, error
)
12182 XErrorEvent
*error
;
12184 if (! NILP (x_error_message_string
))
12185 x_error_catcher (display
, error
);
12187 x_error_quitter (display
, error
);
12191 /* This is the handler for X IO errors, always.
12192 It kills all frames on the display that we lost touch with.
12193 If that was the only one, it prints an error message and kills Emacs. */
12196 x_io_error_quitter (display
)
12201 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
12202 x_connection_closed (display
, buf
);
12206 /* Changing the font of the frame. */
12208 /* Give frame F the font named FONTNAME as its default font, and
12209 return the full name of that font. FONTNAME may be a wildcard
12210 pattern; in that case, we choose some font that fits the pattern.
12211 The return value shows which font we chose. */
12214 x_new_font (f
, fontname
)
12216 register char *fontname
;
12218 struct font_info
*fontp
12219 = FS_LOAD_FONT (f
, fontname
);
12224 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
12225 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
12226 f
->output_data
.x
->fontset
= -1;
12228 x_compute_fringe_widths (f
, 1);
12230 /* Compute the scroll bar width in character columns. */
12231 if (f
->scroll_bar_pixel_width
> 0)
12233 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12234 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
12238 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12239 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
12242 /* Now make the frame display the given font. */
12243 if (FRAME_X_WINDOW (f
) != 0)
12245 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
12246 f
->output_data
.x
->font
->fid
);
12247 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
12248 f
->output_data
.x
->font
->fid
);
12249 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
12250 f
->output_data
.x
->font
->fid
);
12252 frame_update_line_height (f
);
12254 /* Don't change the size of a tip frame; there's no point in
12255 doing it because it's done in Fx_show_tip, and it leads to
12256 problems because the tip frame has no widget. */
12257 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
12258 x_set_window_size (f
, 0, f
->width
, f
->height
);
12261 /* If we are setting a new frame's font for the first time,
12262 there are no faces yet, so this font's height is the line height. */
12263 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
12265 return build_string (fontp
->full_name
);
12268 /* Give frame F the fontset named FONTSETNAME as its default font, and
12269 return the full name of that fontset. FONTSETNAME may be a wildcard
12270 pattern; in that case, we choose some fontset that fits the pattern.
12271 The return value shows which fontset we chose. */
12274 x_new_fontset (f
, fontsetname
)
12278 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
12279 Lisp_Object result
;
12284 if (f
->output_data
.x
->fontset
== fontset
)
12285 /* This fontset is already set in frame F. There's nothing more
12287 return fontset_name (fontset
);
12289 result
= x_new_font (f
, (XSTRING (fontset_ascii (fontset
))->data
));
12291 if (!STRINGP (result
))
12292 /* Can't load ASCII font. */
12295 /* Since x_new_font doesn't update any fontset information, do it now. */
12296 f
->output_data
.x
->fontset
= fontset
;
12300 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
12301 xic_set_xfontset (f
, XSTRING (fontset_ascii (fontset
))->data
);
12304 return build_string (fontsetname
);
12307 /* Compute actual fringe widths */
12310 x_compute_fringe_widths (f
, redraw
)
12314 int o_left
= f
->output_data
.x
->left_fringe_width
;
12315 int o_right
= f
->output_data
.x
->right_fringe_width
;
12316 int o_cols
= f
->output_data
.x
->fringe_cols
;
12318 Lisp_Object left_fringe
= Fassq (Qleft_fringe
, f
->param_alist
);
12319 Lisp_Object right_fringe
= Fassq (Qright_fringe
, f
->param_alist
);
12320 int left_fringe_width
, right_fringe_width
;
12322 if (!NILP (left_fringe
))
12323 left_fringe
= Fcdr (left_fringe
);
12324 if (!NILP (right_fringe
))
12325 right_fringe
= Fcdr (right_fringe
);
12327 left_fringe_width
= ((NILP (left_fringe
) || !INTEGERP (left_fringe
)) ? 8 :
12328 XINT (left_fringe
));
12329 right_fringe_width
= ((NILP (right_fringe
) || !INTEGERP (right_fringe
)) ? 8 :
12330 XINT (right_fringe
));
12332 if (left_fringe_width
|| right_fringe_width
)
12334 int left_wid
= left_fringe_width
>= 0 ? left_fringe_width
: -left_fringe_width
;
12335 int right_wid
= right_fringe_width
>= 0 ? right_fringe_width
: -right_fringe_width
;
12336 int conf_wid
= left_wid
+ right_wid
;
12337 int font_wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12338 int cols
= (left_wid
+ right_wid
+ font_wid
-1) / font_wid
;
12339 int real_wid
= cols
* font_wid
;
12340 if (left_wid
&& right_wid
)
12342 if (left_fringe_width
< 0)
12344 /* Left fringe width is fixed, adjust right fringe if necessary */
12345 f
->output_data
.x
->left_fringe_width
= left_wid
;
12346 f
->output_data
.x
->right_fringe_width
= real_wid
- left_wid
;
12348 else if (right_fringe_width
< 0)
12350 /* Right fringe width is fixed, adjust left fringe if necessary */
12351 f
->output_data
.x
->left_fringe_width
= real_wid
- right_wid
;
12352 f
->output_data
.x
->right_fringe_width
= right_wid
;
12356 /* Adjust both fringes with an equal amount.
12357 Note that we are doing integer arithmetic here, so don't
12358 lose a pixel if the total width is an odd number. */
12359 int fill
= real_wid
- conf_wid
;
12360 f
->output_data
.x
->left_fringe_width
= left_wid
+ fill
/2;
12361 f
->output_data
.x
->right_fringe_width
= right_wid
+ fill
- fill
/2;
12364 else if (left_fringe_width
)
12366 f
->output_data
.x
->left_fringe_width
= real_wid
;
12367 f
->output_data
.x
->right_fringe_width
= 0;
12371 f
->output_data
.x
->left_fringe_width
= 0;
12372 f
->output_data
.x
->right_fringe_width
= real_wid
;
12374 f
->output_data
.x
->fringe_cols
= cols
;
12375 f
->output_data
.x
->fringes_extra
= real_wid
;
12379 f
->output_data
.x
->left_fringe_width
= 0;
12380 f
->output_data
.x
->right_fringe_width
= 0;
12381 f
->output_data
.x
->fringe_cols
= 0;
12382 f
->output_data
.x
->fringes_extra
= 0;
12385 if (redraw
&& FRAME_VISIBLE_P (f
))
12386 if (o_left
!= f
->output_data
.x
->left_fringe_width
||
12387 o_right
!= f
->output_data
.x
->right_fringe_width
||
12388 o_cols
!= f
->output_data
.x
->fringe_cols
)
12392 /***********************************************************************
12394 ***********************************************************************/
12400 /* XIM destroy callback function, which is called whenever the
12401 connection to input method XIM dies. CLIENT_DATA contains a
12402 pointer to the x_display_info structure corresponding to XIM. */
12405 xim_destroy_callback (xim
, client_data
, call_data
)
12407 XPointer client_data
;
12408 XPointer call_data
;
12410 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
12411 Lisp_Object frame
, tail
;
12415 /* No need to call XDestroyIC.. */
12416 FOR_EACH_FRAME (tail
, frame
)
12418 struct frame
*f
= XFRAME (frame
);
12419 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
12421 FRAME_XIC (f
) = NULL
;
12422 if (FRAME_XIC_FONTSET (f
))
12424 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
12425 FRAME_XIC_FONTSET (f
) = NULL
;
12430 /* No need to call XCloseIM. */
12431 dpyinfo
->xim
= NULL
;
12432 XFree (dpyinfo
->xim_styles
);
12436 #endif /* HAVE_X11R6 */
12438 /* Open the connection to the XIM server on display DPYINFO.
12439 RESOURCE_NAME is the resource name Emacs uses. */
12442 xim_open_dpy (dpyinfo
, resource_name
)
12443 struct x_display_info
*dpyinfo
;
12444 char *resource_name
;
12449 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
, EMACS_CLASS
);
12450 dpyinfo
->xim
= xim
;
12455 XIMCallback destroy
;
12458 /* Get supported styles and XIM values. */
12459 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
12462 destroy
.callback
= xim_destroy_callback
;
12463 destroy
.client_data
= (XPointer
)dpyinfo
;
12464 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
12468 #else /* not USE_XIM */
12469 dpyinfo
->xim
= NULL
;
12470 #endif /* not USE_XIM */
12474 #ifdef HAVE_X11R6_XIM
12478 struct x_display_info
*dpyinfo
;
12479 char *resource_name
;
12482 /* XIM instantiate callback function, which is called whenever an XIM
12483 server is available. DISPLAY is teh display of the XIM.
12484 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12485 when the callback was registered. */
12488 xim_instantiate_callback (display
, client_data
, call_data
)
12490 XPointer client_data
;
12491 XPointer call_data
;
12493 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
12494 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
12496 /* We don't support multiple XIM connections. */
12500 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
12502 /* Create XIC for the existing frames on the same display, as long
12503 as they have no XIC. */
12504 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
12506 Lisp_Object tail
, frame
;
12509 FOR_EACH_FRAME (tail
, frame
)
12511 struct frame
*f
= XFRAME (frame
);
12513 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
12514 if (FRAME_XIC (f
) == NULL
)
12516 create_frame_xic (f
);
12517 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
12518 xic_set_statusarea (f
);
12519 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
12521 struct window
*w
= XWINDOW (f
->selected_window
);
12522 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
12531 #endif /* HAVE_X11R6_XIM */
12534 /* Open a connection to the XIM server on display DPYINFO.
12535 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12536 connection only at the first time. On X11R6, open the connection
12537 in the XIM instantiate callback function. */
12540 xim_initialize (dpyinfo
, resource_name
)
12541 struct x_display_info
*dpyinfo
;
12542 char *resource_name
;
12545 #ifdef HAVE_X11R6_XIM
12546 struct xim_inst_t
*xim_inst
;
12549 dpyinfo
->xim
= NULL
;
12550 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
12551 xim_inst
->dpyinfo
= dpyinfo
;
12552 len
= strlen (resource_name
);
12553 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
12554 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
12555 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
12556 resource_name
, EMACS_CLASS
,
12557 xim_instantiate_callback
,
12558 /* Fixme: This is XPointer in
12559 XFree86 but (XPointer *) on
12560 Tru64, at least. */
12561 (XPointer
) xim_inst
);
12562 #else /* not HAVE_X11R6_XIM */
12563 dpyinfo
->xim
= NULL
;
12564 xim_open_dpy (dpyinfo
, resource_name
);
12565 #endif /* not HAVE_X11R6_XIM */
12567 #else /* not USE_XIM */
12568 dpyinfo
->xim
= NULL
;
12569 #endif /* not USE_XIM */
12573 /* Close the connection to the XIM server on display DPYINFO. */
12576 xim_close_dpy (dpyinfo
)
12577 struct x_display_info
*dpyinfo
;
12580 #ifdef HAVE_X11R6_XIM
12581 if (dpyinfo
->display
)
12582 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
12584 xim_instantiate_callback
, NULL
);
12585 #endif /* not HAVE_X11R6_XIM */
12586 if (dpyinfo
->display
)
12587 XCloseIM (dpyinfo
->xim
);
12588 dpyinfo
->xim
= NULL
;
12589 XFree (dpyinfo
->xim_styles
);
12590 #endif /* USE_XIM */
12593 #endif /* not HAVE_X11R6_XIM */
12597 /* Calculate the absolute position in frame F
12598 from its current recorded position values and gravity. */
12601 x_calc_absolute_position (f
)
12605 int win_x
= 0, win_y
= 0;
12606 int flags
= f
->output_data
.x
->size_hint_flags
;
12609 /* We have nothing to do if the current position
12610 is already for the top-left corner. */
12611 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
12614 #ifdef USE_X_TOOLKIT
12615 this_window
= XtWindow (f
->output_data
.x
->widget
);
12617 this_window
= FRAME_X_WINDOW (f
);
12620 /* Find the position of the outside upper-left corner of
12621 the inner window, with respect to the outer window.
12622 But do this only if we will need the results. */
12623 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
12628 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12631 x_clear_errors (FRAME_X_DISPLAY (f
));
12632 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
12634 /* From-window, to-window. */
12636 f
->output_data
.x
->parent_desc
,
12638 /* From-position, to-position. */
12639 0, 0, &win_x
, &win_y
,
12641 /* Child of win. */
12643 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12645 Window newroot
, newparent
= 0xdeadbeef;
12646 Window
*newchildren
;
12647 unsigned int nchildren
;
12649 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
12650 &newparent
, &newchildren
, &nchildren
))
12653 XFree ((char *) newchildren
);
12655 f
->output_data
.x
->parent_desc
= newparent
;
12661 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12665 /* Treat negative positions as relative to the leftmost bottommost
12666 position that fits on the screen. */
12667 if (flags
& XNegative
)
12668 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
12669 - 2 * f
->output_data
.x
->border_width
- win_x
12671 + f
->output_data
.x
->left_pos
);
12674 int height
= PIXEL_HEIGHT (f
);
12676 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12677 /* Something is fishy here. When using Motif, starting Emacs with
12678 `-g -0-0', the frame appears too low by a few pixels.
12680 This seems to be so because initially, while Emacs is starting,
12681 the column widget's height and the frame's pixel height are
12682 different. The column widget's height is the right one. In
12683 later invocations, when Emacs is up, the frame's pixel height
12686 It's not obvious where the initial small difference comes from.
12687 2000-12-01, gerd. */
12689 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
12692 if (flags
& YNegative
)
12693 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
12694 - 2 * f
->output_data
.x
->border_width
12697 + f
->output_data
.x
->top_pos
);
12700 /* The left_pos and top_pos
12701 are now relative to the top and left screen edges,
12702 so the flags should correspond. */
12703 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
12706 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12707 to really change the position, and 0 when calling from
12708 x_make_frame_visible (in that case, XOFF and YOFF are the current
12709 position values). It is -1 when calling from x_set_frame_parameters,
12710 which means, do adjust for borders but don't change the gravity. */
12713 x_set_offset (f
, xoff
, yoff
, change_gravity
)
12715 register int xoff
, yoff
;
12716 int change_gravity
;
12718 int modified_top
, modified_left
;
12720 if (change_gravity
> 0)
12722 f
->output_data
.x
->top_pos
= yoff
;
12723 f
->output_data
.x
->left_pos
= xoff
;
12724 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
12726 f
->output_data
.x
->size_hint_flags
|= XNegative
;
12728 f
->output_data
.x
->size_hint_flags
|= YNegative
;
12729 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
12731 x_calc_absolute_position (f
);
12734 x_wm_set_size_hint (f
, (long) 0, 0);
12736 modified_left
= f
->output_data
.x
->left_pos
;
12737 modified_top
= f
->output_data
.x
->top_pos
;
12738 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12739 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12740 /* It is a mystery why we need to add the border_width here
12741 when the frame is already visible, but experiment says we do. */
12742 if (change_gravity
!= 0)
12744 modified_left
+= f
->output_data
.x
->border_width
;
12745 modified_top
+= f
->output_data
.x
->border_width
;
12749 #ifdef USE_X_TOOLKIT
12750 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
12751 modified_left
, modified_top
);
12752 #else /* not USE_X_TOOLKIT */
12753 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
12754 modified_left
, modified_top
);
12755 #endif /* not USE_X_TOOLKIT */
12759 /* Check if we need to resize the frame due to a fullscreen request.
12760 If so needed, resize the frame. */
12762 x_check_fullscreen (f
)
12765 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_BOTH
)
12767 int width
, height
, ign
;
12769 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
12770 &f
->output_data
.x
->top_pos
);
12772 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
12774 /* We do not need to move the window, it shall be taken care of
12775 when setting WM manager hints.
12776 If the frame is visible already, the position is checked by
12777 x_check_fullscreen_move. */
12778 if (f
->width
!= width
|| f
->height
!= height
)
12780 change_frame_size (f
, height
, width
, 0, 1, 0);
12781 SET_FRAME_GARBAGED (f
);
12782 cancel_mouse_face (f
);
12784 /* Wait for the change of frame size to occur */
12785 f
->output_data
.x
->want_fullscreen
|= FULLSCREEN_WAIT
;
12791 /* If frame parameters are set after the frame is mapped, we need to move
12792 the window. This is done in xfns.c.
12793 Some window managers moves the window to the right position, some
12794 moves the outer window manager window to the specified position.
12795 Here we check that we are in the right spot. If not, make a second
12796 move, assuming we are dealing with the second kind of window manager. */
12798 x_check_fullscreen_move (f
)
12801 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_MOVE_WAIT
)
12803 int expect_top
= f
->output_data
.x
->top_pos
;
12804 int expect_left
= f
->output_data
.x
->left_pos
;
12806 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_HEIGHT
)
12808 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WIDTH
)
12811 if (expect_top
!= f
->output_data
.x
->top_pos
12812 || expect_left
!= f
->output_data
.x
->left_pos
)
12813 x_set_offset (f
, expect_left
, expect_top
, 1);
12815 /* Just do this once */
12816 f
->output_data
.x
->want_fullscreen
&= ~FULLSCREEN_MOVE_WAIT
;
12821 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
12822 wanted positions of the WM window (not emacs window).
12823 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
12824 window (FRAME_X_WINDOW).
12827 x_fullscreen_adjust (f
, width
, height
, top_pos
, left_pos
)
12834 int newwidth
= f
->width
, newheight
= f
->height
;
12836 *top_pos
= f
->output_data
.x
->top_pos
;
12837 *left_pos
= f
->output_data
.x
->left_pos
;
12839 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_HEIGHT
)
12843 ph
= FRAME_X_DISPLAY_INFO (f
)->height
;
12844 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
12845 ph
= CHAR_TO_PIXEL_HEIGHT (f
, newheight
)
12846 - f
->output_data
.x
->y_pixels_diff
;
12847 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
12851 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WIDTH
)
12855 pw
= FRAME_X_DISPLAY_INFO (f
)->width
;
12856 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
12857 pw
= CHAR_TO_PIXEL_WIDTH (f
, newwidth
)
12858 - f
->output_data
.x
->x_pixels_diff
;
12859 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
12864 *height
= newheight
;
12868 /* Change the size of frame F's X window to COLS/ROWS in the case F
12869 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12870 top-left-corner window gravity for this size change and subsequent
12871 size changes. Otherwise we leave the window gravity unchanged. */
12874 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
12876 int change_gravity
;
12879 int pixelwidth
, pixelheight
;
12881 check_frame_size (f
, &rows
, &cols
);
12882 f
->output_data
.x
->vertical_scroll_bar_extra
12883 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
12885 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
12886 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
12887 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
12889 x_compute_fringe_widths (f
, 0);
12891 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
12892 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
12894 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
12895 x_wm_set_size_hint (f
, (long) 0, 0);
12897 XSync (FRAME_X_DISPLAY (f
), False
);
12898 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
12899 pixelwidth
, pixelheight
);
12901 /* Now, strictly speaking, we can't be sure that this is accurate,
12902 but the window manager will get around to dealing with the size
12903 change request eventually, and we'll hear how it went when the
12904 ConfigureNotify event gets here.
12906 We could just not bother storing any of this information here,
12907 and let the ConfigureNotify event set everything up, but that
12908 might be kind of confusing to the Lisp code, since size changes
12909 wouldn't be reported in the frame parameters until some random
12910 point in the future when the ConfigureNotify event arrives.
12912 We pass 1 for DELAY since we can't run Lisp code inside of
12914 change_frame_size (f
, rows
, cols
, 0, 1, 0);
12915 PIXEL_WIDTH (f
) = pixelwidth
;
12916 PIXEL_HEIGHT (f
) = pixelheight
;
12918 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12919 receive in the ConfigureNotify event; if we get what we asked
12920 for, then the event won't cause the screen to become garbaged, so
12921 we have to make sure to do it here. */
12922 SET_FRAME_GARBAGED (f
);
12924 XFlush (FRAME_X_DISPLAY (f
));
12928 /* Call this to change the size of frame F's x-window.
12929 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12930 for this size change and subsequent size changes.
12931 Otherwise we leave the window gravity unchanged. */
12934 x_set_window_size (f
, change_gravity
, cols
, rows
)
12936 int change_gravity
;
12941 #ifdef USE_X_TOOLKIT
12943 if (f
->output_data
.x
->widget
!= NULL
)
12945 /* The x and y position of the widget is clobbered by the
12946 call to XtSetValues within EmacsFrameSetCharSize.
12947 This is a real kludge, but I don't understand Xt so I can't
12948 figure out a correct fix. Can anyone else tell me? -- rms. */
12949 int xpos
= f
->output_data
.x
->widget
->core
.x
;
12950 int ypos
= f
->output_data
.x
->widget
->core
.y
;
12951 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
12952 f
->output_data
.x
->widget
->core
.x
= xpos
;
12953 f
->output_data
.x
->widget
->core
.y
= ypos
;
12956 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
12958 #else /* not USE_X_TOOLKIT */
12960 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
12962 #endif /* not USE_X_TOOLKIT */
12964 /* If cursor was outside the new size, mark it as off. */
12965 mark_window_cursors_off (XWINDOW (f
->root_window
));
12967 /* Clear out any recollection of where the mouse highlighting was,
12968 since it might be in a place that's outside the new frame size.
12969 Actually checking whether it is outside is a pain in the neck,
12970 so don't try--just let the highlighting be done afresh with new size. */
12971 cancel_mouse_face (f
);
12976 /* Mouse warping. */
12979 x_set_mouse_position (f
, x
, y
)
12985 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
12986 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
12988 if (pix_x
< 0) pix_x
= 0;
12989 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
12991 if (pix_y
< 0) pix_y
= 0;
12992 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
12996 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
12997 0, 0, 0, 0, pix_x
, pix_y
);
13001 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13004 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
13010 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
13011 0, 0, 0, 0, pix_x
, pix_y
);
13015 /* focus shifting, raising and lowering. */
13018 x_focus_on_frame (f
)
13021 #if 0 /* This proves to be unpleasant. */
13025 /* I don't think that the ICCCM allows programs to do things like this
13026 without the interaction of the window manager. Whatever you end up
13027 doing with this code, do it to x_unfocus_frame too. */
13028 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
13029 RevertToPointerRoot
, CurrentTime
);
13034 x_unfocus_frame (f
)
13038 /* Look at the remarks in x_focus_on_frame. */
13039 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
13040 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
13041 RevertToPointerRoot
, CurrentTime
);
13045 /* Raise frame F. */
13051 if (f
->async_visible
)
13054 #ifdef USE_X_TOOLKIT
13055 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
13056 #else /* not USE_X_TOOLKIT */
13057 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13058 #endif /* not USE_X_TOOLKIT */
13059 XFlush (FRAME_X_DISPLAY (f
));
13064 /* Lower frame F. */
13070 if (f
->async_visible
)
13073 #ifdef USE_X_TOOLKIT
13074 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
13075 #else /* not USE_X_TOOLKIT */
13076 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13077 #endif /* not USE_X_TOOLKIT */
13078 XFlush (FRAME_X_DISPLAY (f
));
13084 XTframe_raise_lower (f
, raise_flag
)
13094 /* Change of visibility. */
13096 /* This tries to wait until the frame is really visible.
13097 However, if the window manager asks the user where to position
13098 the frame, this will return before the user finishes doing that.
13099 The frame will not actually be visible at that time,
13100 but it will become visible later when the window manager
13101 finishes with it. */
13104 x_make_frame_visible (f
)
13108 int original_top
, original_left
;
13109 int retry_count
= 2;
13115 type
= x_icon_type (f
);
13117 x_bitmap_icon (f
, type
);
13119 if (! FRAME_VISIBLE_P (f
))
13121 /* We test FRAME_GARBAGED_P here to make sure we don't
13122 call x_set_offset a second time
13123 if we get to x_make_frame_visible a second time
13124 before the window gets really visible. */
13125 if (! FRAME_ICONIFIED_P (f
)
13126 && ! f
->output_data
.x
->asked_for_visible
)
13127 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
13129 f
->output_data
.x
->asked_for_visible
= 1;
13131 if (! EQ (Vx_no_window_manager
, Qt
))
13132 x_wm_set_window_state (f
, NormalState
);
13133 #ifdef USE_X_TOOLKIT
13134 /* This was XtPopup, but that did nothing for an iconified frame. */
13135 XtMapWidget (f
->output_data
.x
->widget
);
13136 #else /* not USE_X_TOOLKIT */
13137 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13138 #endif /* not USE_X_TOOLKIT */
13139 #if 0 /* This seems to bring back scroll bars in the wrong places
13140 if the window configuration has changed. They seem
13141 to come back ok without this. */
13142 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
13143 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13147 XFlush (FRAME_X_DISPLAY (f
));
13149 /* Synchronize to ensure Emacs knows the frame is visible
13150 before we do anything else. We do this loop with input not blocked
13151 so that incoming events are handled. */
13155 /* This must be before UNBLOCK_INPUT
13156 since events that arrive in response to the actions above
13157 will set it when they are handled. */
13158 int previously_visible
= f
->output_data
.x
->has_been_visible
;
13160 original_left
= f
->output_data
.x
->left_pos
;
13161 original_top
= f
->output_data
.x
->top_pos
;
13163 /* This must come after we set COUNT. */
13166 /* We unblock here so that arriving X events are processed. */
13168 /* Now move the window back to where it was "supposed to be".
13169 But don't do it if the gravity is negative.
13170 When the gravity is negative, this uses a position
13171 that is 3 pixels too low. Perhaps that's really the border width.
13173 Don't do this if the window has never been visible before,
13174 because the window manager may choose the position
13175 and we don't want to override it. */
13177 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
13178 && f
->output_data
.x
->win_gravity
== NorthWestGravity
13179 && previously_visible
)
13183 unsigned int width
, height
, border
, depth
;
13187 /* On some window managers (such as FVWM) moving an existing
13188 window, even to the same place, causes the window manager
13189 to introduce an offset. This can cause the window to move
13190 to an unexpected location. Check the geometry (a little
13191 slow here) and then verify that the window is in the right
13192 place. If the window is not in the right place, move it
13193 there, and take the potential window manager hit. */
13194 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
13195 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
13197 if (original_left
!= x
|| original_top
!= y
)
13198 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
13199 original_left
, original_top
);
13204 XSETFRAME (frame
, f
);
13206 /* Wait until the frame is visible. Process X events until a
13207 MapNotify event has been seen, or until we think we won't get a
13208 MapNotify at all.. */
13209 for (count
= input_signal_count
+ 10;
13210 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
13212 /* Force processing of queued events. */
13215 /* Machines that do polling rather than SIGIO have been
13216 observed to go into a busy-wait here. So we'll fake an
13217 alarm signal to let the handler know that there's something
13218 to be read. We used to raise a real alarm, but it seems
13219 that the handler isn't always enabled here. This is
13221 if (input_polling_used ())
13223 /* It could be confusing if a real alarm arrives while
13224 processing the fake one. Turn it off and let the
13225 handler reset it. */
13226 extern void poll_for_input_1
P_ ((void));
13227 int old_poll_suppress_count
= poll_suppress_count
;
13228 poll_suppress_count
= 1;
13229 poll_for_input_1 ();
13230 poll_suppress_count
= old_poll_suppress_count
;
13233 /* See if a MapNotify event has been processed. */
13234 FRAME_SAMPLE_VISIBILITY (f
);
13239 (let ((f (selected-frame)))
13243 the frame is not raised with various window managers on
13244 FreeBSD, Linux and Solaris. It turns out that, for some
13245 unknown reason, the call to XtMapWidget is completely ignored.
13246 Mapping the widget a second time works. */
13248 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
13253 /* Change from mapped state to withdrawn state. */
13255 /* Make the frame visible (mapped and not iconified). */
13258 x_make_frame_invisible (f
)
13263 #ifdef USE_X_TOOLKIT
13264 /* Use the frame's outermost window, not the one we normally draw on. */
13265 window
= XtWindow (f
->output_data
.x
->widget
);
13266 #else /* not USE_X_TOOLKIT */
13267 window
= FRAME_X_WINDOW (f
);
13268 #endif /* not USE_X_TOOLKIT */
13270 /* Don't keep the highlight on an invisible frame. */
13271 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
13272 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
13274 #if 0/* This might add unreliability; I don't trust it -- rms. */
13275 if (! f
->async_visible
&& ! f
->async_iconified
)
13281 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13282 that the current position of the window is user-specified, rather than
13283 program-specified, so that when the window is mapped again, it will be
13284 placed at the same location, without forcing the user to position it
13285 by hand again (they have already done that once for this window.) */
13286 x_wm_set_size_hint (f
, (long) 0, 1);
13290 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
13291 DefaultScreen (FRAME_X_DISPLAY (f
))))
13293 UNBLOCK_INPUT_RESIGNAL
;
13294 error ("Can't notify window manager of window withdrawal");
13296 #else /* ! defined (HAVE_X11R4) */
13298 /* Tell the window manager what we're going to do. */
13299 if (! EQ (Vx_no_window_manager
, Qt
))
13303 unmap
.xunmap
.type
= UnmapNotify
;
13304 unmap
.xunmap
.window
= window
;
13305 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
13306 unmap
.xunmap
.from_configure
= False
;
13307 if (! XSendEvent (FRAME_X_DISPLAY (f
),
13308 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
13310 SubstructureRedirectMaskSubstructureNotifyMask
,
13313 UNBLOCK_INPUT_RESIGNAL
;
13314 error ("Can't notify window manager of withdrawal");
13318 /* Unmap the window ourselves. Cheeky! */
13319 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
13320 #endif /* ! defined (HAVE_X11R4) */
13322 /* We can't distinguish this from iconification
13323 just by the event that we get from the server.
13324 So we can't win using the usual strategy of letting
13325 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13326 and synchronize with the server to make sure we agree. */
13328 FRAME_ICONIFIED_P (f
) = 0;
13329 f
->async_visible
= 0;
13330 f
->async_iconified
= 0;
13337 /* Change window state from mapped to iconified. */
13340 x_iconify_frame (f
)
13346 /* Don't keep the highlight on an invisible frame. */
13347 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
13348 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
13350 if (f
->async_iconified
)
13355 FRAME_SAMPLE_VISIBILITY (f
);
13357 type
= x_icon_type (f
);
13359 x_bitmap_icon (f
, type
);
13361 #ifdef USE_X_TOOLKIT
13363 if (! FRAME_VISIBLE_P (f
))
13365 if (! EQ (Vx_no_window_manager
, Qt
))
13366 x_wm_set_window_state (f
, IconicState
);
13367 /* This was XtPopup, but that did nothing for an iconified frame. */
13368 XtMapWidget (f
->output_data
.x
->widget
);
13369 /* The server won't give us any event to indicate
13370 that an invisible frame was changed to an icon,
13371 so we have to record it here. */
13374 f
->async_iconified
= 1;
13375 f
->async_visible
= 0;
13380 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
13381 XtWindow (f
->output_data
.x
->widget
),
13382 DefaultScreen (FRAME_X_DISPLAY (f
)));
13386 error ("Can't notify window manager of iconification");
13388 f
->async_iconified
= 1;
13389 f
->async_visible
= 0;
13393 XFlush (FRAME_X_DISPLAY (f
));
13395 #else /* not USE_X_TOOLKIT */
13397 /* Make sure the X server knows where the window should be positioned,
13398 in case the user deiconifies with the window manager. */
13399 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
13400 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
13402 /* Since we don't know which revision of X we're running, we'll use both
13403 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13405 /* X11R4: send a ClientMessage to the window manager using the
13406 WM_CHANGE_STATE type. */
13410 message
.xclient
.window
= FRAME_X_WINDOW (f
);
13411 message
.xclient
.type
= ClientMessage
;
13412 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
13413 message
.xclient
.format
= 32;
13414 message
.xclient
.data
.l
[0] = IconicState
;
13416 if (! XSendEvent (FRAME_X_DISPLAY (f
),
13417 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
13419 SubstructureRedirectMask
| SubstructureNotifyMask
,
13422 UNBLOCK_INPUT_RESIGNAL
;
13423 error ("Can't notify window manager of iconification");
13427 /* X11R3: set the initial_state field of the window manager hints to
13429 x_wm_set_window_state (f
, IconicState
);
13431 if (!FRAME_VISIBLE_P (f
))
13433 /* If the frame was withdrawn, before, we must map it. */
13434 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13437 f
->async_iconified
= 1;
13438 f
->async_visible
= 0;
13440 XFlush (FRAME_X_DISPLAY (f
));
13442 #endif /* not USE_X_TOOLKIT */
13446 /* Free X resources of frame F. */
13449 x_free_frame_resources (f
)
13452 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13454 struct scroll_bar
*b
;
13458 /* If a display connection is dead, don't try sending more
13459 commands to the X server. */
13460 if (dpyinfo
->display
)
13462 if (f
->output_data
.x
->icon_desc
)
13463 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
13465 #ifdef USE_X_TOOLKIT
13466 /* Explicitly destroy the scroll bars of the frame. Without
13467 this, we get "BadDrawable" errors from the toolkit later on,
13468 presumably from expose events generated for the disappearing
13469 toolkit scroll bars. */
13470 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
13472 b
= XSCROLL_BAR (bar
);
13473 x_scroll_bar_remove (b
);
13479 free_frame_xic (f
);
13482 #ifdef USE_X_TOOLKIT
13483 if (f
->output_data
.x
->widget
)
13485 XtDestroyWidget (f
->output_data
.x
->widget
);
13486 f
->output_data
.x
->widget
= NULL
;
13488 /* Tooltips don't have widgets, only a simple X window, even if
13489 we are using a toolkit. */
13490 else if (FRAME_X_WINDOW (f
))
13491 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13493 free_frame_menubar (f
);
13494 #else /* !USE_X_TOOLKIT */
13495 if (FRAME_X_WINDOW (f
))
13496 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13497 #endif /* !USE_X_TOOLKIT */
13499 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
13500 unload_color (f
, f
->output_data
.x
->background_pixel
);
13501 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
13502 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
13503 unload_color (f
, f
->output_data
.x
->border_pixel
);
13504 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
13506 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
13507 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
13508 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
13509 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
13510 #ifdef USE_TOOLKIT_SCROLL_BARS
13511 /* Scrollbar shadow colors. */
13512 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
13513 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
13514 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
13515 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
13516 #endif /* USE_TOOLKIT_SCROLL_BARS */
13517 if (f
->output_data
.x
->white_relief
.allocated_p
)
13518 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
13519 if (f
->output_data
.x
->black_relief
.allocated_p
)
13520 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
13522 if (FRAME_FACE_CACHE (f
))
13523 free_frame_faces (f
);
13526 XFlush (FRAME_X_DISPLAY (f
));
13529 if (f
->output_data
.x
->saved_menu_event
)
13530 xfree (f
->output_data
.x
->saved_menu_event
);
13532 xfree (f
->output_data
.x
);
13533 f
->output_data
.x
= NULL
;
13535 if (f
== dpyinfo
->x_focus_frame
)
13536 dpyinfo
->x_focus_frame
= 0;
13537 if (f
== dpyinfo
->x_focus_event_frame
)
13538 dpyinfo
->x_focus_event_frame
= 0;
13539 if (f
== dpyinfo
->x_highlight_frame
)
13540 dpyinfo
->x_highlight_frame
= 0;
13542 if (f
== dpyinfo
->mouse_face_mouse_frame
)
13544 dpyinfo
->mouse_face_beg_row
13545 = dpyinfo
->mouse_face_beg_col
= -1;
13546 dpyinfo
->mouse_face_end_row
13547 = dpyinfo
->mouse_face_end_col
= -1;
13548 dpyinfo
->mouse_face_window
= Qnil
;
13549 dpyinfo
->mouse_face_deferred_gc
= 0;
13550 dpyinfo
->mouse_face_mouse_frame
= 0;
13557 /* Destroy the X window of frame F. */
13560 x_destroy_window (f
)
13563 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13565 /* If a display connection is dead, don't try sending more
13566 commands to the X server. */
13567 if (dpyinfo
->display
!= 0)
13568 x_free_frame_resources (f
);
13570 dpyinfo
->reference_count
--;
13574 /* Setting window manager hints. */
13576 /* Set the normal size hints for the window manager, for frame F.
13577 FLAGS is the flags word to use--or 0 meaning preserve the flags
13578 that the window now has.
13579 If USER_POSITION is nonzero, we set the USPosition
13580 flag (this is useful when FLAGS is 0). */
13583 x_wm_set_size_hint (f
, flags
, user_position
)
13588 XSizeHints size_hints
;
13590 #ifdef USE_X_TOOLKIT
13593 Dimension widget_width
, widget_height
;
13594 Window window
= XtWindow (f
->output_data
.x
->widget
);
13595 #else /* not USE_X_TOOLKIT */
13596 Window window
= FRAME_X_WINDOW (f
);
13597 #endif /* not USE_X_TOOLKIT */
13599 /* Setting PMaxSize caused various problems. */
13600 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
13602 size_hints
.x
= f
->output_data
.x
->left_pos
;
13603 size_hints
.y
= f
->output_data
.x
->top_pos
;
13605 #ifdef USE_X_TOOLKIT
13606 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
13607 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
13608 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
13609 size_hints
.height
= widget_height
;
13610 size_hints
.width
= widget_width
;
13611 #else /* not USE_X_TOOLKIT */
13612 size_hints
.height
= PIXEL_HEIGHT (f
);
13613 size_hints
.width
= PIXEL_WIDTH (f
);
13614 #endif /* not USE_X_TOOLKIT */
13616 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
13617 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
13618 size_hints
.max_width
13619 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
13620 size_hints
.max_height
13621 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
13623 /* Calculate the base and minimum sizes.
13625 (When we use the X toolkit, we don't do it here.
13626 Instead we copy the values that the widgets are using, below.) */
13627 #ifndef USE_X_TOOLKIT
13629 int base_width
, base_height
;
13630 int min_rows
= 0, min_cols
= 0;
13632 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
13633 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
13635 check_frame_size (f
, &min_rows
, &min_cols
);
13637 /* The window manager uses the base width hints to calculate the
13638 current number of rows and columns in the frame while
13639 resizing; min_width and min_height aren't useful for this
13640 purpose, since they might not give the dimensions for a
13641 zero-row, zero-column frame.
13643 We use the base_width and base_height members if we have
13644 them; otherwise, we set the min_width and min_height members
13645 to the size for a zero x zero frame. */
13648 size_hints
.flags
|= PBaseSize
;
13649 size_hints
.base_width
= base_width
;
13650 size_hints
.base_height
= base_height
;
13651 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
13652 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
13654 size_hints
.min_width
= base_width
;
13655 size_hints
.min_height
= base_height
;
13659 /* If we don't need the old flags, we don't need the old hint at all. */
13662 size_hints
.flags
|= flags
;
13665 #endif /* not USE_X_TOOLKIT */
13668 XSizeHints hints
; /* Sometimes I hate X Windows... */
13669 long supplied_return
;
13673 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
13676 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
13679 #ifdef USE_X_TOOLKIT
13680 size_hints
.base_height
= hints
.base_height
;
13681 size_hints
.base_width
= hints
.base_width
;
13682 size_hints
.min_height
= hints
.min_height
;
13683 size_hints
.min_width
= hints
.min_width
;
13687 size_hints
.flags
|= flags
;
13692 if (hints
.flags
& PSize
)
13693 size_hints
.flags
|= PSize
;
13694 if (hints
.flags
& PPosition
)
13695 size_hints
.flags
|= PPosition
;
13696 if (hints
.flags
& USPosition
)
13697 size_hints
.flags
|= USPosition
;
13698 if (hints
.flags
& USSize
)
13699 size_hints
.flags
|= USSize
;
13703 #ifndef USE_X_TOOLKIT
13708 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
13709 size_hints
.flags
|= PWinGravity
;
13713 size_hints
.flags
&= ~ PPosition
;
13714 size_hints
.flags
|= USPosition
;
13716 #endif /* PWinGravity */
13719 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
13721 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
13725 /* Used for IconicState or NormalState */
13728 x_wm_set_window_state (f
, state
)
13732 #ifdef USE_X_TOOLKIT
13735 XtSetArg (al
[0], XtNinitialState
, state
);
13736 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
13737 #else /* not USE_X_TOOLKIT */
13738 Window window
= FRAME_X_WINDOW (f
);
13740 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
13741 f
->output_data
.x
->wm_hints
.initial_state
= state
;
13743 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13744 #endif /* not USE_X_TOOLKIT */
13748 x_wm_set_icon_pixmap (f
, pixmap_id
)
13752 Pixmap icon_pixmap
;
13754 #ifndef USE_X_TOOLKIT
13755 Window window
= FRAME_X_WINDOW (f
);
13760 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
13761 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
13765 /* It seems there is no way to turn off use of an icon pixmap.
13766 The following line does it, only if no icon has yet been created,
13767 for some window managers. But with mwm it crashes.
13768 Some people say it should clear the IconPixmapHint bit in this case,
13769 but that doesn't work, and the X consortium said it isn't the
13770 right thing at all. Since there is no way to win,
13771 best to explicitly give up. */
13773 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
13779 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13783 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
13784 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
13787 #else /* not USE_X_TOOLKIT */
13789 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
13790 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13792 #endif /* not USE_X_TOOLKIT */
13796 x_wm_set_icon_position (f
, icon_x
, icon_y
)
13798 int icon_x
, icon_y
;
13800 #ifdef USE_X_TOOLKIT
13801 Window window
= XtWindow (f
->output_data
.x
->widget
);
13803 Window window
= FRAME_X_WINDOW (f
);
13806 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
13807 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
13808 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
13810 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13814 /***********************************************************************
13816 ***********************************************************************/
13818 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13821 x_get_font_info (f
, font_idx
)
13825 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
13829 /* Return a list of names of available fonts matching PATTERN on frame F.
13831 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13834 SIZE < 0 means include scalable fonts.
13836 Frame F null means we have not yet created any frame on X, and
13837 consult the first display in x_display_list. MAXNAMES sets a limit
13838 on how many fonts to match. */
13841 x_list_fonts (f
, pattern
, size
, maxnames
)
13843 Lisp_Object pattern
;
13847 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
13848 Lisp_Object tem
, second_best
;
13849 struct x_display_info
*dpyinfo
13850 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
13851 Display
*dpy
= dpyinfo
->display
;
13852 int try_XLoadQueryFont
= 0;
13854 int allow_scalable_fonts_p
= 0;
13858 allow_scalable_fonts_p
= 1;
13862 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
13863 if (NILP (patterns
))
13864 patterns
= Fcons (pattern
, Qnil
);
13866 if (maxnames
== 1 && !size
)
13867 /* We can return any single font matching PATTERN. */
13868 try_XLoadQueryFont
= 1;
13870 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
13873 char **names
= NULL
;
13875 pattern
= XCAR (patterns
);
13876 /* See if we cached the result for this particular query.
13877 The cache is an alist of the form:
13878 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13879 tem
= XCDR (dpyinfo
->name_list_element
);
13880 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
13881 allow_scalable_fonts_p
? Qt
: Qnil
);
13882 list
= Fassoc (key
, tem
);
13885 list
= Fcdr_safe (list
);
13886 /* We have a cashed list. Don't have to get the list again. */
13890 /* At first, put PATTERN in the cache. */
13893 count
= x_catch_errors (dpy
);
13895 if (try_XLoadQueryFont
)
13898 unsigned long value
;
13900 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
13901 if (x_had_errors_p (dpy
))
13903 /* This error is perhaps due to insufficient memory on X
13904 server. Let's just ignore it. */
13906 x_clear_errors (dpy
);
13910 && XGetFontProperty (font
, XA_FONT
, &value
))
13912 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
13913 int len
= strlen (name
);
13916 /* If DXPC (a Differential X Protocol Compressor)
13917 Ver.3.7 is running, XGetAtomName will return null
13918 string. We must avoid such a name. */
13920 try_XLoadQueryFont
= 0;
13924 names
= (char **) alloca (sizeof (char *));
13925 /* Some systems only allow alloca assigned to a
13927 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
13928 bcopy (name
, names
[0], len
+ 1);
13933 try_XLoadQueryFont
= 0;
13936 XFreeFont (dpy
, font
);
13939 if (!try_XLoadQueryFont
)
13941 /* We try at least 10 fonts because XListFonts will return
13942 auto-scaled fonts at the head. */
13943 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
13945 if (x_had_errors_p (dpy
))
13947 /* This error is perhaps due to insufficient memory on X
13948 server. Let's just ignore it. */
13950 x_clear_errors (dpy
);
13954 x_uncatch_errors (dpy
, count
);
13961 /* Make a list of all the fonts we got back.
13962 Store that in the font cache for the display. */
13963 for (i
= 0; i
< num_fonts
; i
++)
13966 char *p
= names
[i
];
13967 int average_width
= -1, dashes
= 0;
13969 /* Count the number of dashes in NAMES[I]. If there are
13970 14 dashes, and the field value following 12th dash
13971 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13972 is usually too ugly to be used for editing. Let's
13978 if (dashes
== 7) /* PIXEL_SIZE field */
13980 else if (dashes
== 12) /* AVERAGE_WIDTH field */
13981 average_width
= atoi (p
);
13984 if (allow_scalable_fonts_p
13985 || dashes
< 14 || average_width
!= 0)
13987 tem
= build_string (names
[i
]);
13988 if (NILP (Fassoc (tem
, list
)))
13990 if (STRINGP (Vx_pixel_size_width_font_regexp
)
13991 && ((fast_c_string_match_ignore_case
13992 (Vx_pixel_size_width_font_regexp
, names
[i
]))
13994 /* We can set the value of PIXEL_SIZE to the
13995 width of this font. */
13996 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
13998 /* For the moment, width is not known. */
13999 list
= Fcons (Fcons (tem
, Qnil
), list
);
14004 if (!try_XLoadQueryFont
)
14007 XFreeFontNames (names
);
14012 /* Now store the result in the cache. */
14013 XSETCDR (dpyinfo
->name_list_element
,
14014 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
14017 if (NILP (list
)) continue; /* Try the remaining alternatives. */
14019 newlist
= second_best
= Qnil
;
14020 /* Make a list of the fonts that have the right width. */
14021 for (; CONSP (list
); list
= XCDR (list
))
14027 if (!CONSP (tem
) || NILP (XCAR (tem
)))
14031 newlist
= Fcons (XCAR (tem
), newlist
);
14035 if (!INTEGERP (XCDR (tem
)))
14037 /* Since we have not yet known the size of this font, we
14038 must try slow function call XLoadQueryFont. */
14039 XFontStruct
*thisinfo
;
14042 count
= x_catch_errors (dpy
);
14043 thisinfo
= XLoadQueryFont (dpy
,
14044 XSTRING (XCAR (tem
))->data
);
14045 if (x_had_errors_p (dpy
))
14047 /* This error is perhaps due to insufficient memory on X
14048 server. Let's just ignore it. */
14050 x_clear_errors (dpy
);
14052 x_uncatch_errors (dpy
, count
);
14058 (thisinfo
->min_bounds
.width
== 0
14060 : make_number (thisinfo
->max_bounds
.width
)));
14062 XFreeFont (dpy
, thisinfo
);
14066 /* For unknown reason, the previous call of XListFont had
14067 returned a font which can't be opened. Record the size
14068 as 0 not to try to open it again. */
14069 XSETCDR (tem
, make_number (0));
14072 found_size
= XINT (XCDR (tem
));
14073 if (found_size
== size
)
14074 newlist
= Fcons (XCAR (tem
), newlist
);
14075 else if (found_size
> 0)
14077 if (NILP (second_best
))
14079 else if (found_size
< size
)
14081 if (XINT (XCDR (second_best
)) > size
14082 || XINT (XCDR (second_best
)) < found_size
)
14087 if (XINT (XCDR (second_best
)) > size
14088 && XINT (XCDR (second_best
)) > found_size
)
14093 if (!NILP (newlist
))
14095 else if (!NILP (second_best
))
14097 newlist
= Fcons (XCAR (second_best
), Qnil
);
14108 /* Check that FONT is valid on frame F. It is if it can be found in F's
14112 x_check_font (f
, font
)
14117 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14119 xassert (font
!= NULL
);
14121 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14122 if (dpyinfo
->font_table
[i
].name
14123 && font
== dpyinfo
->font_table
[i
].font
)
14126 xassert (i
< dpyinfo
->n_fonts
);
14129 #endif /* GLYPH_DEBUG != 0 */
14131 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14132 Note: There are (broken) X fonts out there with invalid XFontStruct
14133 min_bounds contents. For example, handa@etl.go.jp reports that
14134 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14135 have font->min_bounds.width == 0. */
14138 x_font_min_bounds (font
, w
, h
)
14142 *h
= FONT_HEIGHT (font
);
14143 *w
= font
->min_bounds
.width
;
14145 /* Try to handle the case where FONT->min_bounds has invalid
14146 contents. Since the only font known to have invalid min_bounds
14147 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14149 *w
= font
->max_bounds
.width
;
14153 /* Compute the smallest character width and smallest font height over
14154 all fonts available on frame F. Set the members smallest_char_width
14155 and smallest_font_height in F's x_display_info structure to
14156 the values computed. Value is non-zero if smallest_font_height or
14157 smallest_char_width become smaller than they were before. */
14160 x_compute_min_glyph_bounds (f
)
14164 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14166 int old_width
= dpyinfo
->smallest_char_width
;
14167 int old_height
= dpyinfo
->smallest_font_height
;
14169 dpyinfo
->smallest_font_height
= 100000;
14170 dpyinfo
->smallest_char_width
= 100000;
14172 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
14173 if (dpyinfo
->font_table
[i
].name
)
14175 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
14178 font
= (XFontStruct
*) fontp
->font
;
14179 xassert (font
!= (XFontStruct
*) ~0);
14180 x_font_min_bounds (font
, &w
, &h
);
14182 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
14183 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
14186 xassert (dpyinfo
->smallest_char_width
> 0
14187 && dpyinfo
->smallest_font_height
> 0);
14189 return (dpyinfo
->n_fonts
== 1
14190 || dpyinfo
->smallest_char_width
< old_width
14191 || dpyinfo
->smallest_font_height
< old_height
);
14195 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14196 pointer to the structure font_info while allocating it dynamically.
14197 If SIZE is 0, load any size of font.
14198 If loading is failed, return NULL. */
14201 x_load_font (f
, fontname
, size
)
14203 register char *fontname
;
14206 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14207 Lisp_Object font_names
;
14210 /* Get a list of all the fonts that match this name. Once we
14211 have a list of matching fonts, we compare them against the fonts
14212 we already have by comparing names. */
14213 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
14215 if (!NILP (font_names
))
14220 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14221 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
14222 if (dpyinfo
->font_table
[i
].name
14223 && (!strcmp (dpyinfo
->font_table
[i
].name
,
14224 XSTRING (XCAR (tail
))->data
)
14225 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
14226 XSTRING (XCAR (tail
))->data
)))
14227 return (dpyinfo
->font_table
+ i
);
14230 /* Load the font and add it to the table. */
14234 struct font_info
*fontp
;
14235 unsigned long value
;
14238 /* If we have found fonts by x_list_font, load one of them. If
14239 not, we still try to load a font by the name given as FONTNAME
14240 because XListFonts (called in x_list_font) of some X server has
14241 a bug of not finding a font even if the font surely exists and
14242 is loadable by XLoadQueryFont. */
14243 if (size
> 0 && !NILP (font_names
))
14244 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
14247 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
14248 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
14249 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
14251 /* This error is perhaps due to insufficient memory on X
14252 server. Let's just ignore it. */
14254 x_clear_errors (FRAME_X_DISPLAY (f
));
14256 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
14261 /* Find a free slot in the font table. */
14262 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
14263 if (dpyinfo
->font_table
[i
].name
== NULL
)
14266 /* If no free slot found, maybe enlarge the font table. */
14267 if (i
== dpyinfo
->n_fonts
14268 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
14271 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
14272 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
14273 dpyinfo
->font_table
14274 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
14277 fontp
= dpyinfo
->font_table
+ i
;
14278 if (i
== dpyinfo
->n_fonts
)
14279 ++dpyinfo
->n_fonts
;
14281 /* Now fill in the slots of *FONTP. */
14283 fontp
->font
= font
;
14284 fontp
->font_idx
= i
;
14285 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
14286 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
14288 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14290 if (XGetFontProperty (font
, XA_FONT
, &value
))
14292 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
14296 /* Count the number of dashes in the "full name".
14297 If it is too few, this isn't really the font's full name,
14299 In X11R4, the fonts did not come with their canonical names
14310 full_name
= (char *) xmalloc (p
- name
+ 1);
14311 bcopy (name
, full_name
, p
- name
+ 1);
14317 if (full_name
!= 0)
14318 fontp
->full_name
= full_name
;
14320 fontp
->full_name
= fontp
->name
;
14322 fontp
->size
= font
->max_bounds
.width
;
14323 fontp
->height
= FONT_HEIGHT (font
);
14325 if (NILP (font_names
))
14327 /* We come here because of a bug of XListFonts mentioned at
14328 the head of this block. Let's store this information in
14329 the cache for x_list_fonts. */
14330 Lisp_Object lispy_name
= build_string (fontname
);
14331 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
14332 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
14335 XSETCDR (dpyinfo
->name_list_element
,
14337 Fcons (Fcons (lispy_full_name
,
14338 make_number (fontp
->size
)),
14340 XCDR (dpyinfo
->name_list_element
)));
14343 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
14345 XSETCDR (dpyinfo
->name_list_element
,
14347 Fcons (Fcons (lispy_full_name
,
14348 make_number (fontp
->size
)),
14350 XCDR (dpyinfo
->name_list_element
)));
14354 /* The slot `encoding' specifies how to map a character
14355 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14356 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14357 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14358 2:0xA020..0xFF7F). For the moment, we don't know which charset
14359 uses this font. So, we set information in fontp->encoding[1]
14360 which is never used by any charset. If mapping can't be
14361 decided, set FONT_ENCODING_NOT_DECIDED. */
14362 fontp
->encoding_type
14363 = (font
->max_byte1
== 0
14365 ? (font
->min_char_or_byte2
< 0x80
14366 ? (font
->max_char_or_byte2
< 0x80
14367 ? 0 /* 0x20..0x7F */
14368 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
14369 : 1) /* 0xA0..0xFF */
14371 : (font
->min_byte1
< 0x80
14372 ? (font
->max_byte1
< 0x80
14373 ? (font
->min_char_or_byte2
< 0x80
14374 ? (font
->max_char_or_byte2
< 0x80
14375 ? 0 /* 0x2020..0x7F7F */
14376 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
14377 : 3) /* 0x20A0..0x7FFF */
14378 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
14379 : (font
->min_char_or_byte2
< 0x80
14380 ? (font
->max_char_or_byte2
< 0x80
14381 ? 2 /* 0xA020..0xFF7F */
14382 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
14383 : 1))); /* 0xA0A0..0xFFFF */
14385 fontp
->baseline_offset
14386 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
14387 ? (long) value
: 0);
14388 fontp
->relative_compose
14389 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
14390 ? (long) value
: 0);
14391 fontp
->default_ascent
14392 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
14393 ? (long) value
: 0);
14395 /* Set global flag fonts_changed_p to non-zero if the font loaded
14396 has a character with a smaller width than any other character
14397 before, or if the font loaded has a smaller height than any
14398 other font loaded before. If this happens, it will make a
14399 glyph matrix reallocation necessary. */
14400 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
14407 /* Return a pointer to struct font_info of a font named FONTNAME for
14408 frame F. If no such font is loaded, return NULL. */
14411 x_query_font (f
, fontname
)
14413 register char *fontname
;
14415 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14418 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14419 if (dpyinfo
->font_table
[i
].name
14420 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
14421 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
14422 return (dpyinfo
->font_table
+ i
);
14427 /* Find a CCL program for a font specified by FONTP, and set the member
14428 `encoder' of the structure. */
14431 x_find_ccl_program (fontp
)
14432 struct font_info
*fontp
;
14434 Lisp_Object list
, elt
;
14437 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
14441 && STRINGP (XCAR (elt
))
14442 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
14444 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
14451 struct ccl_program
*ccl
14452 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
14454 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
14457 fontp
->font_encoder
= ccl
;
14463 /***********************************************************************
14465 ***********************************************************************/
14467 #ifdef USE_X_TOOLKIT
14468 static XrmOptionDescRec emacs_options
[] = {
14469 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
14470 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
14472 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14473 XrmoptionSepArg
, NULL
},
14474 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
14476 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14477 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14478 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14479 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
14480 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
14481 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
14482 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
14484 #endif /* USE_X_TOOLKIT */
14486 static int x_initialized
;
14488 #ifdef MULTI_KBOARD
14489 /* Test whether two display-name strings agree up to the dot that separates
14490 the screen number from the server number. */
14492 same_x_server (name1
, name2
)
14493 char *name1
, *name2
;
14495 int seen_colon
= 0;
14496 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
14497 int system_name_length
= strlen (system_name
);
14498 int length_until_period
= 0;
14500 while (system_name
[length_until_period
] != 0
14501 && system_name
[length_until_period
] != '.')
14502 length_until_period
++;
14504 /* Treat `unix' like an empty host name. */
14505 if (! strncmp (name1
, "unix:", 5))
14507 if (! strncmp (name2
, "unix:", 5))
14509 /* Treat this host's name like an empty host name. */
14510 if (! strncmp (name1
, system_name
, system_name_length
)
14511 && name1
[system_name_length
] == ':')
14512 name1
+= system_name_length
;
14513 if (! strncmp (name2
, system_name
, system_name_length
)
14514 && name2
[system_name_length
] == ':')
14515 name2
+= system_name_length
;
14516 /* Treat this host's domainless name like an empty host name. */
14517 if (! strncmp (name1
, system_name
, length_until_period
)
14518 && name1
[length_until_period
] == ':')
14519 name1
+= length_until_period
;
14520 if (! strncmp (name2
, system_name
, length_until_period
)
14521 && name2
[length_until_period
] == ':')
14522 name2
+= length_until_period
;
14524 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
14528 if (seen_colon
&& *name1
== '.')
14532 && (*name1
== '.' || *name1
== '\0')
14533 && (*name2
== '.' || *name2
== '\0'));
14537 struct x_display_info
*
14538 x_term_init (display_name
, xrm_option
, resource_name
)
14539 Lisp_Object display_name
;
14541 char *resource_name
;
14545 struct x_display_info
*dpyinfo
;
14550 if (!x_initialized
)
14556 #ifdef USE_X_TOOLKIT
14557 /* weiner@footloose.sps.mot.com reports that this causes
14559 X protocol error: BadAtom (invalid Atom parameter)
14560 on protocol request 18skiloaf.
14561 So let's not use it until R6. */
14562 #ifdef HAVE_X11XTR6
14563 XtSetLanguageProc (NULL
, NULL
, NULL
);
14574 argv
[argc
++] = "-xrm";
14575 argv
[argc
++] = xrm_option
;
14577 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
14578 resource_name
, EMACS_CLASS
,
14579 emacs_options
, XtNumber (emacs_options
),
14582 #ifdef HAVE_X11XTR6
14583 /* I think this is to compensate for XtSetLanguageProc. */
14588 #else /* not USE_X_TOOLKIT */
14590 XSetLocaleModifiers ("");
14592 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
14593 #endif /* not USE_X_TOOLKIT */
14595 /* Detect failure. */
14602 /* We have definitely succeeded. Record the new connection. */
14604 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
14605 bzero (dpyinfo
, sizeof *dpyinfo
);
14607 #ifdef MULTI_KBOARD
14609 struct x_display_info
*share
;
14612 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
14613 share
= share
->next
, tail
= XCDR (tail
))
14614 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
14615 XSTRING (display_name
)->data
))
14618 dpyinfo
->kboard
= share
->kboard
;
14621 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
14622 init_kboard (dpyinfo
->kboard
);
14623 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
14625 char *vendor
= ServerVendor (dpy
);
14627 dpyinfo
->kboard
->Vsystem_key_alist
14628 = call1 (Qvendor_specific_keysyms
,
14629 build_string (vendor
? vendor
: ""));
14633 dpyinfo
->kboard
->next_kboard
= all_kboards
;
14634 all_kboards
= dpyinfo
->kboard
;
14635 /* Don't let the initial kboard remain current longer than necessary.
14636 That would cause problems if a file loaded on startup tries to
14637 prompt in the mini-buffer. */
14638 if (current_kboard
== initial_kboard
)
14639 current_kboard
= dpyinfo
->kboard
;
14641 dpyinfo
->kboard
->reference_count
++;
14645 /* Put this display on the chain. */
14646 dpyinfo
->next
= x_display_list
;
14647 x_display_list
= dpyinfo
;
14649 /* Put it on x_display_name_list as well, to keep them parallel. */
14650 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
14651 x_display_name_list
);
14652 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
14654 dpyinfo
->display
= dpy
;
14657 XSetAfterFunction (x_current_display
, x_trace_wire
);
14661 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
14662 + STRING_BYTES (XSTRING (Vsystem_name
))
14664 sprintf (dpyinfo
->x_id_name
, "%s@%s",
14665 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
14667 /* Figure out which modifier bits mean what. */
14668 x_find_modifier_meanings (dpyinfo
);
14670 /* Get the scroll bar cursor. */
14671 dpyinfo
->vertical_scroll_bar_cursor
14672 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
14674 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
14675 resource_name
, EMACS_CLASS
);
14676 #ifdef HAVE_XRMSETDATABASE
14677 XrmSetDatabase (dpyinfo
->display
, xrdb
);
14679 dpyinfo
->display
->db
= xrdb
;
14681 /* Put the rdb where we can find it in a way that works on
14683 dpyinfo
->xrdb
= xrdb
;
14685 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
14686 DefaultScreen (dpyinfo
->display
));
14687 select_visual (dpyinfo
);
14688 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
14689 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
14690 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
14691 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
14692 dpyinfo
->grabbed
= 0;
14693 dpyinfo
->reference_count
= 0;
14694 dpyinfo
->icon_bitmap_id
= -1;
14695 dpyinfo
->font_table
= NULL
;
14696 dpyinfo
->n_fonts
= 0;
14697 dpyinfo
->font_table_size
= 0;
14698 dpyinfo
->bitmaps
= 0;
14699 dpyinfo
->bitmaps_size
= 0;
14700 dpyinfo
->bitmaps_last
= 0;
14701 dpyinfo
->scratch_cursor_gc
= 0;
14702 dpyinfo
->mouse_face_mouse_frame
= 0;
14703 dpyinfo
->mouse_face_deferred_gc
= 0;
14704 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
14705 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
14706 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
14707 dpyinfo
->mouse_face_window
= Qnil
;
14708 dpyinfo
->mouse_face_overlay
= Qnil
;
14709 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
14710 dpyinfo
->mouse_face_defer
= 0;
14711 dpyinfo
->mouse_face_hidden
= 0;
14712 dpyinfo
->x_focus_frame
= 0;
14713 dpyinfo
->x_focus_event_frame
= 0;
14714 dpyinfo
->x_highlight_frame
= 0;
14715 dpyinfo
->image_cache
= make_image_cache ();
14717 /* See if a private colormap is requested. */
14718 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
14720 if (dpyinfo
->visual
->class == PseudoColor
)
14723 value
= display_x_get_resource (dpyinfo
,
14724 build_string ("privateColormap"),
14725 build_string ("PrivateColormap"),
14727 if (STRINGP (value
)
14728 && (!strcmp (XSTRING (value
)->data
, "true")
14729 || !strcmp (XSTRING (value
)->data
, "on")))
14730 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
14734 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
14735 dpyinfo
->visual
, AllocNone
);
14738 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
14739 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
14740 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
14741 dpyinfo
->resy
= pixels
* 25.4 / mm
;
14742 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
14743 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
14744 dpyinfo
->resx
= pixels
* 25.4 / mm
;
14747 dpyinfo
->Xatom_wm_protocols
14748 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
14749 dpyinfo
->Xatom_wm_take_focus
14750 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
14751 dpyinfo
->Xatom_wm_save_yourself
14752 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
14753 dpyinfo
->Xatom_wm_delete_window
14754 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
14755 dpyinfo
->Xatom_wm_change_state
14756 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
14757 dpyinfo
->Xatom_wm_configure_denied
14758 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
14759 dpyinfo
->Xatom_wm_window_moved
14760 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
14761 dpyinfo
->Xatom_editres
14762 = XInternAtom (dpyinfo
->display
, "Editres", False
);
14763 dpyinfo
->Xatom_CLIPBOARD
14764 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
14765 dpyinfo
->Xatom_TIMESTAMP
14766 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
14767 dpyinfo
->Xatom_TEXT
14768 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
14769 dpyinfo
->Xatom_COMPOUND_TEXT
14770 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
14771 dpyinfo
->Xatom_DELETE
14772 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
14773 dpyinfo
->Xatom_MULTIPLE
14774 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
14775 dpyinfo
->Xatom_INCR
14776 = XInternAtom (dpyinfo
->display
, "INCR", False
);
14777 dpyinfo
->Xatom_EMACS_TMP
14778 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
14779 dpyinfo
->Xatom_TARGETS
14780 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
14781 dpyinfo
->Xatom_NULL
14782 = XInternAtom (dpyinfo
->display
, "NULL", False
);
14783 dpyinfo
->Xatom_ATOM_PAIR
14784 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
14785 /* For properties of font. */
14786 dpyinfo
->Xatom_PIXEL_SIZE
14787 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
14788 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
14789 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
14790 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
14791 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
14792 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
14793 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
14795 /* Ghostscript support. */
14796 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
14797 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
14799 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
14802 dpyinfo
->cut_buffers_initialized
= 0;
14804 connection
= ConnectionNumber (dpyinfo
->display
);
14805 dpyinfo
->connection
= connection
;
14810 null_bits
[0] = 0x00;
14812 dpyinfo
->null_pixel
14813 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
14814 null_bits
, 1, 1, (long) 0, (long) 0,
14819 extern int gray_bitmap_width
, gray_bitmap_height
;
14820 extern char *gray_bitmap_bits
;
14822 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
14824 gray_bitmap_width
, gray_bitmap_height
,
14825 (unsigned long) 1, (unsigned long) 0, 1);
14829 xim_initialize (dpyinfo
, resource_name
);
14832 #ifdef subprocesses
14833 /* This is only needed for distinguishing keyboard and process input. */
14834 if (connection
!= 0)
14835 add_keyboard_wait_descriptor (connection
);
14838 #ifndef F_SETOWN_BUG
14840 #ifdef F_SETOWN_SOCK_NEG
14841 /* stdin is a socket here */
14842 fcntl (connection
, F_SETOWN
, -getpid ());
14843 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14844 fcntl (connection
, F_SETOWN
, getpid ());
14845 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14846 #endif /* ! defined (F_SETOWN) */
14847 #endif /* F_SETOWN_BUG */
14850 if (interrupt_input
)
14851 init_sigio (connection
);
14852 #endif /* ! defined (SIGIO) */
14855 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14856 /* Make sure that we have a valid font for dialog boxes
14857 so that Xt does not crash. */
14859 Display
*dpy
= dpyinfo
->display
;
14860 XrmValue d
, fr
, to
;
14864 d
.addr
= (XPointer
)&dpy
;
14865 d
.size
= sizeof (Display
*);
14866 fr
.addr
= XtDefaultFont
;
14867 fr
.size
= sizeof (XtDefaultFont
);
14868 to
.size
= sizeof (Font
*);
14869 to
.addr
= (XPointer
)&font
;
14870 count
= x_catch_errors (dpy
);
14871 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
14873 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
14874 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
14875 x_uncatch_errors (dpy
, count
);
14880 /* See if we should run in synchronous mode. This is useful
14881 for debugging X code. */
14884 value
= display_x_get_resource (dpyinfo
,
14885 build_string ("synchronous"),
14886 build_string ("Synchronous"),
14888 if (STRINGP (value
)
14889 && (!strcmp (XSTRING (value
)->data
, "true")
14890 || !strcmp (XSTRING (value
)->data
, "on")))
14891 XSynchronize (dpyinfo
->display
, True
);
14899 /* Get rid of display DPYINFO, assuming all frames are already gone,
14900 and without sending any more commands to the X server. */
14903 x_delete_display (dpyinfo
)
14904 struct x_display_info
*dpyinfo
;
14906 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
14908 /* Discard this display from x_display_name_list and x_display_list.
14909 We can't use Fdelq because that can quit. */
14910 if (! NILP (x_display_name_list
)
14911 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
14912 x_display_name_list
= XCDR (x_display_name_list
);
14917 tail
= x_display_name_list
;
14918 while (CONSP (tail
) && CONSP (XCDR (tail
)))
14920 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
14922 XSETCDR (tail
, XCDR (XCDR (tail
)));
14925 tail
= XCDR (tail
);
14929 if (next_noop_dpyinfo
== dpyinfo
)
14930 next_noop_dpyinfo
= dpyinfo
->next
;
14932 if (x_display_list
== dpyinfo
)
14933 x_display_list
= dpyinfo
->next
;
14936 struct x_display_info
*tail
;
14938 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
14939 if (tail
->next
== dpyinfo
)
14940 tail
->next
= tail
->next
->next
;
14943 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14944 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14945 XrmDestroyDatabase (dpyinfo
->xrdb
);
14948 #ifdef MULTI_KBOARD
14949 if (--dpyinfo
->kboard
->reference_count
== 0)
14950 delete_kboard (dpyinfo
->kboard
);
14954 xim_close_dpy (dpyinfo
);
14957 xfree (dpyinfo
->font_table
);
14958 xfree (dpyinfo
->x_id_name
);
14959 xfree (dpyinfo
->color_cells
);
14964 /* Set up use of X before we make the first connection. */
14966 static struct redisplay_interface x_redisplay_interface
=
14971 x_clear_end_of_line
,
14973 x_after_update_window_line
,
14974 x_update_window_begin
,
14975 x_update_window_end
,
14978 x_clear_mouse_face
,
14979 x_get_glyph_overhangs
,
14980 x_fix_overlapping_area
14986 rif
= &x_redisplay_interface
;
14988 clear_frame_hook
= x_clear_frame
;
14989 ins_del_lines_hook
= x_ins_del_lines
;
14990 delete_glyphs_hook
= x_delete_glyphs
;
14991 ring_bell_hook
= XTring_bell
;
14992 reset_terminal_modes_hook
= XTreset_terminal_modes
;
14993 set_terminal_modes_hook
= XTset_terminal_modes
;
14994 update_begin_hook
= x_update_begin
;
14995 update_end_hook
= x_update_end
;
14996 set_terminal_window_hook
= XTset_terminal_window
;
14997 read_socket_hook
= XTread_socket
;
14998 frame_up_to_date_hook
= XTframe_up_to_date
;
14999 mouse_position_hook
= XTmouse_position
;
15000 frame_rehighlight_hook
= XTframe_rehighlight
;
15001 frame_raise_lower_hook
= XTframe_raise_lower
;
15002 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
15003 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
15004 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
15005 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
15006 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
15008 scroll_region_ok
= 1; /* we'll scroll partial frames */
15009 char_ins_del_ok
= 1;
15010 line_ins_del_ok
= 1; /* we'll just blt 'em */
15011 fast_clear_end_of_line
= 1; /* X does this well */
15012 memory_below_frame
= 0; /* we don't remember what scrolls
15017 last_tool_bar_item
= -1;
15018 any_help_event_p
= 0;
15020 /* Try to use interrupt input; if we can't, then start polling. */
15021 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
15023 #ifdef USE_X_TOOLKIT
15024 XtToolkitInitialize ();
15026 Xt_app_con
= XtCreateApplicationContext ();
15028 /* Register a converter from strings to pixels, which uses
15029 Emacs' color allocation infrastructure. */
15030 XtAppSetTypeConverter (Xt_app_con
,
15031 XtRString
, XtRPixel
, cvt_string_to_pixel
,
15032 cvt_string_to_pixel_args
,
15033 XtNumber (cvt_string_to_pixel_args
),
15034 XtCacheByDisplay
, cvt_pixel_dtor
);
15036 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
15038 /* Install an asynchronous timer that processes Xt timeout events
15039 every 0.1s. This is necessary because some widget sets use
15040 timeouts internally, for example the LessTif menu bar, or the
15041 Xaw3d scroll bar. When Xt timouts aren't processed, these
15042 widgets don't behave normally. */
15044 EMACS_TIME interval
;
15045 EMACS_SET_SECS_USECS (interval
, 0, 100000);
15046 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
15050 #ifdef USE_TOOLKIT_SCROLL_BARS
15051 xaw3d_arrow_scroll
= False
;
15052 xaw3d_pick_top
= True
;
15055 /* Note that there is no real way portable across R3/R4 to get the
15056 original error handler. */
15057 XSetErrorHandler (x_error_handler
);
15058 XSetIOErrorHandler (x_io_error_quitter
);
15060 /* Disable Window Change signals; they are handled by X events. */
15062 signal (SIGWINCH
, SIG_DFL
);
15063 #endif /* ! defined (SIGWINCH) */
15065 signal (SIGPIPE
, x_connection_signal
);
15072 staticpro (&x_error_message_string
);
15073 x_error_message_string
= Qnil
;
15075 staticpro (&x_display_name_list
);
15076 x_display_name_list
= Qnil
;
15078 staticpro (&last_mouse_scroll_bar
);
15079 last_mouse_scroll_bar
= Qnil
;
15081 staticpro (&Qvendor_specific_keysyms
);
15082 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
15084 staticpro (&last_mouse_press_frame
);
15085 last_mouse_press_frame
= Qnil
;
15088 staticpro (&help_echo
);
15089 help_echo_object
= Qnil
;
15090 staticpro (&help_echo_object
);
15091 help_echo_window
= Qnil
;
15092 staticpro (&help_echo_window
);
15093 previous_help_echo
= Qnil
;
15094 staticpro (&previous_help_echo
);
15095 help_echo_pos
= -1;
15097 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
15098 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
15099 x_autoselect_window_p
= 0;
15101 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
15102 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
15103 For example, if a block cursor is over a tab, it will be drawn as
15104 wide as that tab on the display. */);
15105 x_stretch_cursor_p
= 0;
15107 DEFVAR_BOOL ("x-use-underline-position-properties",
15108 &x_use_underline_position_properties
,
15109 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15110 nil means ignore them. If you encounter fonts with bogus
15111 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15112 to 4.1, set this to nil. */);
15113 x_use_underline_position_properties
= 1;
15115 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
15116 doc
: /* What X toolkit scroll bars Emacs uses.
15117 A value of nil means Emacs doesn't use X toolkit scroll bars.
15118 Otherwise, value is a symbol describing the X toolkit. */);
15119 #ifdef USE_TOOLKIT_SCROLL_BARS
15121 Vx_toolkit_scroll_bars
= intern ("motif");
15122 #elif defined HAVE_XAW3D
15123 Vx_toolkit_scroll_bars
= intern ("xaw3d");
15125 Vx_toolkit_scroll_bars
= intern ("xaw");
15128 Vx_toolkit_scroll_bars
= Qnil
;
15131 staticpro (&last_mouse_motion_frame
);
15132 last_mouse_motion_frame
= Qnil
;
15134 Qmodifier_value
= intern ("modifier-value");
15135 Qalt
= intern ("alt");
15136 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
15137 Qhyper
= intern ("hyper");
15138 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
15139 Qmeta
= intern ("meta");
15140 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
15141 Qsuper
= intern ("super");
15142 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
15144 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
15145 doc
: /* Which keys Emacs uses for the alt modifier.
15146 This should be one of the symbols `alt', `hyper', `meta', `super'.
15147 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15148 is nil, which is the same as `alt'. */);
15149 Vx_alt_keysym
= Qnil
;
15151 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
15152 doc
: /* Which keys Emacs uses for the hyper modifier.
15153 This should be one of the symbols `alt', `hyper', `meta', `super'.
15154 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15155 default is nil, which is the same as `hyper'. */);
15156 Vx_hyper_keysym
= Qnil
;
15158 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
15159 doc
: /* Which keys Emacs uses for the meta modifier.
15160 This should be one of the symbols `alt', `hyper', `meta', `super'.
15161 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15162 default is nil, which is the same as `meta'. */);
15163 Vx_meta_keysym
= Qnil
;
15165 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
15166 doc
: /* Which keys Emacs uses for the super modifier.
15167 This should be one of the symbols `alt', `hyper', `meta', `super'.
15168 For example, `super' means use the Super_L and Super_R keysyms. The
15169 default is nil, which is the same as `super'. */);
15170 Vx_super_keysym
= Qnil
;
15174 #endif /* HAVE_X_WINDOWS */