1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
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> */
74 #include "dispextern.h"
76 #include "termhooks.h"
84 #include "intervals.h"
90 #include <X11/Shell.h>
93 #ifdef HAVE_SYS_TIME_H
101 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
102 extern void xlwmenu_redisplay
P_ ((Widget
));
107 extern void free_frame_menubar
P_ ((struct frame
*));
108 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
116 /* Include toolkit specific headers for the scroll bar widget. */
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
139 #endif /* USE_X_TOOLKIT */
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
153 #define abs(x) ((x) < 0 ? -(x) : (x))
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
158 /* Fringe bitmaps. */
160 enum fringe_bitmap_type
163 LEFT_TRUNCATION_BITMAP
,
164 RIGHT_TRUNCATION_BITMAP
,
165 OVERLAY_ARROW_BITMAP
,
166 CONTINUED_LINE_BITMAP
,
167 CONTINUATION_LINE_BITMAP
,
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
177 static unsigned char zv_bits
[] = {
178 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
179 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
180 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
181 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
182 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
183 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
187 /* An arrow like this: `<-'. */
190 #define left_height 8
191 static unsigned char left_bits
[] = {
192 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
194 /* Right truncation arrow bitmap `->'. */
196 #define right_width 8
197 #define right_height 8
198 static unsigned char right_bits
[] = {
199 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
201 /* Marker for continued lines. */
203 #define continued_width 8
204 #define continued_height 8
205 static unsigned char continued_bits
[] = {
206 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
208 /* Marker for continuation lines. */
210 #define continuation_width 8
211 #define continuation_height 8
212 static unsigned char continuation_bits
[] = {
213 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
215 /* Overlay arrow bitmap. */
221 static unsigned char ov_bits
[] = {
222 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
224 /* A triangular arrow. */
227 static unsigned char ov_bits
[] = {
228 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
232 extern Lisp_Object Qhelp_echo
;
235 /* Non-nil means Emacs uses toolkit scroll bars. */
237 Lisp_Object Vx_toolkit_scroll_bars
;
239 /* If a string, XTread_socket generates an event to display that string.
240 (The display is done in read_char.) */
242 static Lisp_Object help_echo
;
243 static Lisp_Object help_echo_window
;
244 static Lisp_Object help_echo_object
;
245 static int help_echo_pos
;
247 /* Temporary variable for XTread_socket. */
249 static Lisp_Object previous_help_echo
;
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
254 static int any_help_event_p
;
256 /* Non-zero means autoselect window with the mouse cursor. */
258 int mouse_autoselect_window
;
260 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
261 static Lisp_Object last_window
;
263 /* Non-zero means draw block and hollow cursor as wide as the glyph
264 under it. For example, if a block cursor is over a tab, it will be
265 drawn as wide as that tab on the display. */
267 int x_stretch_cursor_p
;
269 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
271 int x_use_underline_position_properties
;
273 /* This is a chain of structures for all the X displays currently in
276 struct x_display_info
*x_display_list
;
278 /* This is a list of cons cells, each of the form (NAME
279 . FONT-LIST-CACHE), one for each element of x_display_list and in
280 the same order. NAME is the name of the frame. FONT-LIST-CACHE
281 records previous values returned by x-list-fonts. */
283 Lisp_Object x_display_name_list
;
285 /* Frame being updated by update_frame. This is declared in term.c.
286 This is set by update_begin and looked at by all the XT functions.
287 It is zero while not inside an update. In that case, the XT
288 functions assume that `selected_frame' is the frame to apply to. */
290 extern struct frame
*updating_frame
;
292 /* This is a frame waiting to be auto-raised, within XTread_socket. */
294 struct frame
*pending_autoraise_frame
;
297 /* The application context for Xt use. */
298 XtAppContext Xt_app_con
;
299 static String Xt_default_resources
[] = {0};
300 #endif /* USE_X_TOOLKIT */
302 /* Nominal cursor position -- where to draw output.
303 HPOS and VPOS are window relative glyph matrix coordinates.
304 X and Y are window relative pixel coordinates. */
306 struct cursor_pos output_cursor
;
308 /* Non-zero means user is interacting with a toolkit scroll bar. */
310 static int toolkit_scroll_bar_interaction
;
314 Formerly, we used PointerMotionHintMask (in standard_event_mask)
315 so that we would have to call XQueryPointer after each MotionNotify
316 event to ask for another such event. However, this made mouse tracking
317 slow, and there was a bug that made it eventually stop.
319 Simply asking for MotionNotify all the time seems to work better.
321 In order to avoid asking for motion events and then throwing most
322 of them away or busy-polling the server for mouse positions, we ask
323 the server for pointer motion hints. This means that we get only
324 one event per group of mouse movements. "Groups" are delimited by
325 other kinds of events (focus changes and button clicks, for
326 example), or by XQueryPointer calls; when one of these happens, we
327 get another MotionNotify event the next time the mouse moves. This
328 is at least as efficient as getting motion events when mouse
329 tracking is on, and I suspect only negligibly worse when tracking
332 /* Where the mouse was last time we reported a mouse event. */
334 FRAME_PTR last_mouse_frame
;
335 static XRectangle last_mouse_glyph
;
336 static Lisp_Object last_mouse_press_frame
;
338 /* The scroll bar in which the last X motion event occurred.
340 If the last X motion event occurred in a scroll bar, we set this so
341 XTmouse_position can know whether to report a scroll bar motion or
344 If the last X motion event didn't occur in a scroll bar, we set
345 this to Qnil, to tell XTmouse_position to return an ordinary motion
348 static Lisp_Object last_mouse_scroll_bar
;
350 /* This is a hack. We would really prefer that XTmouse_position would
351 return the time associated with the position it returns, but there
352 doesn't seem to be any way to wrest the time-stamp from the server
353 along with the position query. So, we just keep track of the time
354 of the last movement we received, and return that in hopes that
355 it's somewhat accurate. */
357 static Time last_mouse_movement_time
;
359 /* Incremented by XTread_socket whenever it really tries to read
363 static int volatile input_signal_count
;
365 static int input_signal_count
;
368 /* Used locally within XTread_socket. */
370 static int x_noop_count
;
372 /* Initial values of argv and argc. */
374 extern char **initial_argv
;
375 extern int initial_argc
;
377 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
379 /* Tells if a window manager is present or not. */
381 extern Lisp_Object Vx_no_window_manager
;
383 extern Lisp_Object Qface
, Qmouse_face
;
387 /* A mask of extra modifier bits to put into every keyboard char. */
389 extern EMACS_INT extra_keyboard_modifiers
;
391 /* The keysyms to use for the various modifiers. */
393 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
394 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
396 static Lisp_Object Qvendor_specific_keysyms
;
397 static Lisp_Object Qlatin_1
, Qutf_8
;
399 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
400 extern Lisp_Object x_icon_type
P_ ((struct frame
*));
403 /* Enumeration for overriding/changing the face to use for drawing
404 glyphs in x_draw_glyphs. */
406 enum draw_glyphs_face
416 static int cursor_in_mouse_face_p
P_ ((struct window
*));
417 static int clear_mouse_face
P_ ((struct x_display_info
*));
418 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
419 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
420 static const XColor
*x_color_cells
P_ ((Display
*, int *));
421 static void x_update_window_end
P_ ((struct window
*, int, int));
422 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
423 void x_delete_display
P_ ((struct x_display_info
*));
424 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
426 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
427 int *, int *, Lisp_Object
));
428 static int fast_find_string_pos
P_ ((struct window
*, int, Lisp_Object
,
429 int *, int *, int *, int *, int));
430 static void set_output_cursor
P_ ((struct cursor_pos
*));
431 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
432 int *, int *, int *, int));
433 static void note_mode_line_or_margin_highlight
P_ ((struct window
*, int,
435 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
436 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
437 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
438 static void show_mouse_face
P_ ((struct x_display_info
*,
439 enum draw_glyphs_face
));
440 static int x_io_error_quitter
P_ ((Display
*));
441 int x_catch_errors
P_ ((Display
*));
442 void x_uncatch_errors
P_ ((Display
*, int));
443 void x_lower_frame
P_ ((struct frame
*));
444 void x_scroll_bar_clear
P_ ((struct frame
*));
445 int x_had_errors_p
P_ ((Display
*));
446 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
447 void x_raise_frame
P_ ((struct frame
*));
448 void x_set_window_size
P_ ((struct frame
*, int, int, int));
449 void x_wm_set_window_state
P_ ((struct frame
*, int));
450 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
451 void x_initialize
P_ ((void));
452 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
453 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
454 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
456 enum draw_glyphs_face
));
457 static void x_update_end
P_ ((struct frame
*));
458 static void XTframe_up_to_date
P_ ((struct frame
*));
459 static void XTset_terminal_modes
P_ ((void));
460 static void XTreset_terminal_modes
P_ ((void));
461 static void XTcursor_to
P_ ((int, int, int, int));
462 static void x_write_glyphs
P_ ((struct glyph
*, int));
463 static void x_clear_end_of_line
P_ ((int));
464 static void x_clear_frame
P_ ((void));
465 static void x_clear_cursor
P_ ((struct window
*));
466 static void frame_highlight
P_ ((struct frame
*));
467 static void frame_unhighlight
P_ ((struct frame
*));
468 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
469 static int x_focus_changed
P_ ((int,
471 struct x_display_info
*,
473 struct input_event
*,
475 static int x_detect_focus_change
P_ ((struct x_display_info
*,
477 struct input_event
*,
479 static void XTframe_rehighlight
P_ ((struct frame
*));
480 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
481 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
482 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
483 enum text_cursor_kinds
));
484 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
486 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
487 static int expose_window_tree
P_ ((struct window
*, XRectangle
*));
488 static void expose_overlaps
P_ ((struct window
*, struct glyph_row
*,
489 struct glyph_row
*));
490 static int expose_window
P_ ((struct window
*, XRectangle
*));
491 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
492 XRectangle
*, enum glyph_row_area
));
493 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
495 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
496 static void x_update_window_cursor
P_ ((struct window
*, int));
497 static void x_erase_phys_cursor
P_ ((struct window
*));
498 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
499 static void x_draw_fringe_bitmap
P_ ((struct window
*, struct glyph_row
*,
500 enum fringe_bitmap_type
, int left_p
));
502 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
504 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
505 static void x_draw_row_fringe_bitmaps
P_ ((struct window
*, struct glyph_row
*));
506 static void notice_overwritten_cursor
P_ ((struct window
*, enum glyph_row_area
,
507 int, int, int, int));
508 static void x_flush
P_ ((struct frame
*f
));
509 static void x_update_begin
P_ ((struct frame
*));
510 static void x_update_window_begin
P_ ((struct window
*));
511 static void x_draw_vertical_border
P_ ((struct window
*));
512 static void x_after_update_window_line
P_ ((struct glyph_row
*));
513 static INLINE
void take_vertical_position_into_account
P_ ((struct it
*));
514 static void x_produce_stretch_glyph
P_ ((struct it
*));
515 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Window
));
516 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
517 enum scroll_bar_part
*,
518 Lisp_Object
*, Lisp_Object
*,
520 static void x_check_fullscreen
P_ ((struct frame
*));
521 static void x_check_fullscreen_move
P_ ((struct frame
*));
523 /* Flush display of frame F, or of all frames if F is null. */
532 Lisp_Object rest
, frame
;
533 FOR_EACH_FRAME (rest
, frame
)
534 x_flush (XFRAME (frame
));
536 else if (FRAME_X_P (f
))
537 XFlush (FRAME_X_DISPLAY (f
));
542 /* Remove calls to XFlush by defining XFlush to an empty replacement.
543 Calls to XFlush should be unnecessary because the X output buffer
544 is flushed automatically as needed by calls to XPending,
545 XNextEvent, or XWindowEvent according to the XFlush man page.
546 XTread_socket calls XPending. Removing XFlush improves
549 #define XFlush(DISPLAY) (void) 0
552 /***********************************************************************
554 ***********************************************************************/
558 /* This is a function useful for recording debugging information about
559 the sequence of occurrences in this file. */
567 struct record event_record
[100];
569 int event_record_index
;
571 record_event (locus
, type
)
575 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
576 event_record_index
= 0;
578 event_record
[event_record_index
].locus
= locus
;
579 event_record
[event_record_index
].type
= type
;
580 event_record_index
++;
587 /* Return the struct x_display_info corresponding to DPY. */
589 struct x_display_info
*
590 x_display_info_for_display (dpy
)
593 struct x_display_info
*dpyinfo
;
595 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
596 if (dpyinfo
->display
== dpy
)
604 /***********************************************************************
605 Starting and ending an update
606 ***********************************************************************/
608 /* Start an update of frame F. This function is installed as a hook
609 for update_begin, i.e. it is called when update_begin is called.
610 This function is called prior to calls to x_update_window_begin for
611 each window being updated. Currently, there is nothing to do here
612 because all interesting stuff is done on a window basis. */
622 /* Start update of window W. Set the global variable updated_window
623 to the window being updated and set output_cursor to the cursor
627 x_update_window_begin (w
)
630 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
631 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
634 set_output_cursor (&w
->cursor
);
638 if (f
== display_info
->mouse_face_mouse_frame
)
640 /* Don't do highlighting for mouse motion during the update. */
641 display_info
->mouse_face_defer
= 1;
643 /* If F needs to be redrawn, simply forget about any prior mouse
645 if (FRAME_GARBAGED_P (f
))
646 display_info
->mouse_face_window
= Qnil
;
648 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
649 their mouse_face_p flag set, which means that they are always
650 unequal to rows in a desired matrix which never have that
651 flag set. So, rows containing mouse-face glyphs are never
652 scrolled, and we don't have to switch the mouse highlight off
653 here to prevent it from being scrolled. */
655 /* Can we tell that this update does not affect the window
656 where the mouse highlight is? If so, no need to turn off.
657 Likewise, don't do anything if the frame is garbaged;
658 in that case, the frame's current matrix that we would use
659 is all wrong, and we will redisplay that line anyway. */
660 if (!NILP (display_info
->mouse_face_window
)
661 && w
== XWINDOW (display_info
->mouse_face_window
))
665 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
666 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
669 if (i
< w
->desired_matrix
->nrows
)
670 clear_mouse_face (display_info
);
679 /* Draw a vertical window border to the right of window W if W doesn't
680 have vertical scroll bars. */
683 x_draw_vertical_border (w
)
686 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
688 /* Redraw borders between horizontally adjacent windows. Don't
689 do it for frames with vertical scroll bars because either the
690 right scroll bar of a window, or the left scroll bar of its
691 neighbor will suffice as a border. */
692 if (!WINDOW_RIGHTMOST_P (w
)
693 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
697 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
698 x1
+= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
701 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
702 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
707 /* End update of window W (which is equal to updated_window).
709 Draw vertical borders between horizontally adjacent windows, and
710 display W's cursor if CURSOR_ON_P is non-zero.
712 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
713 glyphs in mouse-face were overwritten. In that case we have to
714 make sure that the mouse-highlight is properly redrawn.
716 W may be a menu bar pseudo-window in case we don't have X toolkit
717 support. Such windows don't have a cursor, so don't display it
721 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
723 int cursor_on_p
, mouse_face_overwritten_p
;
725 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
727 if (!w
->pseudo_window_p
)
732 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
734 output_cursor
.x
, output_cursor
.y
);
736 x_draw_vertical_border (w
);
740 /* If a row with mouse-face was overwritten, arrange for
741 XTframe_up_to_date to redisplay the mouse highlight. */
742 if (mouse_face_overwritten_p
)
744 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
745 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
746 dpyinfo
->mouse_face_window
= Qnil
;
749 updated_window
= NULL
;
753 /* End update of frame F. This function is installed as a hook in
760 /* Mouse highlight may be displayed again. */
761 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
764 XFlush (FRAME_X_DISPLAY (f
));
769 /* This function is called from various places in xdisp.c whenever a
770 complete update has been performed. The global variable
771 updated_window is not available here. */
774 XTframe_up_to_date (f
)
779 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
781 if (dpyinfo
->mouse_face_deferred_gc
782 || f
== dpyinfo
->mouse_face_mouse_frame
)
785 if (dpyinfo
->mouse_face_mouse_frame
)
786 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
787 dpyinfo
->mouse_face_mouse_x
,
788 dpyinfo
->mouse_face_mouse_y
);
789 dpyinfo
->mouse_face_deferred_gc
= 0;
796 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
797 arrow bitmaps, or clear the fringes if no bitmaps are required
798 before DESIRED_ROW is made current. The window being updated is
799 found in updated_window. This function It is called from
800 update_window_line only if it is known that there are differences
801 between bitmaps to be drawn between current row and DESIRED_ROW. */
804 x_after_update_window_line (desired_row
)
805 struct glyph_row
*desired_row
;
807 struct window
*w
= updated_window
;
813 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
816 x_draw_row_fringe_bitmaps (w
, desired_row
);
820 /* When a window has disappeared, make sure that no rest of
821 full-width rows stays visible in the internal border. Could
822 check here if updated_window is the leftmost/rightmost window,
823 but I guess it's not worth doing since vertically split windows
824 are almost never used, internal border is rarely set, and the
825 overhead is very small. */
826 if (windows_or_buffers_changed
827 && desired_row
->full_width_p
828 && (f
= XFRAME (w
->frame
),
829 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
831 && (height
= desired_row
->visible_height
,
834 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
836 /* Internal border is drawn below the tool bar. */
837 if (WINDOWP (f
->tool_bar_window
)
838 && w
== XWINDOW (f
->tool_bar_window
))
842 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
843 0, y
, width
, height
, False
);
844 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
845 f
->output_data
.x
->pixel_width
- width
,
846 y
, width
, height
, False
);
852 /* Draw the bitmap WHICH in one of the left or right fringes of
853 window W. ROW is the glyph row for which to display the bitmap; it
854 determines the vertical position at which the bitmap has to be
858 x_draw_fringe_bitmap (w
, row
, which
, left_p
)
860 struct glyph_row
*row
;
861 enum fringe_bitmap_type which
;
864 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
865 Display
*display
= FRAME_X_DISPLAY (f
);
866 Window window
= FRAME_X_WINDOW (f
);
869 unsigned char *bits
= NULL
;
871 GC gc
= f
->output_data
.x
->normal_gc
;
873 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
875 /* Must clip because of partially visible lines. */
876 x_clip_to_row (w
, row
, gc
, 1);
878 /* Convert row to frame coordinates. */
879 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
883 case NO_FRINGE_BITMAP
:
888 case LEFT_TRUNCATION_BITMAP
:
894 case OVERLAY_ARROW_BITMAP
:
900 case RIGHT_TRUNCATION_BITMAP
:
906 case CONTINUED_LINE_BITMAP
:
907 wd
= continued_width
;
908 h
= continued_height
;
909 bits
= continued_bits
;
912 case CONTINUATION_LINE_BITMAP
:
913 wd
= continuation_width
;
914 h
= continuation_height
;
915 bits
= continuation_bits
;
920 h
= zv_height
- (y
% zv_period
);
921 bits
= zv_bits
+ (y
% zv_period
);
928 /* Clip bitmap if too high. */
932 /* Set dy to the offset in the row to start drawing the bitmap. */
933 dy
= (row
->height
- h
) / 2;
935 face
= FACE_FROM_ID (f
, FRINGE_FACE_ID
);
936 PREPARE_FACE_FOR_DISPLAY (f
, face
);
938 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
943 if (wd
> FRAME_X_LEFT_FRINGE_WIDTH (f
))
944 wd
= FRAME_X_LEFT_FRINGE_WIDTH (f
);
945 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
947 - (FRAME_X_LEFT_FRINGE_WIDTH (f
) - wd
) / 2);
948 if (wd
< FRAME_X_LEFT_FRINGE_WIDTH (f
) || row
->height
> h
)
950 /* If W has a vertical border to its left, don't draw over it. */
951 int border
= ((XFASTINT (w
->left
) > 0
952 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
954 b1
= (window_box_left (w
, -1)
955 - FRAME_X_LEFT_FRINGE_WIDTH (f
)
957 b2
= (FRAME_X_LEFT_FRINGE_WIDTH (f
) - border
);
962 if (wd
> FRAME_X_RIGHT_FRINGE_WIDTH (f
))
963 wd
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
964 x
= (window_box_right (w
, -1)
965 + (FRAME_X_RIGHT_FRINGE_WIDTH (f
) - wd
) / 2);
966 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
968 if (wd
< FRAME_X_RIGHT_FRINGE_WIDTH (f
) || row
->height
> h
)
970 b1
= window_box_right (w
, -1);
971 b2
= FRAME_X_RIGHT_FRINGE_WIDTH (f
);
977 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
979 /* In case the same realized face is used for fringes and
980 for something displayed in the text (e.g. face `region' on
981 mono-displays, the fill style may have been changed to
982 FillSolid in x_draw_glyph_string_background. */
984 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
986 XSetForeground (display
, face
->gc
, face
->background
);
988 XFillRectangle (display
, window
, face
->gc
,
990 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
993 row
->visible_height
);
995 XSetForeground (display
, face
->gc
, face
->foreground
);
998 if (which
!= NO_FRINGE_BITMAP
)
1000 /* Draw the bitmap. I believe these small pixmaps can be cached
1002 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
1004 face
->background
, depth
);
1005 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
1006 XFreePixmap (display
, pixmap
);
1009 XSetClipMask (display
, gc
, None
);
1013 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1014 function with input blocked. */
1017 x_draw_row_fringe_bitmaps (w
, row
)
1019 struct glyph_row
*row
;
1021 struct frame
*f
= XFRAME (w
->frame
);
1022 enum fringe_bitmap_type bitmap
;
1024 xassert (interrupt_input_blocked
);
1026 /* If row is completely invisible, because of vscrolling, we
1027 don't have to draw anything. */
1028 if (row
->visible_height
<= 0)
1031 if (FRAME_X_LEFT_FRINGE_WIDTH (f
) != 0)
1033 /* Decide which bitmap to draw in the left fringe. */
1034 if (row
->overlay_arrow_p
)
1035 bitmap
= OVERLAY_ARROW_BITMAP
;
1036 else if (row
->truncated_on_left_p
)
1037 bitmap
= LEFT_TRUNCATION_BITMAP
;
1038 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
1039 bitmap
= CONTINUATION_LINE_BITMAP
;
1040 else if (row
->indicate_empty_line_p
)
1041 bitmap
= ZV_LINE_BITMAP
;
1043 bitmap
= NO_FRINGE_BITMAP
;
1045 x_draw_fringe_bitmap (w
, row
, bitmap
, 1);
1048 if (FRAME_X_RIGHT_FRINGE_WIDTH (f
) != 0)
1050 /* Decide which bitmap to draw in the right fringe. */
1051 if (row
->truncated_on_right_p
)
1052 bitmap
= RIGHT_TRUNCATION_BITMAP
;
1053 else if (row
->continued_p
)
1054 bitmap
= CONTINUED_LINE_BITMAP
;
1055 else if (row
->indicate_empty_line_p
&& FRAME_X_LEFT_FRINGE_WIDTH (f
) == 0)
1056 bitmap
= ZV_LINE_BITMAP
;
1058 bitmap
= NO_FRINGE_BITMAP
;
1060 x_draw_fringe_bitmap (w
, row
, bitmap
, 0);
1066 /* This is called when starting Emacs and when restarting after
1067 suspend. When starting Emacs, no X window is mapped. And nothing
1068 must be done to Emacs's own window if it is suspended (though that
1072 XTset_terminal_modes ()
1076 /* This is called when exiting or suspending Emacs. Exiting will make
1077 the X-windows go away, and suspending requires no action. */
1080 XTreset_terminal_modes ()
1086 /***********************************************************************
1088 ***********************************************************************/
1090 /* Set the global variable output_cursor to CURSOR. All cursor
1091 positions are relative to updated_window. */
1094 set_output_cursor (cursor
)
1095 struct cursor_pos
*cursor
;
1097 output_cursor
.hpos
= cursor
->hpos
;
1098 output_cursor
.vpos
= cursor
->vpos
;
1099 output_cursor
.x
= cursor
->x
;
1100 output_cursor
.y
= cursor
->y
;
1104 /* Set a nominal cursor position.
1106 HPOS and VPOS are column/row positions in a window glyph matrix. X
1107 and Y are window text area relative pixel positions.
1109 If this is done during an update, updated_window will contain the
1110 window that is being updated and the position is the future output
1111 cursor position for that window. If updated_window is null, use
1112 selected_window and display the cursor at the given position. */
1115 XTcursor_to (vpos
, hpos
, y
, x
)
1116 int vpos
, hpos
, y
, x
;
1120 /* If updated_window is not set, work on selected_window. */
1124 w
= XWINDOW (selected_window
);
1126 /* Set the output cursor. */
1127 output_cursor
.hpos
= hpos
;
1128 output_cursor
.vpos
= vpos
;
1129 output_cursor
.x
= x
;
1130 output_cursor
.y
= y
;
1132 /* If not called as part of an update, really display the cursor.
1133 This will also set the cursor position of W. */
1134 if (updated_window
== NULL
)
1137 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1138 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1145 /***********************************************************************
1147 ***********************************************************************/
1149 /* Function prototypes of this page. */
1151 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1155 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1156 int, XChar2b
*, int,
1158 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1159 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1160 static void x_append_glyph
P_ ((struct it
*));
1161 static void x_append_composite_glyph
P_ ((struct it
*));
1162 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1164 static void x_produce_glyphs
P_ ((struct it
*));
1165 static void x_produce_image_glyph
P_ ((struct it
*it
));
1168 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1169 is not contained in the font. */
1171 static INLINE XCharStruct
*
1172 x_per_char_metric (font
, char2b
)
1176 /* The result metric information. */
1177 XCharStruct
*pcm
= NULL
;
1179 xassert (font
&& char2b
);
1181 if (font
->per_char
!= NULL
)
1183 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1185 /* min_char_or_byte2 specifies the linear character index
1186 corresponding to the first element of the per_char array,
1187 max_char_or_byte2 is the index of the last character. A
1188 character with non-zero CHAR2B->byte1 is not in the font.
1189 A character with byte2 less than min_char_or_byte2 or
1190 greater max_char_or_byte2 is not in the font. */
1191 if (char2b
->byte1
== 0
1192 && char2b
->byte2
>= font
->min_char_or_byte2
1193 && char2b
->byte2
<= font
->max_char_or_byte2
)
1194 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1198 /* If either min_byte1 or max_byte1 are nonzero, both
1199 min_char_or_byte2 and max_char_or_byte2 are less than
1200 256, and the 2-byte character index values corresponding
1201 to the per_char array element N (counting from 0) are:
1203 byte1 = N/D + min_byte1
1204 byte2 = N\D + min_char_or_byte2
1208 D = max_char_or_byte2 - min_char_or_byte2 + 1
1209 / = integer division
1210 \ = integer modulus */
1211 if (char2b
->byte1
>= font
->min_byte1
1212 && char2b
->byte1
<= font
->max_byte1
1213 && char2b
->byte2
>= font
->min_char_or_byte2
1214 && char2b
->byte2
<= font
->max_char_or_byte2
)
1216 pcm
= (font
->per_char
1217 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1218 * (char2b
->byte1
- font
->min_byte1
))
1219 + (char2b
->byte2
- font
->min_char_or_byte2
));
1225 /* If the per_char pointer is null, all glyphs between the first
1226 and last character indexes inclusive have the same
1227 information, as given by both min_bounds and max_bounds. */
1228 if (char2b
->byte2
>= font
->min_char_or_byte2
1229 && char2b
->byte2
<= font
->max_char_or_byte2
)
1230 pcm
= &font
->max_bounds
;
1233 return ((pcm
== NULL
1234 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1239 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1240 the two-byte form of C. Encoding is returned in *CHAR2B. */
1243 x_encode_char (c
, char2b
, font_info
)
1246 struct font_info
*font_info
;
1248 int charset
= CHAR_CHARSET (c
);
1249 XFontStruct
*font
= font_info
->font
;
1251 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1252 This may be either a program in a special encoder language or a
1254 if (font_info
->font_encoder
)
1256 /* It's a program. */
1257 struct ccl_program
*ccl
= font_info
->font_encoder
;
1259 if (CHARSET_DIMENSION (charset
) == 1)
1261 ccl
->reg
[0] = charset
;
1262 ccl
->reg
[1] = char2b
->byte2
;
1267 ccl
->reg
[0] = charset
;
1268 ccl
->reg
[1] = char2b
->byte1
;
1269 ccl
->reg
[2] = char2b
->byte2
;
1272 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1274 /* We assume that MSBs are appropriately set/reset by CCL
1276 if (font
->max_byte1
== 0) /* 1-byte font */
1277 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1279 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1281 else if (font_info
->encoding
[charset
])
1283 /* Fixed encoding scheme. See fontset.h for the meaning of the
1284 encoding numbers. */
1285 int enc
= font_info
->encoding
[charset
];
1287 if ((enc
== 1 || enc
== 2)
1288 && CHARSET_DIMENSION (charset
) == 2)
1289 char2b
->byte1
|= 0x80;
1291 if (enc
== 1 || enc
== 3)
1292 char2b
->byte2
|= 0x80;
1297 /* Get face and two-byte form of character C in face FACE_ID on frame
1298 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1299 means we want to display multibyte text. DISPLAY_P non-zero means
1300 make sure that X resources for the face returned are allocated.
1301 Value is a pointer to a realized face that is ready for display if
1302 DISPLAY_P is non-zero. */
1304 static INLINE
struct face
*
1305 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
, display_p
)
1309 int multibyte_p
, display_p
;
1311 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1315 /* Unibyte case. We don't have to encode, but we have to make
1316 sure to use a face suitable for unibyte. */
1319 face_id
= FACE_FOR_CHAR (f
, face
, c
);
1320 face
= FACE_FROM_ID (f
, face_id
);
1322 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1324 /* Case of ASCII in a face known to fit ASCII. */
1330 int c1
, c2
, charset
;
1332 /* Split characters into bytes. If c2 is -1 afterwards, C is
1333 really a one-byte character so that byte1 is zero. */
1334 SPLIT_CHAR (c
, charset
, c1
, c2
);
1336 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1338 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1340 /* Maybe encode the character in *CHAR2B. */
1341 if (face
->font
!= NULL
)
1343 struct font_info
*font_info
1344 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1346 x_encode_char (c
, char2b
, font_info
);
1350 /* Make sure X resources of the face are allocated. */
1353 xassert (face
!= NULL
);
1354 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1361 /* Get face and two-byte form of character glyph GLYPH on frame F.
1362 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1363 a pointer to a realized face that is ready for display. */
1365 static INLINE
struct face
*
1366 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
1368 struct glyph
*glyph
;
1374 xassert (glyph
->type
== CHAR_GLYPH
);
1375 face
= FACE_FROM_ID (f
, glyph
->face_id
);
1380 if (!glyph
->multibyte_p
)
1382 /* Unibyte case. We don't have to encode, but we have to make
1383 sure to use a face suitable for unibyte. */
1385 char2b
->byte2
= glyph
->u
.ch
;
1387 else if (glyph
->u
.ch
< 128
1388 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
1390 /* Case of ASCII in a face known to fit ASCII. */
1392 char2b
->byte2
= glyph
->u
.ch
;
1396 int c1
, c2
, charset
;
1398 /* Split characters into bytes. If c2 is -1 afterwards, C is
1399 really a one-byte character so that byte1 is zero. */
1400 SPLIT_CHAR (glyph
->u
.ch
, charset
, c1
, c2
);
1402 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1404 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1406 /* Maybe encode the character in *CHAR2B. */
1407 if (charset
!= CHARSET_ASCII
)
1409 struct font_info
*font_info
1410 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1413 x_encode_char (glyph
->u
.ch
, char2b
, font_info
);
1416 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1421 /* Make sure X resources of the face are allocated. */
1422 xassert (face
!= NULL
);
1423 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1428 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1429 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1435 struct glyph
*glyph
;
1436 enum glyph_row_area area
= it
->area
;
1438 xassert (it
->glyph_row
);
1439 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1441 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1442 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1444 glyph
->charpos
= CHARPOS (it
->position
);
1445 glyph
->object
= it
->object
;
1446 glyph
->pixel_width
= it
->pixel_width
;
1447 glyph
->voffset
= it
->voffset
;
1448 glyph
->type
= CHAR_GLYPH
;
1449 glyph
->multibyte_p
= it
->multibyte_p
;
1450 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1451 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1452 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1453 || it
->phys_descent
> it
->descent
);
1454 glyph
->padding_p
= 0;
1455 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
1456 glyph
->face_id
= it
->face_id
;
1457 glyph
->u
.ch
= it
->char_to_display
;
1458 ++it
->glyph_row
->used
[area
];
1462 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1463 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1466 x_append_composite_glyph (it
)
1469 struct glyph
*glyph
;
1470 enum glyph_row_area area
= it
->area
;
1472 xassert (it
->glyph_row
);
1474 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1475 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1477 glyph
->charpos
= CHARPOS (it
->position
);
1478 glyph
->object
= it
->object
;
1479 glyph
->pixel_width
= it
->pixel_width
;
1480 glyph
->voffset
= it
->voffset
;
1481 glyph
->type
= COMPOSITE_GLYPH
;
1482 glyph
->multibyte_p
= it
->multibyte_p
;
1483 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1484 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1485 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1486 || it
->phys_descent
> it
->descent
);
1487 glyph
->padding_p
= 0;
1488 glyph
->glyph_not_available_p
= 0;
1489 glyph
->face_id
= it
->face_id
;
1490 glyph
->u
.cmp_id
= it
->cmp_id
;
1491 ++it
->glyph_row
->used
[area
];
1496 /* Change IT->ascent and IT->height according to the setting of
1500 take_vertical_position_into_account (it
)
1505 if (it
->voffset
< 0)
1506 /* Increase the ascent so that we can display the text higher
1508 it
->ascent
+= abs (it
->voffset
);
1510 /* Increase the descent so that we can display the text lower
1512 it
->descent
+= it
->voffset
;
1517 /* Produce glyphs/get display metrics for the image IT is loaded with.
1518 See the description of struct display_iterator in dispextern.h for
1519 an overview of struct display_iterator. */
1522 x_produce_image_glyph (it
)
1528 xassert (it
->what
== IT_IMAGE
);
1530 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1531 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1534 /* Make sure X resources of the face and image are loaded. */
1535 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1536 prepare_image_for_display (it
->f
, img
);
1538 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
1539 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->vmargin
- it
->ascent
;
1540 it
->pixel_width
= img
->width
+ 2 * img
->hmargin
;
1544 if (face
->box
!= FACE_NO_BOX
)
1546 if (face
->box_line_width
> 0)
1548 it
->ascent
+= face
->box_line_width
;
1549 it
->descent
+= face
->box_line_width
;
1552 if (it
->start_of_box_run_p
)
1553 it
->pixel_width
+= abs (face
->box_line_width
);
1554 if (it
->end_of_box_run_p
)
1555 it
->pixel_width
+= abs (face
->box_line_width
);
1558 take_vertical_position_into_account (it
);
1562 struct glyph
*glyph
;
1563 enum glyph_row_area area
= it
->area
;
1565 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1566 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1568 glyph
->charpos
= CHARPOS (it
->position
);
1569 glyph
->object
= it
->object
;
1570 glyph
->pixel_width
= it
->pixel_width
;
1571 glyph
->voffset
= it
->voffset
;
1572 glyph
->type
= IMAGE_GLYPH
;
1573 glyph
->multibyte_p
= it
->multibyte_p
;
1574 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1575 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1576 glyph
->overlaps_vertically_p
= 0;
1577 glyph
->padding_p
= 0;
1578 glyph
->glyph_not_available_p
= 0;
1579 glyph
->face_id
= it
->face_id
;
1580 glyph
->u
.img_id
= img
->id
;
1581 ++it
->glyph_row
->used
[area
];
1587 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1588 of the glyph, WIDTH and HEIGHT are the width and height of the
1589 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1590 ascent of the glyph (0 <= ASCENT <= 1). */
1593 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1599 struct glyph
*glyph
;
1600 enum glyph_row_area area
= it
->area
;
1602 xassert (ascent
>= 0 && ascent
<= 1);
1604 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1605 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1607 glyph
->charpos
= CHARPOS (it
->position
);
1608 glyph
->object
= object
;
1609 glyph
->pixel_width
= width
;
1610 glyph
->voffset
= it
->voffset
;
1611 glyph
->type
= STRETCH_GLYPH
;
1612 glyph
->multibyte_p
= it
->multibyte_p
;
1613 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1614 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1615 glyph
->overlaps_vertically_p
= 0;
1616 glyph
->padding_p
= 0;
1617 glyph
->glyph_not_available_p
= 0;
1618 glyph
->face_id
= it
->face_id
;
1619 glyph
->u
.stretch
.ascent
= height
* ascent
;
1620 glyph
->u
.stretch
.height
= height
;
1621 ++it
->glyph_row
->used
[area
];
1626 /* Produce a stretch glyph for iterator IT. IT->object is the value
1627 of the glyph property displayed. The value must be a list
1628 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1631 1. `:width WIDTH' specifies that the space should be WIDTH *
1632 canonical char width wide. WIDTH may be an integer or floating
1635 2. `:relative-width FACTOR' specifies that the width of the stretch
1636 should be computed from the width of the first character having the
1637 `glyph' property, and should be FACTOR times that width.
1639 3. `:align-to HPOS' specifies that the space should be wide enough
1640 to reach HPOS, a value in canonical character units.
1642 Exactly one of the above pairs must be present.
1644 4. `:height HEIGHT' specifies that the height of the stretch produced
1645 should be HEIGHT, measured in canonical character units.
1647 5. `:relative-height FACTOR' specifies that the height of the
1648 stretch should be FACTOR times the height of the characters having
1651 Either none or exactly one of 4 or 5 must be present.
1653 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1654 of the stretch should be used for the ascent of the stretch.
1655 ASCENT must be in the range 0 <= ASCENT <= 100. */
1658 ((INTEGERP (X) || FLOATP (X)) \
1664 x_produce_stretch_glyph (it
)
1667 /* (space :width WIDTH :height HEIGHT. */
1669 extern Lisp_Object Qspace
;
1671 extern Lisp_Object QCwidth
, QCheight
, QCascent
;
1672 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1673 extern Lisp_Object QCalign_to
;
1674 Lisp_Object prop
, plist
;
1675 double width
= 0, height
= 0, ascent
= 0;
1676 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1677 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1679 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1681 /* List should start with `space'. */
1682 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1683 plist
= XCDR (it
->object
);
1685 /* Compute the width of the stretch. */
1686 if (prop
= Fplist_get (plist
, QCwidth
),
1688 /* Absolute width `:width WIDTH' specified and valid. */
1689 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1690 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1693 /* Relative width `:relative-width FACTOR' specified and valid.
1694 Compute the width of the characters having the `glyph'
1697 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1700 if (it
->multibyte_p
)
1702 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1703 - IT_BYTEPOS (*it
));
1704 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1707 it2
.c
= *p
, it2
.len
= 1;
1709 it2
.glyph_row
= NULL
;
1710 it2
.what
= IT_CHARACTER
;
1711 x_produce_glyphs (&it2
);
1712 width
= NUMVAL (prop
) * it2
.pixel_width
;
1714 else if (prop
= Fplist_get (plist
, QCalign_to
),
1716 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1718 /* Nothing specified -> width defaults to canonical char width. */
1719 width
= CANON_X_UNIT (it
->f
);
1721 /* Compute height. */
1722 if (prop
= Fplist_get (plist
, QCheight
),
1724 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1725 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1727 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1729 height
= FONT_HEIGHT (font
);
1731 /* Compute percentage of height used for ascent. If
1732 `:ascent ASCENT' is present and valid, use that. Otherwise,
1733 derive the ascent from the font in use. */
1734 if (prop
= Fplist_get (plist
, QCascent
),
1735 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1736 ascent
= NUMVAL (prop
) / 100.0;
1738 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1747 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1748 if (!STRINGP (object
))
1749 object
= it
->w
->buffer
;
1750 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1753 it
->pixel_width
= width
;
1754 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1755 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1758 if (face
->box
!= FACE_NO_BOX
)
1760 if (face
->box_line_width
> 0)
1762 it
->ascent
+= face
->box_line_width
;
1763 it
->descent
+= face
->box_line_width
;
1766 if (it
->start_of_box_run_p
)
1767 it
->pixel_width
+= abs (face
->box_line_width
);
1768 if (it
->end_of_box_run_p
)
1769 it
->pixel_width
+= abs (face
->box_line_width
);
1772 take_vertical_position_into_account (it
);
1775 /* Return proper value to be used as baseline offset of font that has
1776 ASCENT and DESCENT to draw characters by the font at the vertical
1777 center of the line of frame F.
1779 Here, out task is to find the value of BOFF in the following figure;
1781 -------------------------+-----------+-
1782 -+-+---------+-+ | |
1784 | | | | F_ASCENT F_HEIGHT
1787 | | |-|-+------+-----------|------- baseline
1789 | |---------|-+-+ | |
1791 -+-+---------+-+ F_DESCENT |
1792 -------------------------+-----------+-
1794 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1795 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1796 DESCENT = FONT->descent
1797 HEIGHT = FONT_HEIGHT (FONT)
1798 F_DESCENT = (F->output_data.x->font->descent
1799 - F->output_data.x->baseline_offset)
1800 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1803 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1805 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1806 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1807 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1809 /* Produce glyphs/get display metrics for the display element IT is
1810 loaded with. See the description of struct display_iterator in
1811 dispextern.h for an overview of struct display_iterator. */
1814 x_produce_glyphs (it
)
1817 it
->glyph_not_available_p
= 0;
1819 if (it
->what
== IT_CHARACTER
)
1823 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1825 int font_not_found_p
;
1826 struct font_info
*font_info
;
1827 int boff
; /* baseline offset */
1828 /* We may change it->multibyte_p upon unibyte<->multibyte
1829 conversion. So, save the current value now and restore it
1832 Note: It seems that we don't have to record multibyte_p in
1833 struct glyph because the character code itself tells if or
1834 not the character is multibyte. Thus, in the future, we must
1835 consider eliminating the field `multibyte_p' in the struct
1837 int saved_multibyte_p
= it
->multibyte_p
;
1839 /* Maybe translate single-byte characters to multibyte, or the
1841 it
->char_to_display
= it
->c
;
1842 if (!ASCII_BYTE_P (it
->c
))
1844 if (unibyte_display_via_language_environment
1845 && SINGLE_BYTE_CHAR_P (it
->c
)
1847 || !NILP (Vnonascii_translation_table
)))
1849 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1850 it
->multibyte_p
= 1;
1851 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1852 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1854 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
1855 && !it
->multibyte_p
)
1857 it
->multibyte_p
= 1;
1858 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1859 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1863 /* Get font to use. Encode IT->char_to_display. */
1864 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1865 it
->face_id
, &char2b
,
1866 it
->multibyte_p
, 0);
1869 /* When no suitable font found, use the default font. */
1870 font_not_found_p
= font
== NULL
;
1871 if (font_not_found_p
)
1873 font
= FRAME_FONT (it
->f
);
1874 boff
= it
->f
->output_data
.x
->baseline_offset
;
1879 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1880 boff
= font_info
->baseline_offset
;
1881 if (font_info
->vertical_centering
)
1882 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1885 if (it
->char_to_display
>= ' '
1886 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1888 /* Either unibyte or ASCII. */
1893 pcm
= x_per_char_metric (font
, &char2b
);
1894 it
->ascent
= font
->ascent
+ boff
;
1895 it
->descent
= font
->descent
- boff
;
1899 it
->phys_ascent
= pcm
->ascent
+ boff
;
1900 it
->phys_descent
= pcm
->descent
- boff
;
1901 it
->pixel_width
= pcm
->width
;
1905 it
->glyph_not_available_p
= 1;
1906 it
->phys_ascent
= font
->ascent
+ boff
;
1907 it
->phys_descent
= font
->descent
- boff
;
1908 it
->pixel_width
= FONT_WIDTH (font
);
1911 /* If this is a space inside a region of text with
1912 `space-width' property, change its width. */
1913 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1915 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1917 /* If face has a box, add the box thickness to the character
1918 height. If character has a box line to the left and/or
1919 right, add the box line width to the character's width. */
1920 if (face
->box
!= FACE_NO_BOX
)
1922 int thick
= face
->box_line_width
;
1926 it
->ascent
+= thick
;
1927 it
->descent
+= thick
;
1932 if (it
->start_of_box_run_p
)
1933 it
->pixel_width
+= thick
;
1934 if (it
->end_of_box_run_p
)
1935 it
->pixel_width
+= thick
;
1938 /* If face has an overline, add the height of the overline
1939 (1 pixel) and a 1 pixel margin to the character height. */
1940 if (face
->overline_p
)
1943 take_vertical_position_into_account (it
);
1945 /* If we have to actually produce glyphs, do it. */
1950 /* Translate a space with a `space-width' property
1951 into a stretch glyph. */
1952 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1953 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1954 it
->ascent
+ it
->descent
, ascent
);
1957 x_append_glyph (it
);
1959 /* If characters with lbearing or rbearing are displayed
1960 in this line, record that fact in a flag of the
1961 glyph row. This is used to optimize X output code. */
1962 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
1963 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1966 else if (it
->char_to_display
== '\n')
1968 /* A newline has no width but we need the height of the line. */
1969 it
->pixel_width
= 0;
1971 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1972 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1974 if (face
->box
!= FACE_NO_BOX
1975 && face
->box_line_width
> 0)
1977 it
->ascent
+= face
->box_line_width
;
1978 it
->descent
+= face
->box_line_width
;
1981 else if (it
->char_to_display
== '\t')
1983 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1984 int x
= it
->current_x
+ it
->continuation_lines_width
;
1985 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1987 /* If the distance from the current position to the next tab
1988 stop is less than a canonical character width, use the
1989 tab stop after that. */
1990 if (next_tab_x
- x
< CANON_X_UNIT (it
->f
))
1991 next_tab_x
+= tab_width
;
1993 it
->pixel_width
= next_tab_x
- x
;
1995 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1996 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
2000 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
2001 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
2002 it
->ascent
+ it
->descent
, ascent
);
2007 /* A multi-byte character. Assume that the display width of the
2008 character is the width of the character multiplied by the
2009 width of the font. */
2011 /* If we found a font, this font should give us the right
2012 metrics. If we didn't find a font, use the frame's
2013 default font and calculate the width of the character
2014 from the charset width; this is what old redisplay code
2016 pcm
= x_per_char_metric (font
, &char2b
);
2017 if (font_not_found_p
|| !pcm
)
2019 int charset
= CHAR_CHARSET (it
->char_to_display
);
2021 it
->glyph_not_available_p
= 1;
2022 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
2023 * CHARSET_WIDTH (charset
));
2024 it
->phys_ascent
= font
->ascent
+ boff
;
2025 it
->phys_descent
= font
->descent
- boff
;
2029 it
->pixel_width
= pcm
->width
;
2030 it
->phys_ascent
= pcm
->ascent
+ boff
;
2031 it
->phys_descent
= pcm
->descent
- boff
;
2033 && (pcm
->lbearing
< 0
2034 || pcm
->rbearing
> pcm
->width
))
2035 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2038 it
->ascent
= font
->ascent
+ boff
;
2039 it
->descent
= font
->descent
- boff
;
2040 if (face
->box
!= FACE_NO_BOX
)
2042 int thick
= face
->box_line_width
;
2046 it
->ascent
+= thick
;
2047 it
->descent
+= thick
;
2052 if (it
->start_of_box_run_p
)
2053 it
->pixel_width
+= thick
;
2054 if (it
->end_of_box_run_p
)
2055 it
->pixel_width
+= thick
;
2058 /* If face has an overline, add the height of the overline
2059 (1 pixel) and a 1 pixel margin to the character height. */
2060 if (face
->overline_p
)
2063 take_vertical_position_into_account (it
);
2066 x_append_glyph (it
);
2068 it
->multibyte_p
= saved_multibyte_p
;
2070 else if (it
->what
== IT_COMPOSITION
)
2072 /* Note: A composition is represented as one glyph in the
2073 glyph matrix. There are no padding glyphs. */
2076 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2078 int font_not_found_p
;
2079 struct font_info
*font_info
;
2080 int boff
; /* baseline offset */
2081 struct composition
*cmp
= composition_table
[it
->cmp_id
];
2083 /* Maybe translate single-byte characters to multibyte. */
2084 it
->char_to_display
= it
->c
;
2085 if (unibyte_display_via_language_environment
2086 && SINGLE_BYTE_CHAR_P (it
->c
)
2089 && !NILP (Vnonascii_translation_table
))))
2091 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2094 /* Get face and font to use. Encode IT->char_to_display. */
2095 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2096 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2097 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2098 it
->face_id
, &char2b
, it
->multibyte_p
, 0);
2101 /* When no suitable font found, use the default font. */
2102 font_not_found_p
= font
== NULL
;
2103 if (font_not_found_p
)
2105 font
= FRAME_FONT (it
->f
);
2106 boff
= it
->f
->output_data
.x
->baseline_offset
;
2111 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2112 boff
= font_info
->baseline_offset
;
2113 if (font_info
->vertical_centering
)
2114 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2117 /* There are no padding glyphs, so there is only one glyph to
2118 produce for the composition. Important is that pixel_width,
2119 ascent and descent are the values of what is drawn by
2120 draw_glyphs (i.e. the values of the overall glyphs composed). */
2123 /* If we have not yet calculated pixel size data of glyphs of
2124 the composition for the current face font, calculate them
2125 now. Theoretically, we have to check all fonts for the
2126 glyphs, but that requires much time and memory space. So,
2127 here we check only the font of the first glyph. This leads
2128 to incorrect display very rarely, and C-l (recenter) can
2129 correct the display anyway. */
2130 if (cmp
->font
!= (void *) font
)
2132 /* Ascent and descent of the font of the first character of
2133 this composition (adjusted by baseline offset). Ascent
2134 and descent of overall glyphs should not be less than
2135 them respectively. */
2136 int font_ascent
= font
->ascent
+ boff
;
2137 int font_descent
= font
->descent
- boff
;
2138 /* Bounding box of the overall glyphs. */
2139 int leftmost
, rightmost
, lowest
, highest
;
2140 int i
, width
, ascent
, descent
;
2142 cmp
->font
= (void *) font
;
2144 /* Initialize the bounding box. */
2146 && (pcm
= x_per_char_metric (font
, &char2b
)))
2149 ascent
= pcm
->ascent
;
2150 descent
= pcm
->descent
;
2154 width
= FONT_WIDTH (font
);
2155 ascent
= font
->ascent
;
2156 descent
= font
->descent
;
2160 lowest
= - descent
+ boff
;
2161 highest
= ascent
+ boff
;
2165 && font_info
->default_ascent
2166 && CHAR_TABLE_P (Vuse_default_ascent
)
2167 && !NILP (Faref (Vuse_default_ascent
,
2168 make_number (it
->char_to_display
))))
2169 highest
= font_info
->default_ascent
+ boff
;
2171 /* Draw the first glyph at the normal position. It may be
2172 shifted to right later if some other glyphs are drawn at
2174 cmp
->offsets
[0] = 0;
2175 cmp
->offsets
[1] = boff
;
2177 /* Set cmp->offsets for the remaining glyphs. */
2178 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2180 int left
, right
, btm
, top
;
2181 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2182 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2184 face
= FACE_FROM_ID (it
->f
, face_id
);
2185 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2186 it
->multibyte_p
, 0);
2190 font
= FRAME_FONT (it
->f
);
2191 boff
= it
->f
->output_data
.x
->baseline_offset
;
2197 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2198 boff
= font_info
->baseline_offset
;
2199 if (font_info
->vertical_centering
)
2200 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2204 && (pcm
= x_per_char_metric (font
, &char2b
)))
2207 ascent
= pcm
->ascent
;
2208 descent
= pcm
->descent
;
2212 width
= FONT_WIDTH (font
);
2217 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2219 /* Relative composition with or without
2221 left
= (leftmost
+ rightmost
- width
) / 2;
2222 btm
= - descent
+ boff
;
2223 if (font_info
&& font_info
->relative_compose
2224 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2225 || NILP (Faref (Vignore_relative_composition
,
2226 make_number (ch
)))))
2229 if (- descent
>= font_info
->relative_compose
)
2230 /* One extra pixel between two glyphs. */
2232 else if (ascent
<= 0)
2233 /* One extra pixel between two glyphs. */
2234 btm
= lowest
- 1 - ascent
- descent
;
2239 /* A composition rule is specified by an integer
2240 value that encodes global and new reference
2241 points (GREF and NREF). GREF and NREF are
2242 specified by numbers as below:
2250 ---3---4---5--- baseline
2252 6---7---8 -- descent
2254 int rule
= COMPOSITION_RULE (cmp
, i
);
2255 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2257 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2258 grefx
= gref
% 3, nrefx
= nref
% 3;
2259 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2262 + grefx
* (rightmost
- leftmost
) / 2
2263 - nrefx
* width
/ 2);
2264 btm
= ((grefy
== 0 ? highest
2266 : grefy
== 2 ? lowest
2267 : (highest
+ lowest
) / 2)
2268 - (nrefy
== 0 ? ascent
+ descent
2269 : nrefy
== 1 ? descent
- boff
2271 : (ascent
+ descent
) / 2));
2274 cmp
->offsets
[i
* 2] = left
;
2275 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2277 /* Update the bounding box of the overall glyphs. */
2278 right
= left
+ width
;
2279 top
= btm
+ descent
+ ascent
;
2280 if (left
< leftmost
)
2282 if (right
> rightmost
)
2290 /* If there are glyphs whose x-offsets are negative,
2291 shift all glyphs to the right and make all x-offsets
2295 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2296 cmp
->offsets
[i
* 2] -= leftmost
;
2297 rightmost
-= leftmost
;
2300 cmp
->pixel_width
= rightmost
;
2301 cmp
->ascent
= highest
;
2302 cmp
->descent
= - lowest
;
2303 if (cmp
->ascent
< font_ascent
)
2304 cmp
->ascent
= font_ascent
;
2305 if (cmp
->descent
< font_descent
)
2306 cmp
->descent
= font_descent
;
2309 it
->pixel_width
= cmp
->pixel_width
;
2310 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2311 it
->descent
= it
->phys_descent
= cmp
->descent
;
2313 if (face
->box
!= FACE_NO_BOX
)
2315 int thick
= face
->box_line_width
;
2319 it
->ascent
+= thick
;
2320 it
->descent
+= thick
;
2325 if (it
->start_of_box_run_p
)
2326 it
->pixel_width
+= thick
;
2327 if (it
->end_of_box_run_p
)
2328 it
->pixel_width
+= thick
;
2331 /* If face has an overline, add the height of the overline
2332 (1 pixel) and a 1 pixel margin to the character height. */
2333 if (face
->overline_p
)
2336 take_vertical_position_into_account (it
);
2339 x_append_composite_glyph (it
);
2341 else if (it
->what
== IT_IMAGE
)
2342 x_produce_image_glyph (it
);
2343 else if (it
->what
== IT_STRETCH
)
2344 x_produce_stretch_glyph (it
);
2346 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2347 because this isn't true for images with `:ascent 100'. */
2348 xassert (it
->ascent
>= 0 && it
->descent
>= 0);
2349 if (it
->area
== TEXT_AREA
)
2350 it
->current_x
+= it
->pixel_width
;
2352 it
->descent
+= it
->extra_line_spacing
;
2354 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2355 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2356 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2357 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2361 /* Estimate the pixel height of the mode or top line on frame F.
2362 FACE_ID specifies what line's height to estimate. */
2365 x_estimate_mode_line_height (f
, face_id
)
2367 enum face_id face_id
;
2369 int height
= FONT_HEIGHT (FRAME_FONT (f
));
2371 /* This function is called so early when Emacs starts that the face
2372 cache and mode line face are not yet initialized. */
2373 if (FRAME_FACE_CACHE (f
))
2375 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2379 height
= FONT_HEIGHT (face
->font
);
2380 if (face
->box_line_width
> 0)
2381 height
+= 2 * face
->box_line_width
;
2389 /***********************************************************************
2391 ***********************************************************************/
2393 /* A sequence of glyphs to be drawn in the same face.
2395 This data structure is not really completely X specific, so it
2396 could possibly, at least partially, be useful for other systems. It
2397 is currently not part of the external redisplay interface because
2398 it's not clear what other systems will need. */
2402 /* X-origin of the string. */
2405 /* Y-origin and y-position of the base line of this string. */
2408 /* The width of the string, not including a face extension. */
2411 /* The width of the string, including a face extension. */
2412 int background_width
;
2414 /* The height of this string. This is the height of the line this
2415 string is drawn in, and can be different from the height of the
2416 font the string is drawn in. */
2419 /* Number of pixels this string overwrites in front of its x-origin.
2420 This number is zero if the string has an lbearing >= 0; it is
2421 -lbearing, if the string has an lbearing < 0. */
2424 /* Number of pixels this string overwrites past its right-most
2425 nominal x-position, i.e. x + width. Zero if the string's
2426 rbearing is <= its nominal width, rbearing - width otherwise. */
2429 /* The frame on which the glyph string is drawn. */
2432 /* The window on which the glyph string is drawn. */
2435 /* X display and window for convenience. */
2439 /* The glyph row for which this string was built. It determines the
2440 y-origin and height of the string. */
2441 struct glyph_row
*row
;
2443 /* The area within row. */
2444 enum glyph_row_area area
;
2446 /* Characters to be drawn, and number of characters. */
2450 /* A face-override for drawing cursors, mouse face and similar. */
2451 enum draw_glyphs_face hl
;
2453 /* Face in which this string is to be drawn. */
2456 /* Font in which this string is to be drawn. */
2459 /* Font info for this string. */
2460 struct font_info
*font_info
;
2462 /* Non-null means this string describes (part of) a composition.
2463 All characters from char2b are drawn composed. */
2464 struct composition
*cmp
;
2466 /* Index of this glyph string's first character in the glyph
2467 definition of CMP. If this is zero, this glyph string describes
2468 the first character of a composition. */
2471 /* 1 means this glyph strings face has to be drawn to the right end
2472 of the window's drawing area. */
2473 unsigned extends_to_end_of_line_p
: 1;
2475 /* 1 means the background of this string has been drawn. */
2476 unsigned background_filled_p
: 1;
2478 /* 1 means glyph string must be drawn with 16-bit functions. */
2479 unsigned two_byte_p
: 1;
2481 /* 1 means that the original font determined for drawing this glyph
2482 string could not be loaded. The member `font' has been set to
2483 the frame's default font in this case. */
2484 unsigned font_not_found_p
: 1;
2486 /* 1 means that the face in which this glyph string is drawn has a
2488 unsigned stippled_p
: 1;
2490 /* 1 means only the foreground of this glyph string must be drawn,
2491 and we should use the physical height of the line this glyph
2492 string appears in as clip rect. */
2493 unsigned for_overlaps_p
: 1;
2495 /* The GC to use for drawing this glyph string. */
2498 /* A pointer to the first glyph in the string. This glyph
2499 corresponds to char2b[0]. Needed to draw rectangles if
2500 font_not_found_p is 1. */
2501 struct glyph
*first_glyph
;
2503 /* Image, if any. */
2506 struct glyph_string
*next
, *prev
;
2513 x_dump_glyph_string (s
)
2514 struct glyph_string
*s
;
2516 fprintf (stderr
, "glyph string\n");
2517 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2518 s
->x
, s
->y
, s
->width
, s
->height
);
2519 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2520 fprintf (stderr
, " hl = %d\n", s
->hl
);
2521 fprintf (stderr
, " left overhang = %d, right = %d\n",
2522 s
->left_overhang
, s
->right_overhang
);
2523 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2524 fprintf (stderr
, " extends to end of line = %d\n",
2525 s
->extends_to_end_of_line_p
);
2526 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2527 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2530 #endif /* GLYPH_DEBUG */
2534 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2535 struct glyph_string
**,
2536 struct glyph_string
*,
2537 struct glyph_string
*));
2538 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2539 struct glyph_string
**,
2540 struct glyph_string
*,
2541 struct glyph_string
*));
2542 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2543 struct glyph_string
**,
2544 struct glyph_string
*));
2545 static int x_left_overwritten
P_ ((struct glyph_string
*));
2546 static int x_left_overwriting
P_ ((struct glyph_string
*));
2547 static int x_right_overwritten
P_ ((struct glyph_string
*));
2548 static int x_right_overwriting
P_ ((struct glyph_string
*));
2549 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2551 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2552 XChar2b
*, struct window
*,
2554 enum glyph_row_area
, int,
2555 enum draw_glyphs_face
));
2556 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2557 enum glyph_row_area
, int, int,
2558 enum draw_glyphs_face
, int));
2559 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2560 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2561 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2563 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2564 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2565 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2566 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2567 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2568 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2569 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2570 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2571 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2573 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2574 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2575 unsigned long *, double, int));
2576 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2577 double, int, unsigned long));
2578 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2579 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2580 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2581 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2582 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2583 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2584 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2586 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2587 int, int, int, int, XRectangle
*));
2588 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2589 int, int, int, XRectangle
*));
2590 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2591 enum glyph_row_area
));
2592 static int x_fill_stretch_glyph_string
P_ ((struct glyph_string
*,
2594 enum glyph_row_area
, int, int));
2597 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2601 /* Append the list of glyph strings with head H and tail T to the list
2602 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2605 x_append_glyph_string_lists (head
, tail
, h
, t
)
2606 struct glyph_string
**head
, **tail
;
2607 struct glyph_string
*h
, *t
;
2621 /* Prepend the list of glyph strings with head H and tail T to the
2622 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2626 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2627 struct glyph_string
**head
, **tail
;
2628 struct glyph_string
*h
, *t
;
2642 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2643 Set *HEAD and *TAIL to the resulting list. */
2646 x_append_glyph_string (head
, tail
, s
)
2647 struct glyph_string
**head
, **tail
;
2648 struct glyph_string
*s
;
2650 s
->next
= s
->prev
= NULL
;
2651 x_append_glyph_string_lists (head
, tail
, s
, s
);
2655 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2660 struct glyph_string
*s
;
2662 if (s
->font
== FRAME_FONT (s
->f
)
2663 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2664 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2666 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2669 /* Cursor on non-default face: must merge. */
2673 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2674 xgcv
.foreground
= s
->face
->background
;
2676 /* If the glyph would be invisible, try a different foreground. */
2677 if (xgcv
.foreground
== xgcv
.background
)
2678 xgcv
.foreground
= s
->face
->foreground
;
2679 if (xgcv
.foreground
== xgcv
.background
)
2680 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2681 if (xgcv
.foreground
== xgcv
.background
)
2682 xgcv
.foreground
= s
->face
->foreground
;
2684 /* Make sure the cursor is distinct from text in this face. */
2685 if (xgcv
.background
== s
->face
->background
2686 && xgcv
.foreground
== s
->face
->foreground
)
2688 xgcv
.background
= s
->face
->foreground
;
2689 xgcv
.foreground
= s
->face
->background
;
2692 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2693 xgcv
.font
= s
->font
->fid
;
2694 xgcv
.graphics_exposures
= False
;
2695 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2697 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2698 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2701 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2702 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2704 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2709 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2712 x_set_mouse_face_gc (s
)
2713 struct glyph_string
*s
;
2718 /* What face has to be used last for the mouse face? */
2719 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2720 face
= FACE_FROM_ID (s
->f
, face_id
);
2722 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2724 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2725 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2727 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2728 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2729 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2731 /* If font in this face is same as S->font, use it. */
2732 if (s
->font
== s
->face
->font
)
2733 s
->gc
= s
->face
->gc
;
2736 /* Otherwise construct scratch_cursor_gc with values from FACE
2741 xgcv
.background
= s
->face
->background
;
2742 xgcv
.foreground
= s
->face
->foreground
;
2743 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2744 xgcv
.font
= s
->font
->fid
;
2745 xgcv
.graphics_exposures
= False
;
2746 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2748 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2749 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2752 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2753 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2755 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2758 xassert (s
->gc
!= 0);
2762 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2763 Faces to use in the mode line have already been computed when the
2764 matrix was built, so there isn't much to do, here. */
2767 x_set_mode_line_face_gc (s
)
2768 struct glyph_string
*s
;
2770 s
->gc
= s
->face
->gc
;
2774 /* Set S->gc of glyph string S for drawing that glyph string. Set
2775 S->stippled_p to a non-zero value if the face of S has a stipple
2779 x_set_glyph_string_gc (s
)
2780 struct glyph_string
*s
;
2782 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2784 if (s
->hl
== DRAW_NORMAL_TEXT
)
2786 s
->gc
= s
->face
->gc
;
2787 s
->stippled_p
= s
->face
->stipple
!= 0;
2789 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2791 x_set_mode_line_face_gc (s
);
2792 s
->stippled_p
= s
->face
->stipple
!= 0;
2794 else if (s
->hl
== DRAW_CURSOR
)
2796 x_set_cursor_gc (s
);
2799 else if (s
->hl
== DRAW_MOUSE_FACE
)
2801 x_set_mouse_face_gc (s
);
2802 s
->stippled_p
= s
->face
->stipple
!= 0;
2804 else if (s
->hl
== DRAW_IMAGE_RAISED
2805 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2807 s
->gc
= s
->face
->gc
;
2808 s
->stippled_p
= s
->face
->stipple
!= 0;
2812 s
->gc
= s
->face
->gc
;
2813 s
->stippled_p
= s
->face
->stipple
!= 0;
2816 /* GC must have been set. */
2817 xassert (s
->gc
!= 0);
2821 /* Return in *R the clipping rectangle for glyph string S. */
2824 x_get_glyph_string_clip_rect (s
, r
)
2825 struct glyph_string
*s
;
2828 if (s
->row
->full_width_p
)
2830 /* Draw full-width. X coordinates are relative to S->w->left. */
2831 int canon_x
= CANON_X_UNIT (s
->f
);
2833 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2834 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2836 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2838 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2839 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2843 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2845 /* Unless displaying a mode or menu bar line, which are always
2846 fully visible, clip to the visible part of the row. */
2847 if (s
->w
->pseudo_window_p
)
2848 r
->height
= s
->row
->visible_height
;
2850 r
->height
= s
->height
;
2854 /* This is a text line that may be partially visible. */
2855 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2856 r
->width
= window_box_width (s
->w
, s
->area
);
2857 r
->height
= s
->row
->visible_height
;
2860 /* If S draws overlapping rows, it's sufficient to use the top and
2861 bottom of the window for clipping because this glyph string
2862 intentionally draws over other lines. */
2863 if (s
->for_overlaps_p
)
2865 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2866 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2870 /* Don't use S->y for clipping because it doesn't take partially
2871 visible lines into account. For example, it can be negative for
2872 partially visible lines at the top of a window. */
2873 if (!s
->row
->full_width_p
2874 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2875 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2877 r
->y
= max (0, s
->row
->y
);
2879 /* If drawing a tool-bar window, draw it over the internal border
2880 at the top of the window. */
2881 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2882 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2885 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2889 /* Set clipping for output of glyph string S. S may be part of a mode
2890 line or menu if we don't have X toolkit support. */
2893 x_set_glyph_string_clipping (s
)
2894 struct glyph_string
*s
;
2897 x_get_glyph_string_clip_rect (s
, &r
);
2898 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2902 /* Compute left and right overhang of glyph string S. If S is a glyph
2903 string for a composition, assume overhangs don't exist. */
2906 x_compute_glyph_string_overhangs (s
)
2907 struct glyph_string
*s
;
2910 && s
->first_glyph
->type
== CHAR_GLYPH
)
2913 int direction
, font_ascent
, font_descent
;
2914 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2915 &font_ascent
, &font_descent
, &cs
);
2916 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2917 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2922 /* Compute overhangs and x-positions for glyph string S and its
2923 predecessors, or successors. X is the starting x-position for S.
2924 BACKWARD_P non-zero means process predecessors. */
2927 x_compute_overhangs_and_x (s
, x
, backward_p
)
2928 struct glyph_string
*s
;
2936 x_compute_glyph_string_overhangs (s
);
2946 x_compute_glyph_string_overhangs (s
);
2955 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2956 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2957 assumed to be zero. */
2960 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2961 struct glyph
*glyph
;
2967 if (glyph
->type
== CHAR_GLYPH
)
2971 struct font_info
*font_info
;
2975 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
2977 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2979 && (pcm
= x_per_char_metric (font
, &char2b
)))
2981 if (pcm
->rbearing
> pcm
->width
)
2982 *right
= pcm
->rbearing
- pcm
->width
;
2983 if (pcm
->lbearing
< 0)
2984 *left
= -pcm
->lbearing
;
2990 /* Return the index of the first glyph preceding glyph string S that
2991 is overwritten by S because of S's left overhang. Value is -1
2992 if no glyphs are overwritten. */
2995 x_left_overwritten (s
)
2996 struct glyph_string
*s
;
3000 if (s
->left_overhang
)
3003 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3004 int first
= s
->first_glyph
- glyphs
;
3006 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
3007 x
-= glyphs
[i
].pixel_width
;
3018 /* Return the index of the first glyph preceding glyph string S that
3019 is overwriting S because of its right overhang. Value is -1 if no
3020 glyph in front of S overwrites S. */
3023 x_left_overwriting (s
)
3024 struct glyph_string
*s
;
3027 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3028 int first
= s
->first_glyph
- glyphs
;
3032 for (i
= first
- 1; i
>= 0; --i
)
3035 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3038 x
-= glyphs
[i
].pixel_width
;
3045 /* Return the index of the last glyph following glyph string S that is
3046 not overwritten by S because of S's right overhang. Value is -1 if
3047 no such glyph is found. */
3050 x_right_overwritten (s
)
3051 struct glyph_string
*s
;
3055 if (s
->right_overhang
)
3058 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3059 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3060 int end
= s
->row
->used
[s
->area
];
3062 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
3063 x
+= glyphs
[i
].pixel_width
;
3072 /* Return the index of the last glyph following glyph string S that
3073 overwrites S because of its left overhang. Value is negative
3074 if no such glyph is found. */
3077 x_right_overwriting (s
)
3078 struct glyph_string
*s
;
3081 int end
= s
->row
->used
[s
->area
];
3082 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3083 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3087 for (i
= first
; i
< end
; ++i
)
3090 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3093 x
+= glyphs
[i
].pixel_width
;
3100 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3103 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3104 struct glyph_string
*s
;
3108 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
3109 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3110 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3111 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3115 /* Draw the background of glyph_string S. If S->background_filled_p
3116 is non-zero don't draw it. FORCE_P non-zero means draw the
3117 background even if it wouldn't be drawn normally. This is used
3118 when a string preceding S draws into the background of S, or S
3119 contains the first component of a composition. */
3122 x_draw_glyph_string_background (s
, force_p
)
3123 struct glyph_string
*s
;
3126 /* Nothing to do if background has already been drawn or if it
3127 shouldn't be drawn in the first place. */
3128 if (!s
->background_filled_p
)
3130 int box_line_width
= max (s
->face
->box_line_width
, 0);
3134 /* Fill background with a stipple pattern. */
3135 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3136 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3137 s
->y
+ box_line_width
,
3138 s
->background_width
,
3139 s
->height
- 2 * box_line_width
);
3140 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3141 s
->background_filled_p
= 1;
3143 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
3144 || s
->font_not_found_p
3145 || s
->extends_to_end_of_line_p
3148 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
3149 s
->background_width
,
3150 s
->height
- 2 * box_line_width
);
3151 s
->background_filled_p
= 1;
3157 /* Draw the foreground of glyph string S. */
3160 x_draw_glyph_string_foreground (s
)
3161 struct glyph_string
*s
;
3165 /* If first glyph of S has a left box line, start drawing the text
3166 of S to the right of that box line. */
3167 if (s
->face
->box
!= FACE_NO_BOX
3168 && s
->first_glyph
->left_box_line_p
)
3169 x
= s
->x
+ abs (s
->face
->box_line_width
);
3173 /* Draw characters of S as rectangles if S's font could not be
3175 if (s
->font_not_found_p
)
3177 for (i
= 0; i
< s
->nchars
; ++i
)
3179 struct glyph
*g
= s
->first_glyph
+ i
;
3180 XDrawRectangle (s
->display
, s
->window
,
3181 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3183 x
+= g
->pixel_width
;
3188 char *char1b
= (char *) s
->char2b
;
3189 int boff
= s
->font_info
->baseline_offset
;
3191 if (s
->font_info
->vertical_centering
)
3192 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3194 /* If we can use 8-bit functions, condense S->char2b. */
3196 for (i
= 0; i
< s
->nchars
; ++i
)
3197 char1b
[i
] = s
->char2b
[i
].byte2
;
3199 /* Draw text with XDrawString if background has already been
3200 filled. Otherwise, use XDrawImageString. (Note that
3201 XDrawImageString is usually faster than XDrawString.) Always
3202 use XDrawImageString when drawing the cursor so that there is
3203 no chance that characters under a box cursor are invisible. */
3204 if (s
->for_overlaps_p
3205 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3207 /* Draw characters with 16-bit or 8-bit functions. */
3209 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3210 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3212 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3213 s
->ybase
- boff
, char1b
, s
->nchars
);
3218 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3219 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3221 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3222 s
->ybase
- boff
, char1b
, s
->nchars
);
3227 /* Draw the foreground of composite glyph string S. */
3230 x_draw_composite_glyph_string_foreground (s
)
3231 struct glyph_string
*s
;
3235 /* If first glyph of S has a left box line, start drawing the text
3236 of S to the right of that box line. */
3237 if (s
->face
->box
!= FACE_NO_BOX
3238 && s
->first_glyph
->left_box_line_p
)
3239 x
= s
->x
+ abs (s
->face
->box_line_width
);
3243 /* S is a glyph string for a composition. S->gidx is the index of
3244 the first character drawn for glyphs of this composition.
3245 S->gidx == 0 means we are drawing the very first character of
3246 this composition. */
3248 /* Draw a rectangle for the composition if the font for the very
3249 first character of the composition could not be loaded. */
3250 if (s
->font_not_found_p
)
3253 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3254 s
->width
- 1, s
->height
- 1);
3258 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3259 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3260 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3261 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3267 #ifdef USE_X_TOOLKIT
3269 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3270 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
3271 XrmValue
*, XrmValue
*, XtPointer
*));
3272 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
3273 XrmValue
*, Cardinal
*));
3276 /* Return the frame on which widget WIDGET is used.. Abort if frame
3277 cannot be determined. */
3279 static struct frame
*
3280 x_frame_of_widget (widget
)
3283 struct x_display_info
*dpyinfo
;
3287 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3289 /* Find the top-level shell of the widget. Note that this function
3290 can be called when the widget is not yet realized, so XtWindow
3291 (widget) == 0. That's the reason we can't simply use
3292 x_any_window_to_frame. */
3293 while (!XtIsTopLevelShell (widget
))
3294 widget
= XtParent (widget
);
3296 /* Look for a frame with that top-level widget. Allocate the color
3297 on that frame to get the right gamma correction value. */
3298 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3299 if (GC_FRAMEP (XCAR (tail
))
3300 && (f
= XFRAME (XCAR (tail
)),
3301 (f
->output_data
.nothing
!= 1
3302 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3303 && f
->output_data
.x
->widget
== widget
)
3310 /* Allocate the color COLOR->pixel on the screen and display of
3311 widget WIDGET in colormap CMAP. If an exact match cannot be
3312 allocated, try the nearest color available. Value is non-zero
3313 if successful. This is called from lwlib. */
3316 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3321 struct frame
*f
= x_frame_of_widget (widget
);
3322 return x_alloc_nearest_color (f
, cmap
, color
);
3326 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3327 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3328 If this produces the same color as PIXEL, try a color where all RGB
3329 values have DELTA added. Return the allocated color in *PIXEL.
3330 DISPLAY is the X display, CMAP is the colormap to operate on.
3331 Value is non-zero if successful. */
3334 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
3338 unsigned long *pixel
;
3342 struct frame
*f
= x_frame_of_widget (widget
);
3343 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
3347 /* Structure specifying which arguments should be passed by Xt to
3348 cvt_string_to_pixel. We want the widget's screen and colormap. */
3350 static XtConvertArgRec cvt_string_to_pixel_args
[] =
3352 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
3354 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
3359 /* The address of this variable is returned by
3360 cvt_string_to_pixel. */
3362 static Pixel cvt_string_to_pixel_value
;
3365 /* Convert a color name to a pixel color.
3367 DPY is the display we are working on.
3369 ARGS is an array of *NARGS XrmValue structures holding additional
3370 information about the widget for which the conversion takes place.
3371 The contents of this array are determined by the specification
3372 in cvt_string_to_pixel_args.
3374 FROM is a pointer to an XrmValue which points to the color name to
3375 convert. TO is an XrmValue in which to return the pixel color.
3377 CLOSURE_RET is a pointer to user-data, in which we record if
3378 we allocated the color or not.
3380 Value is True if successful, False otherwise. */
3383 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
3387 XrmValue
*from
, *to
;
3388 XtPointer
*closure_ret
;
3398 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
3399 "wrongParameters", "cvt_string_to_pixel",
3401 "Screen and colormap args required", NULL
, NULL
);
3405 screen
= *(Screen
**) args
[0].addr
;
3406 cmap
= *(Colormap
*) args
[1].addr
;
3407 color_name
= (String
) from
->addr
;
3409 if (strcmp (color_name
, XtDefaultBackground
) == 0)
3411 *closure_ret
= (XtPointer
) False
;
3412 pixel
= WhitePixelOfScreen (screen
);
3414 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
3416 *closure_ret
= (XtPointer
) False
;
3417 pixel
= BlackPixelOfScreen (screen
);
3419 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
3420 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
3422 pixel
= color
.pixel
;
3423 *closure_ret
= (XtPointer
) True
;
3428 Cardinal nparams
= 1;
3430 params
[0] = color_name
;
3431 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
3432 "badValue", "cvt_string_to_pixel",
3433 "XtToolkitError", "Invalid color `%s'",
3438 if (to
->addr
!= NULL
)
3440 if (to
->size
< sizeof (Pixel
))
3442 to
->size
= sizeof (Pixel
);
3446 *(Pixel
*) to
->addr
= pixel
;
3450 cvt_string_to_pixel_value
= pixel
;
3451 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
3454 to
->size
= sizeof (Pixel
);
3459 /* Free a pixel color which was previously allocated via
3460 cvt_string_to_pixel. This is registered as the destructor
3461 for this type of resource via XtSetTypeConverter.
3463 APP is the application context in which we work.
3465 TO is a pointer to an XrmValue holding the color to free.
3466 CLOSURE is the value we stored in CLOSURE_RET for this color
3467 in cvt_string_to_pixel.
3469 ARGS and NARGS are like for cvt_string_to_pixel. */
3472 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
3481 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
3483 "Screen and colormap arguments required",
3486 else if (closure
!= NULL
)
3488 /* We did allocate the pixel, so free it. */
3489 Screen
*screen
= *(Screen
**) args
[0].addr
;
3490 Colormap cmap
= *(Colormap
*) args
[1].addr
;
3491 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
3492 (Pixel
*) to
->addr
, 1);
3497 #endif /* USE_X_TOOLKIT */
3500 /* Value is an array of XColor structures for the contents of the
3501 color map of display DPY. Set *NCELLS to the size of the array.
3502 Note that this probably shouldn't be called for large color maps,
3503 say a 24-bit TrueColor map. */
3505 static const XColor
*
3506 x_color_cells (dpy
, ncells
)
3510 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
3512 if (dpyinfo
->color_cells
== NULL
)
3514 Screen
*screen
= dpyinfo
->screen
;
3517 dpyinfo
->ncolor_cells
3518 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
3519 dpyinfo
->color_cells
3520 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
3521 * sizeof *dpyinfo
->color_cells
);
3523 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
3524 dpyinfo
->color_cells
[i
].pixel
= i
;
3526 XQueryColors (dpy
, dpyinfo
->cmap
,
3527 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
3530 *ncells
= dpyinfo
->ncolor_cells
;
3531 return dpyinfo
->color_cells
;
3535 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3536 colors in COLORS. Use cached information, if available. */
3539 x_query_colors (f
, colors
, ncolors
)
3544 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3546 if (dpyinfo
->color_cells
)
3549 for (i
= 0; i
< ncolors
; ++i
)
3551 unsigned long pixel
= colors
[i
].pixel
;
3552 xassert (pixel
< dpyinfo
->ncolor_cells
);
3553 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
3554 colors
[i
] = dpyinfo
->color_cells
[pixel
];
3558 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
3562 /* On frame F, translate pixel color to RGB values for the color in
3563 COLOR. Use cached information, if available. */
3566 x_query_color (f
, color
)
3570 x_query_colors (f
, color
, 1);
3574 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3575 exact match can't be allocated, try the nearest color available.
3576 Value is non-zero if successful. Set *COLOR to the color
3580 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
3587 rc
= XAllocColor (dpy
, cmap
, color
);
3590 /* If we got to this point, the colormap is full, so we're going
3591 to try to get the next closest color. The algorithm used is
3592 a least-squares matching, which is what X uses for closest
3593 color matching with StaticColor visuals. */
3595 unsigned long nearest_delta
= ~0;
3597 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
3599 for (nearest
= i
= 0; i
< ncells
; ++i
)
3601 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3602 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3603 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3604 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3606 if (delta
< nearest_delta
)
3609 nearest_delta
= delta
;
3613 color
->red
= cells
[nearest
].red
;
3614 color
->green
= cells
[nearest
].green
;
3615 color
->blue
= cells
[nearest
].blue
;
3616 rc
= XAllocColor (dpy
, cmap
, color
);
3620 /* If allocation succeeded, and the allocated pixel color is not
3621 equal to a cached pixel color recorded earlier, there was a
3622 change in the colormap, so clear the color cache. */
3623 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
3624 XColor
*cached_color
;
3626 if (dpyinfo
->color_cells
3627 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
3628 (cached_color
->red
!= color
->red
3629 || cached_color
->blue
!= color
->blue
3630 || cached_color
->green
!= color
->green
)))
3632 xfree (dpyinfo
->color_cells
);
3633 dpyinfo
->color_cells
= NULL
;
3634 dpyinfo
->ncolor_cells
= 0;
3638 #ifdef DEBUG_X_COLORS
3640 register_color (color
->pixel
);
3641 #endif /* DEBUG_X_COLORS */
3647 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3648 exact match can't be allocated, try the nearest color available.
3649 Value is non-zero if successful. Set *COLOR to the color
3653 x_alloc_nearest_color (f
, cmap
, color
)
3658 gamma_correct (f
, color
);
3659 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
3663 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3664 It's necessary to do this instead of just using PIXEL directly to
3665 get color reference counts right. */
3668 x_copy_color (f
, pixel
)
3670 unsigned long pixel
;
3674 color
.pixel
= pixel
;
3676 x_query_color (f
, &color
);
3677 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3679 #ifdef DEBUG_X_COLORS
3680 register_color (pixel
);
3686 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3687 It's necessary to do this instead of just using PIXEL directly to
3688 get color reference counts right. */
3691 x_copy_dpy_color (dpy
, cmap
, pixel
)
3694 unsigned long pixel
;
3698 color
.pixel
= pixel
;
3700 XQueryColor (dpy
, cmap
, &color
);
3701 XAllocColor (dpy
, cmap
, &color
);
3703 #ifdef DEBUG_X_COLORS
3704 register_color (pixel
);
3710 /* Brightness beyond which a color won't have its highlight brightness
3713 Nominally, highlight colors for `3d' faces are calculated by
3714 brightening an object's color by a constant scale factor, but this
3715 doesn't yield good results for dark colors, so for colors who's
3716 brightness is less than this value (on a scale of 0-65535) have an
3717 use an additional additive factor.
3719 The value here is set so that the default menu-bar/mode-line color
3720 (grey75) will not have its highlights changed at all. */
3721 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3724 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3725 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3726 If this produces the same color as PIXEL, try a color where all RGB
3727 values have DELTA added. Return the allocated color in *PIXEL.
3728 DISPLAY is the X display, CMAP is the colormap to operate on.
3729 Value is non-zero if successful. */
3732 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3736 unsigned long *pixel
;
3744 /* Get RGB color values. */
3745 color
.pixel
= *pixel
;
3746 x_query_color (f
, &color
);
3748 /* Change RGB values by specified FACTOR. Avoid overflow! */
3749 xassert (factor
>= 0);
3750 new.red
= min (0xffff, factor
* color
.red
);
3751 new.green
= min (0xffff, factor
* color
.green
);
3752 new.blue
= min (0xffff, factor
* color
.blue
);
3754 /* Calculate brightness of COLOR. */
3755 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
3757 /* We only boost colors that are darker than
3758 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3759 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3760 /* Make an additive adjustment to NEW, because it's dark enough so
3761 that scaling by FACTOR alone isn't enough. */
3763 /* How far below the limit this color is (0 - 1, 1 being darker). */
3764 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3765 /* The additive adjustment. */
3766 int min_delta
= delta
* dimness
* factor
/ 2;
3770 new.red
= max (0, new.red
- min_delta
);
3771 new.green
= max (0, new.green
- min_delta
);
3772 new.blue
= max (0, new.blue
- min_delta
);
3776 new.red
= min (0xffff, min_delta
+ new.red
);
3777 new.green
= min (0xffff, min_delta
+ new.green
);
3778 new.blue
= min (0xffff, min_delta
+ new.blue
);
3782 /* Try to allocate the color. */
3783 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3786 if (new.pixel
== *pixel
)
3788 /* If we end up with the same color as before, try adding
3789 delta to the RGB values. */
3790 x_free_colors (f
, &new.pixel
, 1);
3792 new.red
= min (0xffff, delta
+ color
.red
);
3793 new.green
= min (0xffff, delta
+ color
.green
);
3794 new.blue
= min (0xffff, delta
+ color
.blue
);
3795 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3806 /* Set up the foreground color for drawing relief lines of glyph
3807 string S. RELIEF is a pointer to a struct relief containing the GC
3808 with which lines will be drawn. Use a color that is FACTOR or
3809 DELTA lighter or darker than the relief's background which is found
3810 in S->f->output_data.x->relief_background. If such a color cannot
3811 be allocated, use DEFAULT_PIXEL, instead. */
3814 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3816 struct relief
*relief
;
3819 unsigned long default_pixel
;
3822 struct x_output
*di
= f
->output_data
.x
;
3823 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3824 unsigned long pixel
;
3825 unsigned long background
= di
->relief_background
;
3826 Colormap cmap
= FRAME_X_COLORMAP (f
);
3827 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3828 Display
*dpy
= FRAME_X_DISPLAY (f
);
3830 xgcv
.graphics_exposures
= False
;
3831 xgcv
.line_width
= 1;
3833 /* Free previously allocated color. The color cell will be reused
3834 when it has been freed as many times as it was allocated, so this
3835 doesn't affect faces using the same colors. */
3837 && relief
->allocated_p
)
3839 x_free_colors (f
, &relief
->pixel
, 1);
3840 relief
->allocated_p
= 0;
3843 /* Allocate new color. */
3844 xgcv
.foreground
= default_pixel
;
3846 if (dpyinfo
->n_planes
!= 1
3847 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3849 relief
->allocated_p
= 1;
3850 xgcv
.foreground
= relief
->pixel
= pixel
;
3853 if (relief
->gc
== 0)
3855 xgcv
.stipple
= dpyinfo
->gray
;
3857 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3860 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3864 /* Set up colors for the relief lines around glyph string S. */
3867 x_setup_relief_colors (s
)
3868 struct glyph_string
*s
;
3870 struct x_output
*di
= s
->f
->output_data
.x
;
3871 unsigned long color
;
3873 if (s
->face
->use_box_color_for_shadows_p
)
3874 color
= s
->face
->box_color
;
3875 else if (s
->first_glyph
->type
== IMAGE_GLYPH
3877 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
3878 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
3883 /* Get the background color of the face. */
3884 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3885 color
= xgcv
.background
;
3888 if (di
->white_relief
.gc
== 0
3889 || color
!= di
->relief_background
)
3891 di
->relief_background
= color
;
3892 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3893 WHITE_PIX_DEFAULT (s
->f
));
3894 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3895 BLACK_PIX_DEFAULT (s
->f
));
3900 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3901 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3902 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3903 relief. LEFT_P non-zero means draw a relief on the left side of
3904 the rectangle. RIGHT_P non-zero means draw a relief on the right
3905 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3909 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3910 raised_p
, left_p
, right_p
, clip_rect
)
3912 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3913 XRectangle
*clip_rect
;
3915 Display
*dpy
= FRAME_X_DISPLAY (f
);
3916 Window window
= FRAME_X_WINDOW (f
);
3921 gc
= f
->output_data
.x
->white_relief
.gc
;
3923 gc
= f
->output_data
.x
->black_relief
.gc
;
3924 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
3927 for (i
= 0; i
< width
; ++i
)
3928 XDrawLine (dpy
, window
, gc
,
3929 left_x
+ i
* left_p
, top_y
+ i
,
3930 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3934 for (i
= 0; i
< width
; ++i
)
3935 XDrawLine (dpy
, window
, gc
,
3936 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
3938 XSetClipMask (dpy
, gc
, None
);
3940 gc
= f
->output_data
.x
->black_relief
.gc
;
3942 gc
= f
->output_data
.x
->white_relief
.gc
;
3943 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
3946 for (i
= 0; i
< width
; ++i
)
3947 XDrawLine (dpy
, window
, gc
,
3948 left_x
+ i
* left_p
, bottom_y
- i
,
3949 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3953 for (i
= 0; i
< width
; ++i
)
3954 XDrawLine (dpy
, window
, gc
,
3955 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3957 XSetClipMask (dpy
, gc
, None
);
3961 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3962 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3963 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3964 left side of the rectangle. RIGHT_P non-zero means draw a line
3965 on the right side of the rectangle. CLIP_RECT is the clipping
3966 rectangle to use when drawing. */
3969 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3970 left_p
, right_p
, clip_rect
)
3971 struct glyph_string
*s
;
3972 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3973 XRectangle
*clip_rect
;
3977 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3978 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3979 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3982 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3983 left_x
, top_y
, right_x
- left_x
+ 1, width
);
3987 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3988 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
3991 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3992 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
3996 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3997 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
3999 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4000 XSetClipMask (s
->display
, s
->gc
, None
);
4004 /* Draw a box around glyph string S. */
4007 x_draw_glyph_string_box (s
)
4008 struct glyph_string
*s
;
4010 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
4011 int left_p
, right_p
;
4012 struct glyph
*last_glyph
;
4013 XRectangle clip_rect
;
4015 last_x
= window_box_right (s
->w
, s
->area
);
4016 if (s
->row
->full_width_p
4017 && !s
->w
->pseudo_window_p
)
4019 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
4020 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
4021 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
4024 /* The glyph that may have a right box line. */
4025 last_glyph
= (s
->cmp
|| s
->img
4027 : s
->first_glyph
+ s
->nchars
- 1);
4029 width
= abs (s
->face
->box_line_width
);
4030 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
4032 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
4034 : min (last_x
, s
->x
+ s
->background_width
) - 1);
4036 bottom_y
= top_y
+ s
->height
- 1;
4038 left_p
= (s
->first_glyph
->left_box_line_p
4039 || (s
->hl
== DRAW_MOUSE_FACE
4041 || s
->prev
->hl
!= s
->hl
)));
4042 right_p
= (last_glyph
->right_box_line_p
4043 || (s
->hl
== DRAW_MOUSE_FACE
4045 || s
->next
->hl
!= s
->hl
)));
4047 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4049 if (s
->face
->box
== FACE_SIMPLE_BOX
)
4050 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
4051 left_p
, right_p
, &clip_rect
);
4054 x_setup_relief_colors (s
);
4055 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
4056 width
, raised_p
, left_p
, right_p
, &clip_rect
);
4061 /* Draw foreground of image glyph string S. */
4064 x_draw_image_foreground (s
)
4065 struct glyph_string
*s
;
4068 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4070 /* If first glyph of S has a left box line, start drawing it to the
4071 right of that line. */
4072 if (s
->face
->box
!= FACE_NO_BOX
4073 && s
->first_glyph
->left_box_line_p
)
4074 x
= s
->x
+ abs (s
->face
->box_line_width
);
4078 /* If there is a margin around the image, adjust x- and y-position
4080 x
+= s
->img
->hmargin
;
4081 y
+= s
->img
->vmargin
;
4087 /* We can't set both a clip mask and use XSetClipRectangles
4088 because the latter also sets a clip mask. We also can't
4089 trust on the shape extension to be available
4090 (XShapeCombineRegion). So, compute the rectangle to draw
4092 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4095 XRectangle clip_rect
, image_rect
, r
;
4097 xgcv
.clip_mask
= s
->img
->mask
;
4098 xgcv
.clip_x_origin
= x
;
4099 xgcv
.clip_y_origin
= y
;
4100 xgcv
.function
= GXcopy
;
4101 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4103 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4106 image_rect
.width
= s
->img
->width
;
4107 image_rect
.height
= s
->img
->height
;
4108 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4109 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4110 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4114 XRectangle clip_rect
, image_rect
, r
;
4116 x_get_glyph_string_clip_rect (s
, &clip_rect
);
4119 image_rect
.width
= s
->img
->width
;
4120 image_rect
.height
= s
->img
->height
;
4121 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
4122 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
4123 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
4125 /* When the image has a mask, we can expect that at
4126 least part of a mouse highlight or a block cursor will
4127 be visible. If the image doesn't have a mask, make
4128 a block cursor visible by drawing a rectangle around
4129 the image. I believe it's looking better if we do
4130 nothing here for mouse-face. */
4131 if (s
->hl
== DRAW_CURSOR
)
4133 int r
= s
->img
->relief
;
4135 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
4136 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4141 /* Draw a rectangle if image could not be loaded. */
4142 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
4143 s
->img
->width
- 1, s
->img
->height
- 1);
4147 /* Draw a relief around the image glyph string S. */
4150 x_draw_image_relief (s
)
4151 struct glyph_string
*s
;
4153 int x0
, y0
, x1
, y1
, thick
, raised_p
;
4156 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
4158 /* If first glyph of S has a left box line, start drawing it to the
4159 right of that line. */
4160 if (s
->face
->box
!= FACE_NO_BOX
4161 && s
->first_glyph
->left_box_line_p
)
4162 x
= s
->x
+ abs (s
->face
->box_line_width
);
4166 /* If there is a margin around the image, adjust x- and y-position
4168 x
+= s
->img
->hmargin
;
4169 y
+= s
->img
->vmargin
;
4171 if (s
->hl
== DRAW_IMAGE_SUNKEN
4172 || s
->hl
== DRAW_IMAGE_RAISED
)
4174 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
4175 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
4179 thick
= abs (s
->img
->relief
);
4180 raised_p
= s
->img
->relief
> 0;
4185 x1
= x
+ s
->img
->width
+ thick
- 1;
4186 y1
= y
+ s
->img
->height
+ thick
- 1;
4188 x_setup_relief_colors (s
);
4189 x_get_glyph_string_clip_rect (s
, &r
);
4190 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
4194 /* Draw the foreground of image glyph string S to PIXMAP. */
4197 x_draw_image_foreground_1 (s
, pixmap
)
4198 struct glyph_string
*s
;
4202 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
4204 /* If first glyph of S has a left box line, start drawing it to the
4205 right of that line. */
4206 if (s
->face
->box
!= FACE_NO_BOX
4207 && s
->first_glyph
->left_box_line_p
)
4208 x
= abs (s
->face
->box_line_width
);
4212 /* If there is a margin around the image, adjust x- and y-position
4214 x
+= s
->img
->hmargin
;
4215 y
+= s
->img
->vmargin
;
4221 /* We can't set both a clip mask and use XSetClipRectangles
4222 because the latter also sets a clip mask. We also can't
4223 trust on the shape extension to be available
4224 (XShapeCombineRegion). So, compute the rectangle to draw
4226 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4230 xgcv
.clip_mask
= s
->img
->mask
;
4231 xgcv
.clip_x_origin
= x
;
4232 xgcv
.clip_y_origin
= y
;
4233 xgcv
.function
= GXcopy
;
4234 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4236 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4237 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4238 XSetClipMask (s
->display
, s
->gc
, None
);
4242 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4243 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4245 /* When the image has a mask, we can expect that at
4246 least part of a mouse highlight or a block cursor will
4247 be visible. If the image doesn't have a mask, make
4248 a block cursor visible by drawing a rectangle around
4249 the image. I believe it's looking better if we do
4250 nothing here for mouse-face. */
4251 if (s
->hl
== DRAW_CURSOR
)
4253 int r
= s
->img
->relief
;
4255 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
4256 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
4261 /* Draw a rectangle if image could not be loaded. */
4262 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
4263 s
->img
->width
- 1, s
->img
->height
- 1);
4267 /* Draw part of the background of glyph string S. X, Y, W, and H
4268 give the rectangle to draw. */
4271 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
4272 struct glyph_string
*s
;
4277 /* Fill background with a stipple pattern. */
4278 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4279 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
4280 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4283 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
4287 /* Draw image glyph string S.
4290 s->x +-------------------------
4293 | +-------------------------
4296 | | +-------------------
4302 x_draw_image_glyph_string (s
)
4303 struct glyph_string
*s
;
4306 int box_line_hwidth
= abs (s
->face
->box_line_width
);
4307 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
4309 Pixmap pixmap
= None
;
4311 height
= s
->height
- 2 * box_line_vwidth
;
4313 /* Fill background with face under the image. Do it only if row is
4314 taller than image or if image has a clip mask to reduce
4316 s
->stippled_p
= s
->face
->stipple
!= 0;
4317 if (height
> s
->img
->height
4321 || s
->img
->pixmap
== 0
4322 || s
->width
!= s
->background_width
)
4324 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
4325 x
= s
->x
+ box_line_hwidth
;
4329 y
= s
->y
+ box_line_vwidth
;
4333 /* Create a pixmap as large as the glyph string. Fill it
4334 with the background color. Copy the image to it, using
4335 its mask. Copy the temporary pixmap to the display. */
4336 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
4337 int depth
= DefaultDepthOfScreen (screen
);
4339 /* Create a pixmap as large as the glyph string. */
4340 pixmap
= XCreatePixmap (s
->display
, s
->window
,
4341 s
->background_width
,
4344 /* Don't clip in the following because we're working on the
4346 XSetClipMask (s
->display
, s
->gc
, None
);
4348 /* Fill the pixmap with the background color/stipple. */
4351 /* Fill background with a stipple pattern. */
4352 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4353 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4354 0, 0, s
->background_width
, s
->height
);
4355 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4360 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
4362 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
4363 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4364 0, 0, s
->background_width
, s
->height
);
4365 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4369 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
4371 s
->background_filled_p
= 1;
4374 /* Draw the foreground. */
4377 x_draw_image_foreground_1 (s
, pixmap
);
4378 x_set_glyph_string_clipping (s
);
4379 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
4380 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
4381 XFreePixmap (s
->display
, pixmap
);
4384 x_draw_image_foreground (s
);
4386 /* If we must draw a relief around the image, do it. */
4388 || s
->hl
== DRAW_IMAGE_RAISED
4389 || s
->hl
== DRAW_IMAGE_SUNKEN
)
4390 x_draw_image_relief (s
);
4394 /* Draw stretch glyph string S. */
4397 x_draw_stretch_glyph_string (s
)
4398 struct glyph_string
*s
;
4400 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4401 s
->stippled_p
= s
->face
->stipple
!= 0;
4403 if (s
->hl
== DRAW_CURSOR
4404 && !x_stretch_cursor_p
)
4406 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4407 as wide as the stretch glyph. */
4408 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
4411 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
4413 /* Clear rest using the GC of the original non-cursor face. */
4414 if (width
< s
->background_width
)
4416 int x
= s
->x
+ width
, y
= s
->y
;
4417 int w
= s
->background_width
- width
, h
= s
->height
;
4421 if (s
->row
->mouse_face_p
4422 && cursor_in_mouse_face_p (s
->w
))
4424 x_set_mouse_face_gc (s
);
4430 x_get_glyph_string_clip_rect (s
, &r
);
4431 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
4433 if (s
->face
->stipple
)
4435 /* Fill background with a stipple pattern. */
4436 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
4437 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4438 XSetFillStyle (s
->display
, gc
, FillSolid
);
4443 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
4444 XSetForeground (s
->display
, gc
, xgcv
.background
);
4445 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4446 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
4450 else if (!s
->background_filled_p
)
4451 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
4454 s
->background_filled_p
= 1;
4458 /* Draw glyph string S. */
4461 x_draw_glyph_string (s
)
4462 struct glyph_string
*s
;
4464 int relief_drawn_p
= 0;
4466 /* If S draws into the background of its successor, draw the
4467 background of the successor first so that S can draw into it.
4468 This makes S->next use XDrawString instead of XDrawImageString. */
4469 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
4471 xassert (s
->next
->img
== NULL
);
4472 x_set_glyph_string_gc (s
->next
);
4473 x_set_glyph_string_clipping (s
->next
);
4474 x_draw_glyph_string_background (s
->next
, 1);
4477 /* Set up S->gc, set clipping and draw S. */
4478 x_set_glyph_string_gc (s
);
4480 /* Draw relief (if any) in advance for char/composition so that the
4481 glyph string can be drawn over it. */
4482 if (!s
->for_overlaps_p
4483 && s
->face
->box
!= FACE_NO_BOX
4484 && (s
->first_glyph
->type
== CHAR_GLYPH
4485 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
4488 x_set_glyph_string_clipping (s
);
4489 x_draw_glyph_string_background (s
, 1);
4490 x_draw_glyph_string_box (s
);
4491 x_set_glyph_string_clipping (s
);
4495 x_set_glyph_string_clipping (s
);
4497 switch (s
->first_glyph
->type
)
4500 x_draw_image_glyph_string (s
);
4504 x_draw_stretch_glyph_string (s
);
4508 if (s
->for_overlaps_p
)
4509 s
->background_filled_p
= 1;
4511 x_draw_glyph_string_background (s
, 0);
4512 x_draw_glyph_string_foreground (s
);
4515 case COMPOSITE_GLYPH
:
4516 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4517 s
->background_filled_p
= 1;
4519 x_draw_glyph_string_background (s
, 1);
4520 x_draw_composite_glyph_string_foreground (s
);
4527 if (!s
->for_overlaps_p
)
4529 /* Draw underline. */
4530 if (s
->face
->underline_p
)
4532 unsigned long tem
, h
;
4535 /* Get the underline thickness. Default is 1 pixel. */
4536 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4539 /* Get the underline position. This is the recommended
4540 vertical offset in pixels from the baseline to the top of
4541 the underline. This is a signed value according to the
4542 specs, and its default is
4544 ROUND ((maximum descent) / 2), with
4545 ROUND(x) = floor (x + 0.5) */
4547 if (x_use_underline_position_properties
4548 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4549 y
= s
->ybase
+ (long) tem
;
4550 else if (s
->face
->font
)
4551 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4553 y
= s
->y
+ s
->height
- h
;
4555 if (s
->face
->underline_defaulted_p
)
4556 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4557 s
->x
, y
, s
->width
, h
);
4561 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4562 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4563 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4564 s
->x
, y
, s
->width
, h
);
4565 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4569 /* Draw overline. */
4570 if (s
->face
->overline_p
)
4572 unsigned long dy
= 0, h
= 1;
4574 if (s
->face
->overline_color_defaulted_p
)
4575 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4580 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4581 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4582 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4584 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4588 /* Draw strike-through. */
4589 if (s
->face
->strike_through_p
)
4591 unsigned long h
= 1;
4592 unsigned long dy
= (s
->height
- h
) / 2;
4594 if (s
->face
->strike_through_color_defaulted_p
)
4595 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4600 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4601 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4602 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4604 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4608 /* Draw relief if not yet drawn. */
4609 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
4610 x_draw_glyph_string_box (s
);
4613 /* Reset clipping. */
4614 XSetClipMask (s
->display
, s
->gc
, None
);
4618 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4619 struct face
**, int));
4622 /* Fill glyph string S with composition components specified by S->cmp.
4624 FACES is an array of faces for all components of this composition.
4625 S->gidx is the index of the first component for S.
4626 OVERLAPS_P non-zero means S should draw the foreground only, and
4627 use its physical height for clipping.
4629 Value is the index of a component not in S. */
4632 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4633 struct glyph_string
*s
;
4634 struct face
**faces
;
4641 s
->for_overlaps_p
= overlaps_p
;
4643 s
->face
= faces
[s
->gidx
];
4644 s
->font
= s
->face
->font
;
4645 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4647 /* For all glyphs of this composition, starting at the offset
4648 S->gidx, until we reach the end of the definition or encounter a
4649 glyph that requires the different face, add it to S. */
4651 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4654 /* All glyph strings for the same composition has the same width,
4655 i.e. the width set for the first component of the composition. */
4657 s
->width
= s
->first_glyph
->pixel_width
;
4659 /* If the specified font could not be loaded, use the frame's
4660 default font, but record the fact that we couldn't load it in
4661 the glyph string so that we can draw rectangles for the
4662 characters of the glyph string. */
4663 if (s
->font
== NULL
)
4665 s
->font_not_found_p
= 1;
4666 s
->font
= FRAME_FONT (s
->f
);
4669 /* Adjust base line for subscript/superscript text. */
4670 s
->ybase
+= s
->first_glyph
->voffset
;
4672 xassert (s
->face
&& s
->face
->gc
);
4674 /* This glyph string must always be drawn with 16-bit functions. */
4677 return s
->gidx
+ s
->nchars
;
4681 /* Fill glyph string S from a sequence of character glyphs.
4683 FACE_ID is the face id of the string. START is the index of the
4684 first glyph to consider, END is the index of the last + 1.
4685 OVERLAPS_P non-zero means S should draw the foreground only, and
4686 use its physical height for clipping.
4688 Value is the index of the first glyph not in S. */
4691 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4692 struct glyph_string
*s
;
4694 int start
, end
, overlaps_p
;
4696 struct glyph
*glyph
, *last
;
4698 int glyph_not_available_p
;
4700 xassert (s
->f
== XFRAME (s
->w
->frame
));
4701 xassert (s
->nchars
== 0);
4702 xassert (start
>= 0 && end
> start
);
4704 s
->for_overlaps_p
= overlaps_p
,
4705 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4706 last
= s
->row
->glyphs
[s
->area
] + end
;
4707 voffset
= glyph
->voffset
;
4709 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4712 && glyph
->type
== CHAR_GLYPH
4713 && glyph
->voffset
== voffset
4714 /* Same face id implies same font, nowadays. */
4715 && glyph
->face_id
== face_id
4716 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
4720 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4721 s
->char2b
+ s
->nchars
,
4723 s
->two_byte_p
= two_byte_p
;
4725 xassert (s
->nchars
<= end
- start
);
4726 s
->width
+= glyph
->pixel_width
;
4730 s
->font
= s
->face
->font
;
4731 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4733 /* If the specified font could not be loaded, use the frame's font,
4734 but record the fact that we couldn't load it in
4735 S->font_not_found_p so that we can draw rectangles for the
4736 characters of the glyph string. */
4737 if (s
->font
== NULL
|| glyph_not_available_p
)
4739 s
->font_not_found_p
= 1;
4740 s
->font
= FRAME_FONT (s
->f
);
4743 /* Adjust base line for subscript/superscript text. */
4744 s
->ybase
+= voffset
;
4746 xassert (s
->face
&& s
->face
->gc
);
4747 return glyph
- s
->row
->glyphs
[s
->area
];
4751 /* Fill glyph string S from image glyph S->first_glyph. */
4754 x_fill_image_glyph_string (s
)
4755 struct glyph_string
*s
;
4757 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4758 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
4760 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
4761 s
->font
= s
->face
->font
;
4762 s
->width
= s
->first_glyph
->pixel_width
;
4764 /* Adjust base line for subscript/superscript text. */
4765 s
->ybase
+= s
->first_glyph
->voffset
;
4769 /* Fill glyph string S from a sequence of stretch glyphs.
4771 ROW is the glyph row in which the glyphs are found, AREA is the
4772 area within the row. START is the index of the first glyph to
4773 consider, END is the index of the last + 1.
4775 Value is the index of the first glyph not in S. */
4778 x_fill_stretch_glyph_string (s
, row
, area
, start
, end
)
4779 struct glyph_string
*s
;
4780 struct glyph_row
*row
;
4781 enum glyph_row_area area
;
4784 struct glyph
*glyph
, *last
;
4785 int voffset
, face_id
;
4787 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4789 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4790 last
= s
->row
->glyphs
[s
->area
] + end
;
4791 face_id
= glyph
->face_id
;
4792 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
4793 s
->font
= s
->face
->font
;
4794 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4795 s
->width
= glyph
->pixel_width
;
4796 voffset
= glyph
->voffset
;
4800 && glyph
->type
== STRETCH_GLYPH
4801 && glyph
->voffset
== voffset
4802 && glyph
->face_id
== face_id
);
4804 s
->width
+= glyph
->pixel_width
;
4806 /* Adjust base line for subscript/superscript text. */
4807 s
->ybase
+= voffset
;
4809 /* The case that face->gc == 0 is handled when drawing the glyph
4810 string by calling PREPARE_FACE_FOR_DISPLAY. */
4812 return glyph
- s
->row
->glyphs
[s
->area
];
4816 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4817 of XChar2b structures for S; it can't be allocated in
4818 x_init_glyph_string because it must be allocated via `alloca'. W
4819 is the window on which S is drawn. ROW and AREA are the glyph row
4820 and area within the row from which S is constructed. START is the
4821 index of the first glyph structure covered by S. HL is a
4822 face-override for drawing S. */
4825 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4826 struct glyph_string
*s
;
4829 struct glyph_row
*row
;
4830 enum glyph_row_area area
;
4832 enum draw_glyphs_face hl
;
4834 bzero (s
, sizeof *s
);
4836 s
->f
= XFRAME (w
->frame
);
4837 s
->display
= FRAME_X_DISPLAY (s
->f
);
4838 s
->window
= FRAME_X_WINDOW (s
->f
);
4843 s
->first_glyph
= row
->glyphs
[area
] + start
;
4844 s
->height
= row
->height
;
4845 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4847 /* Display the internal border below the tool-bar window. */
4848 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4849 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4851 s
->ybase
= s
->y
+ row
->ascent
;
4855 /* Set background width of glyph string S. START is the index of the
4856 first glyph following S. LAST_X is the right-most x-position + 1
4857 in the drawing area. */
4860 x_set_glyph_string_background_width (s
, start
, last_x
)
4861 struct glyph_string
*s
;
4865 /* If the face of this glyph string has to be drawn to the end of
4866 the drawing area, set S->extends_to_end_of_line_p. */
4867 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4869 if (start
== s
->row
->used
[s
->area
]
4870 && s
->area
== TEXT_AREA
4871 && ((s
->hl
== DRAW_NORMAL_TEXT
4872 && (s
->row
->fill_line_p
4873 || s
->face
->background
!= default_face
->background
4874 || s
->face
->stipple
!= default_face
->stipple
4875 || s
->row
->mouse_face_p
))
4876 || s
->hl
== DRAW_MOUSE_FACE
4877 || ((s
->hl
== DRAW_IMAGE_RAISED
|| s
->hl
== DRAW_IMAGE_SUNKEN
)
4878 && s
->row
->fill_line_p
)))
4879 s
->extends_to_end_of_line_p
= 1;
4881 /* If S extends its face to the end of the line, set its
4882 background_width to the distance to the right edge of the drawing
4884 if (s
->extends_to_end_of_line_p
)
4885 s
->background_width
= last_x
- s
->x
+ 1;
4887 s
->background_width
= s
->width
;
4891 /* Add a glyph string for a stretch glyph to the list of strings
4892 between HEAD and TAIL. START is the index of the stretch glyph in
4893 row area AREA of glyph row ROW. END is the index of the last glyph
4894 in that glyph row area. X is the current output position assigned
4895 to the new glyph string constructed. HL overrides that face of the
4896 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4897 is the right-most x-position of the drawing area. */
4899 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4900 and below -- keep them on one line. */
4901 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4904 s = (struct glyph_string *) alloca (sizeof *s); \
4905 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4906 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4907 x_append_glyph_string (&HEAD, &TAIL, s); \
4913 /* Add a glyph string for an image glyph to the list of strings
4914 between HEAD and TAIL. START is the index of the image glyph in
4915 row area AREA of glyph row ROW. END is the index of the last glyph
4916 in that glyph row area. X is the current output position assigned
4917 to the new glyph string constructed. HL overrides that face of the
4918 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4919 is the right-most x-position of the drawing area. */
4921 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4924 s = (struct glyph_string *) alloca (sizeof *s); \
4925 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4926 x_fill_image_glyph_string (s); \
4927 x_append_glyph_string (&HEAD, &TAIL, s); \
4934 /* Add a glyph string for a sequence of character glyphs to the list
4935 of strings between HEAD and TAIL. START is the index of the first
4936 glyph in row area AREA of glyph row ROW that is part of the new
4937 glyph string. END is the index of the last glyph in that glyph row
4938 area. X is the current output position assigned to the new glyph
4939 string constructed. HL overrides that face of the glyph; e.g. it
4940 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4941 right-most x-position of the drawing area. */
4943 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4949 c = (ROW)->glyphs[AREA][START].u.ch; \
4950 face_id = (ROW)->glyphs[AREA][START].face_id; \
4952 s = (struct glyph_string *) alloca (sizeof *s); \
4953 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4954 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4955 x_append_glyph_string (&HEAD, &TAIL, s); \
4957 START = x_fill_glyph_string (s, face_id, START, END, \
4963 /* Add a glyph string for a composite sequence to the list of strings
4964 between HEAD and TAIL. START is the index of the first glyph in
4965 row area AREA of glyph row ROW that is part of the new glyph
4966 string. END is the index of the last glyph in that glyph row area.
4967 X is the current output position assigned to the new glyph string
4968 constructed. HL overrides that face of the glyph; e.g. it is
4969 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4970 x-position of the drawing area. */
4972 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4974 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4975 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4976 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4977 struct composition *cmp = composition_table[cmp_id]; \
4978 int glyph_len = cmp->glyph_len; \
4980 struct face **faces; \
4981 struct glyph_string *first_s = NULL; \
4984 base_face = base_face->ascii_face; \
4985 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4986 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4987 /* At first, fill in `char2b' and `faces'. */ \
4988 for (n = 0; n < glyph_len; n++) \
4990 int c = COMPOSITION_GLYPH (cmp, n); \
4991 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4992 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4993 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4994 this_face_id, char2b + n, 1, 1); \
4997 /* Make glyph_strings for each glyph sequence that is drawable by \
4998 the same face, and append them to HEAD/TAIL. */ \
4999 for (n = 0; n < cmp->glyph_len;) \
5001 s = (struct glyph_string *) alloca (sizeof *s); \
5002 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5003 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5011 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5019 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5020 of AREA of glyph row ROW on window W between indices START and END.
5021 HL overrides the face for drawing glyph strings, e.g. it is
5022 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5023 x-positions of the drawing area.
5025 This is an ugly monster macro construct because we must use alloca
5026 to allocate glyph strings (because x_draw_glyphs can be called
5029 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5032 HEAD = TAIL = NULL; \
5033 while (START < END) \
5035 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5036 switch (first_glyph->type) \
5039 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5040 TAIL, HL, X, LAST_X, \
5044 case COMPOSITE_GLYPH: \
5045 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5046 HEAD, TAIL, HL, X, LAST_X,\
5050 case STRETCH_GLYPH: \
5051 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5052 HEAD, TAIL, HL, X, LAST_X); \
5056 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5057 TAIL, HL, X, LAST_X); \
5064 x_set_glyph_string_background_width (s, START, LAST_X); \
5071 /* Draw glyphs between START and END in AREA of ROW on window W,
5072 starting at x-position X. X is relative to AREA in W. HL is a
5073 face-override with the following meaning:
5075 DRAW_NORMAL_TEXT draw normally
5076 DRAW_CURSOR draw in cursor face
5077 DRAW_MOUSE_FACE draw in mouse face.
5078 DRAW_INVERSE_VIDEO draw in mode line face
5079 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5080 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5082 If OVERLAPS_P is non-zero, draw only the foreground of characters
5083 and clip to the physical height of ROW.
5085 Value is the x-position reached, relative to AREA of W. */
5088 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, overlaps_p
)
5091 struct glyph_row
*row
;
5092 enum glyph_row_area area
;
5094 enum draw_glyphs_face hl
;
5097 struct glyph_string
*head
, *tail
;
5098 struct glyph_string
*s
;
5099 int last_x
, area_width
;
5103 /* Let's rather be paranoid than getting a SEGV. */
5104 end
= min (end
, row
->used
[area
]);
5105 start
= max (0, start
);
5106 start
= min (end
, start
);
5108 /* Translate X to frame coordinates. Set last_x to the right
5109 end of the drawing area. */
5110 if (row
->full_width_p
)
5112 /* X is relative to the left edge of W, without scroll bars
5114 struct frame
*f
= XFRAME (w
->frame
);
5115 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
5118 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5119 last_x
= window_left_x
+ area_width
;
5121 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5123 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5124 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5130 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5131 last_x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5135 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
5136 area_width
= window_box_width (w
, area
);
5137 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
5140 /* Build a doubly-linked list of glyph_string structures between
5141 head and tail from what we have to draw. Note that the macro
5142 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5143 the reason we use a separate variable `i'. */
5145 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
5148 x_reached
= tail
->x
+ tail
->background_width
;
5152 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5153 the row, redraw some glyphs in front or following the glyph
5154 strings built above. */
5155 if (head
&& !overlaps_p
&& row
->contains_overlapping_glyphs_p
)
5158 struct glyph_string
*h
, *t
;
5160 /* Compute overhangs for all glyph strings. */
5161 for (s
= head
; s
; s
= s
->next
)
5162 x_compute_glyph_string_overhangs (s
);
5164 /* Prepend glyph strings for glyphs in front of the first glyph
5165 string that are overwritten because of the first glyph
5166 string's left overhang. The background of all strings
5167 prepended must be drawn because the first glyph string
5169 i
= x_left_overwritten (head
);
5173 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
5174 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5177 x_compute_overhangs_and_x (t
, head
->x
, 1);
5178 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5181 /* Prepend glyph strings for glyphs in front of the first glyph
5182 string that overwrite that glyph string because of their
5183 right overhang. For these strings, only the foreground must
5184 be drawn, because it draws over the glyph string at `head'.
5185 The background must not be drawn because this would overwrite
5186 right overhangs of preceding glyphs for which no glyph
5188 i
= x_left_overwriting (head
);
5191 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
5192 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
5194 for (s
= h
; s
; s
= s
->next
)
5195 s
->background_filled_p
= 1;
5196 x_compute_overhangs_and_x (t
, head
->x
, 1);
5197 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
5200 /* Append glyphs strings for glyphs following the last glyph
5201 string tail that are overwritten by tail. The background of
5202 these strings has to be drawn because tail's foreground draws
5204 i
= x_right_overwritten (tail
);
5207 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5208 DRAW_NORMAL_TEXT
, x
, last_x
,
5210 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5211 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5214 /* Append glyph strings for glyphs following the last glyph
5215 string tail that overwrite tail. The foreground of such
5216 glyphs has to be drawn because it writes into the background
5217 of tail. The background must not be drawn because it could
5218 paint over the foreground of following glyphs. */
5219 i
= x_right_overwriting (tail
);
5222 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
5223 DRAW_NORMAL_TEXT
, x
, last_x
,
5225 for (s
= h
; s
; s
= s
->next
)
5226 s
->background_filled_p
= 1;
5227 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
5228 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5232 /* Draw all strings. */
5233 for (s
= head
; s
; s
= s
->next
)
5234 x_draw_glyph_string (s
);
5236 if (area
== TEXT_AREA
5237 && !row
->full_width_p
5238 /* When drawing overlapping rows, only the glyph strings'
5239 foreground is drawn, which doesn't erase a cursor
5243 int x0
= head
? head
->x
: x
;
5244 int x1
= tail
? tail
->x
+ tail
->background_width
: x
;
5246 x0
= FRAME_TO_WINDOW_PIXEL_X (w
, x0
);
5247 x1
= FRAME_TO_WINDOW_PIXEL_X (w
, x1
);
5249 if (XFASTINT (w
->left_margin_width
) != 0)
5251 int left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5252 x0
-= left_area_width
;
5253 x1
-= left_area_width
;
5256 notice_overwritten_cursor (w
, area
, x0
, x1
,
5257 row
->y
, MATRIX_ROW_BOTTOM_Y (row
));
5260 /* Value is the x-position up to which drawn, relative to AREA of W.
5261 This doesn't include parts drawn because of overhangs. */
5262 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
5263 if (!row
->full_width_p
)
5265 if (area
> LEFT_MARGIN_AREA
&& XFASTINT (w
->left_margin_width
) != 0)
5266 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
5267 if (area
> TEXT_AREA
)
5268 x_reached
-= window_box_width (w
, TEXT_AREA
);
5275 /* Fix the display of area AREA of overlapping row ROW in window W. */
5278 x_fix_overlapping_area (w
, row
, area
)
5280 struct glyph_row
*row
;
5281 enum glyph_row_area area
;
5287 if (area
== LEFT_MARGIN_AREA
)
5289 else if (area
== TEXT_AREA
)
5290 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5292 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5293 + window_box_width (w
, TEXT_AREA
));
5295 for (i
= 0; i
< row
->used
[area
];)
5297 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
5299 int start
= i
, start_x
= x
;
5303 x
+= row
->glyphs
[area
][i
].pixel_width
;
5306 while (i
< row
->used
[area
]
5307 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
5309 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
5310 DRAW_NORMAL_TEXT
, 1);
5314 x
+= row
->glyphs
[area
][i
].pixel_width
;
5323 /* Output LEN glyphs starting at START at the nominal cursor position.
5324 Advance the nominal cursor over the text. The global variable
5325 updated_window contains the window being updated, updated_row is
5326 the glyph row being updated, and updated_area is the area of that
5327 row being updated. */
5330 x_write_glyphs (start
, len
)
5331 struct glyph
*start
;
5336 xassert (updated_window
&& updated_row
);
5341 hpos
= start
- updated_row
->glyphs
[updated_area
];
5342 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
5343 updated_row
, updated_area
,
5345 DRAW_NORMAL_TEXT
, 0);
5347 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
5348 if (updated_area
== TEXT_AREA
5349 && updated_window
->phys_cursor_on_p
5350 && updated_window
->phys_cursor
.vpos
== output_cursor
.vpos
5351 && updated_window
->phys_cursor
.hpos
>= hpos
5352 && updated_window
->phys_cursor
.hpos
< hpos
+ len
)
5353 updated_window
->phys_cursor_on_p
= 0;
5357 /* Advance the output cursor. */
5358 output_cursor
.hpos
+= len
;
5359 output_cursor
.x
= x
;
5363 /* Insert LEN glyphs from START at the nominal cursor position. */
5366 x_insert_glyphs (start
, len
)
5367 struct glyph
*start
;
5372 int line_height
, shift_by_width
, shifted_region_width
;
5373 struct glyph_row
*row
;
5374 struct glyph
*glyph
;
5375 int frame_x
, frame_y
, hpos
;
5377 xassert (updated_window
&& updated_row
);
5380 f
= XFRAME (WINDOW_FRAME (w
));
5382 /* Get the height of the line we are in. */
5384 line_height
= row
->height
;
5386 /* Get the width of the glyphs to insert. */
5388 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
5389 shift_by_width
+= glyph
->pixel_width
;
5391 /* Get the width of the region to shift right. */
5392 shifted_region_width
= (window_box_width (w
, updated_area
)
5397 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
5398 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
5399 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5400 f
->output_data
.x
->normal_gc
,
5402 shifted_region_width
, line_height
,
5403 frame_x
+ shift_by_width
, frame_y
);
5405 /* Write the glyphs. */
5406 hpos
= start
- row
->glyphs
[updated_area
];
5407 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
5408 DRAW_NORMAL_TEXT
, 0);
5410 /* Advance the output cursor. */
5411 output_cursor
.hpos
+= len
;
5412 output_cursor
.x
+= shift_by_width
;
5417 /* Delete N glyphs at the nominal cursor position. Not implemented
5428 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5429 If they are <= 0, this is probably an error. */
5432 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
5439 xassert (width
> 0 && height
> 0);
5440 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
5444 /* Erase the current text line from the nominal cursor position
5445 (inclusive) to pixel column TO_X (exclusive). The idea is that
5446 everything from TO_X onward is already erased.
5448 TO_X is a pixel position relative to updated_area of
5449 updated_window. TO_X == -1 means clear to the end of this area. */
5452 x_clear_end_of_line (to_x
)
5456 struct window
*w
= updated_window
;
5457 int max_x
, min_y
, max_y
;
5458 int from_x
, from_y
, to_y
;
5460 xassert (updated_window
&& updated_row
);
5461 f
= XFRAME (w
->frame
);
5463 if (updated_row
->full_width_p
)
5465 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5466 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5467 && !w
->pseudo_window_p
)
5468 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5471 max_x
= window_box_width (w
, updated_area
);
5472 max_y
= window_text_bottom_y (w
);
5474 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5475 of window. For TO_X > 0, truncate to end of drawing area. */
5481 to_x
= min (to_x
, max_x
);
5483 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
5485 /* Notice if the cursor will be cleared by this operation. */
5486 if (!updated_row
->full_width_p
)
5487 notice_overwritten_cursor (w
, updated_area
,
5488 output_cursor
.x
, -1,
5490 MATRIX_ROW_BOTTOM_Y (updated_row
));
5492 from_x
= output_cursor
.x
;
5494 /* Translate to frame coordinates. */
5495 if (updated_row
->full_width_p
)
5497 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
5498 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
5502 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
5503 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
5506 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
5507 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
5508 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
5510 /* Prevent inadvertently clearing to end of the X window. */
5511 if (to_x
> from_x
&& to_y
> from_y
)
5514 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5515 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
5522 /* Clear entire frame. If updating_frame is non-null, clear that
5523 frame. Otherwise clear the selected frame. */
5533 f
= SELECTED_FRAME ();
5535 /* Clearing the frame will erase any cursor, so mark them all as no
5537 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5538 output_cursor
.hpos
= output_cursor
.vpos
= 0;
5539 output_cursor
.x
= -1;
5541 /* We don't set the output cursor here because there will always
5542 follow an explicit cursor_to. */
5544 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5546 /* We have to clear the scroll bars, too. If we have changed
5547 colors or something like that, then they should be notified. */
5548 x_scroll_bar_clear (f
);
5550 XFlush (FRAME_X_DISPLAY (f
));
5556 /* Invert the middle quarter of the frame for .15 sec. */
5558 /* We use the select system call to do the waiting, so we have to make
5559 sure it's available. If it isn't, we just won't do visual bells. */
5561 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5564 /* Subtract the `struct timeval' values X and Y, storing the result in
5565 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5568 timeval_subtract (result
, x
, y
)
5569 struct timeval
*result
, x
, y
;
5571 /* Perform the carry for the later subtraction by updating y. This
5572 is safer because on some systems the tv_sec member is unsigned. */
5573 if (x
.tv_usec
< y
.tv_usec
)
5575 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
5576 y
.tv_usec
-= 1000000 * nsec
;
5580 if (x
.tv_usec
- y
.tv_usec
> 1000000)
5582 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
5583 y
.tv_usec
+= 1000000 * nsec
;
5587 /* Compute the time remaining to wait. tv_usec is certainly
5589 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5590 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5592 /* Return indication of whether the result should be considered
5594 return x
.tv_sec
< y
.tv_sec
;
5606 /* Create a GC that will use the GXxor function to flip foreground
5607 pixels into background pixels. */
5611 values
.function
= GXxor
;
5612 values
.foreground
= (f
->output_data
.x
->foreground_pixel
5613 ^ f
->output_data
.x
->background_pixel
);
5615 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5616 GCFunction
| GCForeground
, &values
);
5620 /* Get the height not including a menu bar widget. */
5621 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
5622 /* Height of each line to flash. */
5623 int flash_height
= FRAME_LINE_HEIGHT (f
);
5624 /* These will be the left and right margins of the rectangles. */
5625 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
5626 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
5630 /* Don't flash the area between a scroll bar and the frame
5631 edge it is next to. */
5632 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
5634 case vertical_scroll_bar_left
:
5635 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5638 case vertical_scroll_bar_right
:
5639 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5646 width
= flash_right
- flash_left
;
5648 /* If window is tall, flash top and bottom line. */
5649 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5651 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5653 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5654 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5655 width
, flash_height
);
5656 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5658 (height
- flash_height
5659 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5660 width
, flash_height
);
5663 /* If it is short, flash it all. */
5664 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5665 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5666 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5671 struct timeval wakeup
;
5673 EMACS_GET_TIME (wakeup
);
5675 /* Compute time to wait until, propagating carry from usecs. */
5676 wakeup
.tv_usec
+= 150000;
5677 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5678 wakeup
.tv_usec
%= 1000000;
5680 /* Keep waiting until past the time wakeup or any input gets
5682 while (! detect_input_pending ())
5684 struct timeval current
;
5685 struct timeval timeout
;
5687 EMACS_GET_TIME (current
);
5689 /* Break if result would be negative. */
5690 if (timeval_subtract (¤t
, wakeup
, current
))
5693 /* How long `select' should wait. */
5695 timeout
.tv_usec
= 10000;
5697 /* Try to wait that long--but we might wake up sooner. */
5698 select (0, NULL
, NULL
, NULL
, &timeout
);
5702 /* If window is tall, flash top and bottom line. */
5703 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5705 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5707 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5708 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5709 width
, flash_height
);
5710 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5712 (height
- flash_height
5713 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5714 width
, flash_height
);
5717 /* If it is short, flash it all. */
5718 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5719 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5720 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5722 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5730 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5733 /* Make audible bell. */
5738 struct frame
*f
= SELECTED_FRAME ();
5740 if (FRAME_X_DISPLAY (f
))
5742 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5749 XBell (FRAME_X_DISPLAY (f
), 0);
5750 XFlush (FRAME_X_DISPLAY (f
));
5757 /* Specify how many text lines, from the top of the window,
5758 should be affected by insert-lines and delete-lines operations.
5759 This, and those operations, are used only within an update
5760 that is bounded by calls to x_update_begin and x_update_end. */
5763 XTset_terminal_window (n
)
5766 /* This function intentionally left blank. */
5771 /***********************************************************************
5773 ***********************************************************************/
5775 /* Perform an insert-lines or delete-lines operation, inserting N
5776 lines or deleting -N lines at vertical position VPOS. */
5779 x_ins_del_lines (vpos
, n
)
5786 /* Scroll part of the display as described by RUN. */
5789 x_scroll_run (w
, run
)
5793 struct frame
*f
= XFRAME (w
->frame
);
5794 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5796 /* Get frame-relative bounding box of the text display area of W,
5797 without mode lines. Include in this box the left and right
5799 window_box (w
, -1, &x
, &y
, &width
, &height
);
5800 width
+= FRAME_X_FRINGE_WIDTH (f
);
5801 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
5803 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5804 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5805 bottom_y
= y
+ height
;
5809 /* Scrolling up. Make sure we don't copy part of the mode
5810 line at the bottom. */
5811 if (from_y
+ run
->height
> bottom_y
)
5812 height
= bottom_y
- from_y
;
5814 height
= run
->height
;
5818 /* Scolling down. Make sure we don't copy over the mode line.
5820 if (to_y
+ run
->height
> bottom_y
)
5821 height
= bottom_y
- to_y
;
5823 height
= run
->height
;
5828 /* Cursor off. Will be switched on again in x_update_window_end. */
5832 XCopyArea (FRAME_X_DISPLAY (f
),
5833 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5834 f
->output_data
.x
->normal_gc
,
5844 /***********************************************************************
5846 ***********************************************************************/
5848 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5849 corner of the exposed rectangle. W and H are width and height of
5850 the exposed area. All are pixel values. W or H zero means redraw
5851 the entire frame. */
5854 expose_frame (f
, x
, y
, w
, h
)
5859 int mouse_face_overwritten_p
= 0;
5861 TRACE ((stderr
, "expose_frame "));
5863 /* No need to redraw if frame will be redrawn soon. */
5864 if (FRAME_GARBAGED_P (f
))
5866 TRACE ((stderr
, " garbaged\n"));
5870 /* If basic faces haven't been realized yet, there is no point in
5871 trying to redraw anything. This can happen when we get an expose
5872 event while Emacs is starting, e.g. by moving another window. */
5873 if (FRAME_FACE_CACHE (f
) == NULL
5874 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5876 TRACE ((stderr
, " no faces\n"));
5880 if (w
== 0 || h
== 0)
5883 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5884 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5894 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5895 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
5897 if (WINDOWP (f
->tool_bar_window
))
5898 mouse_face_overwritten_p
5899 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
5901 #ifndef USE_X_TOOLKIT
5902 if (WINDOWP (f
->menu_bar_window
))
5903 mouse_face_overwritten_p
5904 |= expose_window (XWINDOW (f
->menu_bar_window
), &r
);
5905 #endif /* not USE_X_TOOLKIT */
5907 /* Some window managers support a focus-follows-mouse style with
5908 delayed raising of frames. Imagine a partially obscured frame,
5909 and moving the mouse into partially obscured mouse-face on that
5910 frame. The visible part of the mouse-face will be highlighted,
5911 then the WM raises the obscured frame. With at least one WM, KDE
5912 2.1, Emacs is not getting any event for the raising of the frame
5913 (even tried with SubstructureRedirectMask), only Expose events.
5914 These expose events will draw text normally, i.e. not
5915 highlighted. Which means we must redo the highlight here.
5916 Subsume it under ``we love X''. --gerd 2001-08-15 */
5917 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
5919 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5920 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5922 int x
= dpyinfo
->mouse_face_mouse_x
;
5923 int y
= dpyinfo
->mouse_face_mouse_y
;
5924 clear_mouse_face (dpyinfo
);
5925 note_mouse_highlight (f
, x
, y
);
5931 /* Redraw (parts) of all windows in the window tree rooted at W that
5932 intersect R. R contains frame pixel coordinates. Value is
5933 non-zero if the exposure overwrites mouse-face. */
5936 expose_window_tree (w
, r
)
5940 struct frame
*f
= XFRAME (w
->frame
);
5941 int mouse_face_overwritten_p
= 0;
5943 while (w
&& !FRAME_GARBAGED_P (f
))
5945 if (!NILP (w
->hchild
))
5946 mouse_face_overwritten_p
5947 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
5948 else if (!NILP (w
->vchild
))
5949 mouse_face_overwritten_p
5950 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
5952 mouse_face_overwritten_p
|= expose_window (w
, r
);
5954 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
5957 return mouse_face_overwritten_p
;
5961 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5962 which intersects rectangle R. R is in window-relative coordinates. */
5965 expose_area (w
, row
, r
, area
)
5967 struct glyph_row
*row
;
5969 enum glyph_row_area area
;
5971 struct glyph
*first
= row
->glyphs
[area
];
5972 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5974 int first_x
, start_x
, x
;
5976 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5977 /* If row extends face to end of line write the whole line. */
5978 x_draw_glyphs (w
, 0, row
, area
, 0, row
->used
[area
],
5979 DRAW_NORMAL_TEXT
, 0);
5982 /* Set START_X to the window-relative start position for drawing glyphs of
5983 AREA. The first glyph of the text area can be partially visible.
5984 The first glyphs of other areas cannot. */
5985 if (area
== LEFT_MARGIN_AREA
)
5987 else if (area
== TEXT_AREA
)
5988 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5990 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5991 + window_box_width (w
, TEXT_AREA
));
5994 /* Find the first glyph that must be redrawn. */
5996 && x
+ first
->pixel_width
< r
->x
)
5998 x
+= first
->pixel_width
;
6002 /* Find the last one. */
6006 && x
< r
->x
+ r
->width
)
6008 x
+= last
->pixel_width
;
6014 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
6015 first
- row
->glyphs
[area
],
6016 last
- row
->glyphs
[area
],
6017 DRAW_NORMAL_TEXT
, 0);
6022 /* Redraw the parts of the glyph row ROW on window W intersecting
6023 rectangle R. R is in window-relative coordinates. Value is
6024 non-zero if mouse-face was overwritten. */
6027 expose_line (w
, row
, r
)
6029 struct glyph_row
*row
;
6032 xassert (row
->enabled_p
);
6034 if (row
->mode_line_p
|| w
->pseudo_window_p
)
6035 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
6036 DRAW_NORMAL_TEXT
, 0);
6039 if (row
->used
[LEFT_MARGIN_AREA
])
6040 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
6041 if (row
->used
[TEXT_AREA
])
6042 expose_area (w
, row
, r
, TEXT_AREA
);
6043 if (row
->used
[RIGHT_MARGIN_AREA
])
6044 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
6045 x_draw_row_fringe_bitmaps (w
, row
);
6048 return row
->mouse_face_p
;
6052 /* Return non-zero if W's cursor intersects rectangle R. */
6055 x_phys_cursor_in_rect_p (w
, r
)
6059 XRectangle cr
, result
;
6060 struct glyph
*cursor_glyph
;
6062 cursor_glyph
= get_phys_cursor_glyph (w
);
6065 cr
.x
= w
->phys_cursor
.x
;
6066 cr
.y
= w
->phys_cursor
.y
;
6067 cr
.width
= cursor_glyph
->pixel_width
;
6068 cr
.height
= w
->phys_cursor_height
;
6069 return x_intersect_rectangles (&cr
, r
, &result
);
6076 /* Redraw those parts of glyphs rows during expose event handling that
6077 overlap other rows. Redrawing of an exposed line writes over parts
6078 of lines overlapping that exposed line; this function fixes that.
6080 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6081 row in W's current matrix that is exposed and overlaps other rows.
6082 LAST_OVERLAPPING_ROW is the last such row. */
6085 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
)
6087 struct glyph_row
*first_overlapping_row
;
6088 struct glyph_row
*last_overlapping_row
;
6090 struct glyph_row
*row
;
6092 for (row
= first_overlapping_row
; row
<= last_overlapping_row
; ++row
)
6093 if (row
->overlapping_p
)
6095 xassert (row
->enabled_p
&& !row
->mode_line_p
);
6097 if (row
->used
[LEFT_MARGIN_AREA
])
6098 x_fix_overlapping_area (w
, row
, LEFT_MARGIN_AREA
);
6100 if (row
->used
[TEXT_AREA
])
6101 x_fix_overlapping_area (w
, row
, TEXT_AREA
);
6103 if (row
->used
[RIGHT_MARGIN_AREA
])
6104 x_fix_overlapping_area (w
, row
, RIGHT_MARGIN_AREA
);
6109 /* Redraw the part of window W intersection rectangle FR. Pixel
6110 coordinates in FR are frame-relative. Call this function with
6111 input blocked. Value is non-zero if the exposure overwrites
6115 expose_window (w
, fr
)
6119 struct frame
*f
= XFRAME (w
->frame
);
6121 int mouse_face_overwritten_p
= 0;
6123 /* If window is not yet fully initialized, do nothing. This can
6124 happen when toolkit scroll bars are used and a window is split.
6125 Reconfiguring the scroll bar will generate an expose for a newly
6127 if (w
->current_matrix
== NULL
)
6130 /* When we're currently updating the window, display and current
6131 matrix usually don't agree. Arrange for a thorough display
6133 if (w
== updated_window
)
6135 SET_FRAME_GARBAGED (f
);
6139 /* Frame-relative pixel rectangle of W. */
6140 wr
.x
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
6141 wr
.y
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
6142 wr
.width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
6143 wr
.height
= XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
6145 if (x_intersect_rectangles (fr
, &wr
, &r
))
6147 int yb
= window_text_bottom_y (w
);
6148 struct glyph_row
*row
;
6149 int cursor_cleared_p
;
6150 struct glyph_row
*first_overlapping_row
, *last_overlapping_row
;
6152 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
6153 r
.x
, r
.y
, r
.width
, r
.height
));
6155 /* Convert to window coordinates. */
6156 r
.x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.x
);
6157 r
.y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.y
);
6159 /* Turn off the cursor. */
6160 if (!w
->pseudo_window_p
6161 && x_phys_cursor_in_rect_p (w
, &r
))
6164 cursor_cleared_p
= 1;
6167 cursor_cleared_p
= 0;
6169 /* Update lines intersecting rectangle R. */
6170 first_overlapping_row
= last_overlapping_row
= NULL
;
6171 for (row
= w
->current_matrix
->rows
;
6176 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
6178 if ((y0
>= r
.y
&& y0
< r
.y
+ r
.height
)
6179 || (y1
> r
.y
&& y1
< r
.y
+ r
.height
)
6180 || (r
.y
>= y0
&& r
.y
< y1
)
6181 || (r
.y
+ r
.height
> y0
&& r
.y
+ r
.height
< y1
))
6183 if (row
->overlapping_p
)
6185 if (first_overlapping_row
== NULL
)
6186 first_overlapping_row
= row
;
6187 last_overlapping_row
= row
;
6190 if (expose_line (w
, row
, &r
))
6191 mouse_face_overwritten_p
= 1;
6198 /* Display the mode line if there is one. */
6199 if (WINDOW_WANTS_MODELINE_P (w
)
6200 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
6202 && row
->y
< r
.y
+ r
.height
)
6204 if (expose_line (w
, row
, &r
))
6205 mouse_face_overwritten_p
= 1;
6208 if (!w
->pseudo_window_p
)
6210 /* Fix the display of overlapping rows. */
6211 if (first_overlapping_row
)
6212 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
);
6214 /* Draw border between windows. */
6215 x_draw_vertical_border (w
);
6217 /* Turn the cursor on again. */
6218 if (cursor_cleared_p
)
6219 x_update_window_cursor (w
, 1);
6223 return mouse_face_overwritten_p
;
6227 /* Determine the intersection of two rectangles R1 and R2. Return
6228 the intersection in *RESULT. Value is non-zero if RESULT is not
6232 x_intersect_rectangles (r1
, r2
, result
)
6233 XRectangle
*r1
, *r2
, *result
;
6235 XRectangle
*left
, *right
;
6236 XRectangle
*upper
, *lower
;
6237 int intersection_p
= 0;
6239 /* Rearrange so that R1 is the left-most rectangle. */
6241 left
= r1
, right
= r2
;
6243 left
= r2
, right
= r1
;
6245 /* X0 of the intersection is right.x0, if this is inside R1,
6246 otherwise there is no intersection. */
6247 if (right
->x
<= left
->x
+ left
->width
)
6249 result
->x
= right
->x
;
6251 /* The right end of the intersection is the minimum of the
6252 the right ends of left and right. */
6253 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
6256 /* Same game for Y. */
6258 upper
= r1
, lower
= r2
;
6260 upper
= r2
, lower
= r1
;
6262 /* The upper end of the intersection is lower.y0, if this is inside
6263 of upper. Otherwise, there is no intersection. */
6264 if (lower
->y
<= upper
->y
+ upper
->height
)
6266 result
->y
= lower
->y
;
6268 /* The lower end of the intersection is the minimum of the lower
6269 ends of upper and lower. */
6270 result
->height
= (min (lower
->y
+ lower
->height
,
6271 upper
->y
+ upper
->height
)
6277 return intersection_p
;
6288 /* We used to only do this if Vx_no_window_manager was non-nil, but
6289 the ICCCM (section 4.1.6) says that the window's border pixmap
6290 and border pixel are window attributes which are "private to the
6291 client", so we can always change it to whatever we want. */
6293 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6294 f
->output_data
.x
->border_pixel
);
6296 x_update_cursor (f
, 1);
6300 frame_unhighlight (f
)
6303 /* We used to only do this if Vx_no_window_manager was non-nil, but
6304 the ICCCM (section 4.1.6) says that the window's border pixmap
6305 and border pixel are window attributes which are "private to the
6306 client", so we can always change it to whatever we want. */
6308 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6309 f
->output_data
.x
->border_tile
);
6311 x_update_cursor (f
, 1);
6314 /* The focus has changed. Update the frames as necessary to reflect
6315 the new situation. Note that we can't change the selected frame
6316 here, because the Lisp code we are interrupting might become confused.
6317 Each event gets marked with the frame in which it occurred, so the
6318 Lisp code can tell when the switch took place by examining the events. */
6321 x_new_focus_frame (dpyinfo
, frame
)
6322 struct x_display_info
*dpyinfo
;
6323 struct frame
*frame
;
6325 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
6327 if (frame
!= dpyinfo
->x_focus_frame
)
6329 /* Set this before calling other routines, so that they see
6330 the correct value of x_focus_frame. */
6331 dpyinfo
->x_focus_frame
= frame
;
6333 if (old_focus
&& old_focus
->auto_lower
)
6334 x_lower_frame (old_focus
);
6337 selected_frame
= frame
;
6338 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
6340 Fselect_window (selected_frame
->selected_window
);
6341 choose_minibuf_frame ();
6344 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
6345 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
6347 pending_autoraise_frame
= 0;
6350 x_frame_rehighlight (dpyinfo
);
6353 /* Handle FocusIn and FocusOut state changes for FRAME.
6354 If FRAME has focus and there exists more than one frame, puts
6355 an FOCUS_IN_EVENT into BUFP.
6356 Returns number of events inserted into BUFP. */
6359 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
, numchars
)
6362 struct x_display_info
*dpyinfo
;
6363 struct frame
*frame
;
6364 struct input_event
*bufp
;
6369 if (type
== FocusIn
)
6371 if (dpyinfo
->x_focus_event_frame
!= frame
)
6373 x_new_focus_frame (dpyinfo
, frame
);
6374 dpyinfo
->x_focus_event_frame
= frame
;
6376 /* Don't stop displaying the initial startup message
6377 for a switch-frame event we don't need. */
6379 && GC_NILP (Vterminal_frame
)
6380 && GC_CONSP (Vframe_list
)
6381 && !GC_NILP (XCDR (Vframe_list
)))
6383 bufp
->kind
= FOCUS_IN_EVENT
;
6384 XSETFRAME (bufp
->frame_or_window
, frame
);
6392 frame
->output_data
.x
->focus_state
|= state
;
6395 if (FRAME_XIC (frame
))
6396 XSetICFocus (FRAME_XIC (frame
));
6399 else if (type
== FocusOut
)
6401 frame
->output_data
.x
->focus_state
&= ~state
;
6403 if (dpyinfo
->x_focus_event_frame
== frame
)
6405 dpyinfo
->x_focus_event_frame
= 0;
6406 x_new_focus_frame (dpyinfo
, 0);
6410 if (FRAME_XIC (frame
))
6411 XUnsetICFocus (FRAME_XIC (frame
));
6418 /* The focus may have changed. Figure out if it is a real focus change,
6419 by checking both FocusIn/Out and Enter/LeaveNotify events.
6421 Returns number of events inserted into BUFP. */
6424 x_detect_focus_change (dpyinfo
, event
, bufp
, numchars
)
6425 struct x_display_info
*dpyinfo
;
6427 struct input_event
*bufp
;
6430 struct frame
*frame
;
6433 frame
= x_top_window_to_frame (dpyinfo
, event
->xany
.window
);
6434 if (! frame
) return nr_events
;
6436 switch (event
->type
)
6440 if (event
->xcrossing
.detail
!= NotifyInferior
6441 && event
->xcrossing
.focus
6442 && ! (frame
->output_data
.x
->focus_state
& FOCUS_EXPLICIT
))
6443 nr_events
= x_focus_changed ((event
->type
== EnterNotify
6444 ? FocusIn
: FocusOut
),
6454 nr_events
= x_focus_changed (event
->type
,
6455 (event
->xfocus
.detail
== NotifyPointer
6456 ? FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
6468 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6471 x_mouse_leave (dpyinfo
)
6472 struct x_display_info
*dpyinfo
;
6474 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
6477 /* The focus has changed, or we have redirected a frame's focus to
6478 another frame (this happens when a frame uses a surrogate
6479 mini-buffer frame). Shift the highlight as appropriate.
6481 The FRAME argument doesn't necessarily have anything to do with which
6482 frame is being highlighted or un-highlighted; we only use it to find
6483 the appropriate X display info. */
6486 XTframe_rehighlight (frame
)
6487 struct frame
*frame
;
6489 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
6493 x_frame_rehighlight (dpyinfo
)
6494 struct x_display_info
*dpyinfo
;
6496 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
6498 if (dpyinfo
->x_focus_frame
)
6500 dpyinfo
->x_highlight_frame
6501 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
6502 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
6503 : dpyinfo
->x_focus_frame
);
6504 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
6506 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
6507 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
6511 dpyinfo
->x_highlight_frame
= 0;
6513 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
6516 frame_unhighlight (old_highlight
);
6517 if (dpyinfo
->x_highlight_frame
)
6518 frame_highlight (dpyinfo
->x_highlight_frame
);
6524 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6526 /* Initialize mode_switch_bit and modifier_meaning. */
6528 x_find_modifier_meanings (dpyinfo
)
6529 struct x_display_info
*dpyinfo
;
6531 int min_code
, max_code
;
6534 XModifierKeymap
*mods
;
6536 dpyinfo
->meta_mod_mask
= 0;
6537 dpyinfo
->shift_lock_mask
= 0;
6538 dpyinfo
->alt_mod_mask
= 0;
6539 dpyinfo
->super_mod_mask
= 0;
6540 dpyinfo
->hyper_mod_mask
= 0;
6543 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
6545 min_code
= dpyinfo
->display
->min_keycode
;
6546 max_code
= dpyinfo
->display
->max_keycode
;
6549 syms
= XGetKeyboardMapping (dpyinfo
->display
,
6550 min_code
, max_code
- min_code
+ 1,
6552 mods
= XGetModifierMapping (dpyinfo
->display
);
6554 /* Scan the modifier table to see which modifier bits the Meta and
6555 Alt keysyms are on. */
6557 int row
, col
; /* The row and column in the modifier table. */
6559 for (row
= 3; row
< 8; row
++)
6560 for (col
= 0; col
< mods
->max_keypermod
; col
++)
6563 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
6565 /* Zeroes are used for filler. Skip them. */
6569 /* Are any of this keycode's keysyms a meta key? */
6573 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
6575 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
6581 dpyinfo
->meta_mod_mask
|= (1 << row
);
6586 dpyinfo
->alt_mod_mask
|= (1 << row
);
6591 dpyinfo
->hyper_mod_mask
|= (1 << row
);
6596 dpyinfo
->super_mod_mask
|= (1 << row
);
6600 /* Ignore this if it's not on the lock modifier. */
6601 if ((1 << row
) == LockMask
)
6602 dpyinfo
->shift_lock_mask
= LockMask
;
6610 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6611 if (! dpyinfo
->meta_mod_mask
)
6613 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
6614 dpyinfo
->alt_mod_mask
= 0;
6617 /* If some keys are both alt and meta,
6618 make them just meta, not alt. */
6619 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
6621 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
6624 XFree ((char *) syms
);
6625 XFreeModifiermap (mods
);
6628 /* Convert between the modifier bits X uses and the modifier bits
6632 x_x_to_emacs_modifiers (dpyinfo
, state
)
6633 struct x_display_info
*dpyinfo
;
6636 EMACS_UINT mod_meta
= meta_modifier
;
6637 EMACS_UINT mod_alt
= alt_modifier
;
6638 EMACS_UINT mod_hyper
= hyper_modifier
;
6639 EMACS_UINT mod_super
= super_modifier
;
6642 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
6643 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
6644 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
6645 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
6646 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
6647 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
6648 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
6649 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
6652 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
6653 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
6654 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
6655 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
6656 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
6657 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
6661 x_emacs_to_x_modifiers (dpyinfo
, state
)
6662 struct x_display_info
*dpyinfo
;
6665 EMACS_UINT mod_meta
= meta_modifier
;
6666 EMACS_UINT mod_alt
= alt_modifier
;
6667 EMACS_UINT mod_hyper
= hyper_modifier
;
6668 EMACS_UINT mod_super
= super_modifier
;
6672 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
6673 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
6674 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
6675 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
6676 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
6677 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
6678 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
6679 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
6682 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
6683 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
6684 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
6685 | ((state
& shift_modifier
) ? ShiftMask
: 0)
6686 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
6687 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
6690 /* Convert a keysym to its name. */
6693 x_get_keysym_name (keysym
)
6699 value
= XKeysymToString (keysym
);
6707 /* Mouse clicks and mouse movement. Rah. */
6709 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6710 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6711 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6712 not force the value into range. */
6715 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
6717 register int pix_x
, pix_y
;
6718 register int *x
, *y
;
6722 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6723 even for negative values. */
6725 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
6727 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
6729 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
6730 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
6734 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
6735 bounds
->height
= f
->output_data
.x
->line_height
;
6736 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
6737 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
6744 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
6745 pix_x
= FRAME_WINDOW_WIDTH (f
);
6749 else if (pix_y
> f
->height
)
6758 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6759 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6760 can't tell the positions because W's display is not up to date,
6764 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
6767 int *frame_x
, *frame_y
;
6771 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
6772 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
6774 if (display_completed
)
6776 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6777 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
6778 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
6784 *frame_x
+= glyph
->pixel_width
;
6792 *frame_y
= *frame_x
= 0;
6796 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6797 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6802 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6804 If the event is a button press, then note that we have grabbed
6808 construct_mouse_click (result
, event
, f
)
6809 struct input_event
*result
;
6810 XButtonEvent
*event
;
6813 /* Make the event type NO_EVENT; we'll change that when we decide
6815 result
->kind
= MOUSE_CLICK_EVENT
;
6816 result
->code
= event
->button
- Button1
;
6817 result
->timestamp
= event
->time
;
6818 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6820 | (event
->type
== ButtonRelease
6824 XSETINT (result
->x
, event
->x
);
6825 XSETINT (result
->y
, event
->y
);
6826 XSETFRAME (result
->frame_or_window
, f
);
6832 /* Function to report a mouse movement to the mainstream Emacs code.
6833 The input handler calls this.
6835 We have received a mouse movement event, which is given in *event.
6836 If the mouse is over a different glyph than it was last time, tell
6837 the mainstream emacs code by setting mouse_moved. If not, ask for
6838 another motion event, so we can check again the next time it moves. */
6840 static XMotionEvent last_mouse_motion_event
;
6841 static Lisp_Object last_mouse_motion_frame
;
6844 note_mouse_movement (frame
, event
)
6846 XMotionEvent
*event
;
6848 last_mouse_movement_time
= event
->time
;
6849 last_mouse_motion_event
= *event
;
6850 XSETFRAME (last_mouse_motion_frame
, frame
);
6852 if (event
->window
!= FRAME_X_WINDOW (frame
))
6854 frame
->mouse_moved
= 1;
6855 last_mouse_scroll_bar
= Qnil
;
6856 note_mouse_highlight (frame
, -1, -1);
6859 /* Has the mouse moved off the glyph it was on at the last sighting? */
6860 else if (event
->x
< last_mouse_glyph
.x
6861 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6862 || event
->y
< last_mouse_glyph
.y
6863 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6865 frame
->mouse_moved
= 1;
6866 last_mouse_scroll_bar
= Qnil
;
6867 note_mouse_highlight (frame
, event
->x
, event
->y
);
6872 /************************************************************************
6874 ************************************************************************/
6876 /* Find the glyph under window-relative coordinates X/Y in window W.
6877 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6878 strings. Return in *HPOS and *VPOS the row and column number of
6879 the glyph found. Return in *AREA the glyph area containing X.
6880 Value is a pointer to the glyph found or null if X/Y is not on
6881 text, or we can't tell because W's current matrix is not up to
6884 static struct glyph
*
6885 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
6888 int *hpos
, *vpos
, *area
;
6891 struct glyph
*glyph
, *end
;
6892 struct glyph_row
*row
= NULL
;
6893 int x0
, i
, left_area_width
;
6895 /* Find row containing Y. Give up if some row is not enabled. */
6896 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6898 row
= MATRIX_ROW (w
->current_matrix
, i
);
6899 if (!row
->enabled_p
)
6901 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6908 /* Give up if Y is not in the window. */
6909 if (i
== w
->current_matrix
->nrows
)
6912 /* Get the glyph area containing X. */
6913 if (w
->pseudo_window_p
)
6920 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6921 if (x
< left_area_width
)
6923 *area
= LEFT_MARGIN_AREA
;
6926 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6929 x0
= row
->x
+ left_area_width
;
6933 *area
= RIGHT_MARGIN_AREA
;
6934 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6938 /* Find glyph containing X. */
6939 glyph
= row
->glyphs
[*area
];
6940 end
= glyph
+ row
->used
[*area
];
6943 if (x
< x0
+ glyph
->pixel_width
)
6945 if (w
->pseudo_window_p
)
6947 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
6951 x0
+= glyph
->pixel_width
;
6958 *hpos
= glyph
- row
->glyphs
[*area
];
6963 /* Convert frame-relative x/y to coordinates relative to window W.
6964 Takes pseudo-windows into account. */
6967 frame_to_window_pixel_xy (w
, x
, y
)
6971 if (w
->pseudo_window_p
)
6973 /* A pseudo-window is always full-width, and starts at the
6974 left edge of the frame, plus a frame border. */
6975 struct frame
*f
= XFRAME (w
->frame
);
6976 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6977 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6981 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6982 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6987 /* Take proper action when mouse has moved to the mode or header line
6988 or marginal area of window W, x-position X and y-position Y. Area
6989 is 1, 3, 6 or 7 for the mode line, header line, left and right
6990 marginal area respectively. X is relative to the start of the text
6991 display area of W, so the width of bitmap areas and scroll bars
6992 must be subtracted to get a position relative to the start of the
6996 note_mode_line_or_margin_highlight (w
, x
, y
, portion
)
7000 struct frame
*f
= XFRAME (w
->frame
);
7001 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7002 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
7004 Lisp_Object string
, help
, map
, pos
;
7006 if (portion
== 1 || portion
== 3)
7007 string
= mode_line_string (w
, x
, y
, portion
== 1, &charpos
);
7009 string
= marginal_area_string (w
, x
, y
, portion
, &charpos
);
7011 if (STRINGP (string
))
7013 pos
= make_number (charpos
);
7015 /* If we're on a string with `help-echo' text property, arrange
7016 for the help to be displayed. This is done by setting the
7017 global variable help_echo to the help string. */
7018 help
= Fget_text_property (pos
, Qhelp_echo
, string
);
7022 XSETWINDOW (help_echo_window
, w
);
7023 help_echo_object
= string
;
7024 help_echo_pos
= charpos
;
7027 /* Change the mouse pointer according to what is under X/Y. */
7028 map
= Fget_text_property (pos
, Qlocal_map
, string
);
7030 map
= Fget_text_property (pos
, Qkeymap
, string
);
7032 cursor
= f
->output_data
.x
->nontext_cursor
;
7035 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7039 /* Take proper action when the mouse has moved to position X, Y on
7040 frame F as regards highlighting characters that have mouse-face
7041 properties. Also de-highlighting chars where the mouse was before.
7042 X and Y can be negative or out of range. */
7045 note_mouse_highlight (f
, x
, y
)
7049 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7053 Cursor cursor
= None
;
7056 /* When a menu is active, don't highlight because this looks odd. */
7057 #ifdef USE_X_TOOLKIT
7058 if (popup_activated ())
7062 if (NILP (Vmouse_highlight
)
7063 || !f
->glyphs_initialized_p
)
7066 dpyinfo
->mouse_face_mouse_x
= x
;
7067 dpyinfo
->mouse_face_mouse_y
= y
;
7068 dpyinfo
->mouse_face_mouse_frame
= f
;
7070 if (dpyinfo
->mouse_face_defer
)
7075 dpyinfo
->mouse_face_deferred_gc
= 1;
7079 /* Which window is that in? */
7080 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
7082 /* If we were displaying active text in another window, clear that. */
7083 if (! EQ (window
, dpyinfo
->mouse_face_window
))
7084 clear_mouse_face (dpyinfo
);
7086 /* Not on a window -> return. */
7087 if (!WINDOWP (window
))
7090 /* Convert to window-relative pixel coordinates. */
7091 w
= XWINDOW (window
);
7092 frame_to_window_pixel_xy (w
, &x
, &y
);
7094 /* Handle tool-bar window differently since it doesn't display a
7096 if (EQ (window
, f
->tool_bar_window
))
7098 note_tool_bar_highlight (f
, x
, y
);
7102 /* Mouse is on the mode, header line or margin? */
7103 if (portion
== 1 || portion
== 3 || portion
== 6 || portion
== 7)
7105 note_mode_line_or_margin_highlight (w
, x
, y
, portion
);
7110 cursor
= f
->output_data
.x
->horizontal_drag_cursor
;
7112 cursor
= f
->output_data
.x
->text_cursor
;
7114 /* Are we in a window whose display is up to date?
7115 And verify the buffer's text has not changed. */
7116 b
= XBUFFER (w
->buffer
);
7117 if (/* Within text portion of the window. */
7119 && EQ (w
->window_end_valid
, w
->buffer
)
7120 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
7121 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
7123 int hpos
, vpos
, pos
, i
, area
;
7124 struct glyph
*glyph
;
7126 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
7127 Lisp_Object
*overlay_vec
= NULL
;
7129 struct buffer
*obuf
;
7130 int obegv
, ozv
, same_region
;
7132 /* Find the glyph under X/Y. */
7133 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
7135 /* Clear mouse face if X/Y not over text. */
7137 || area
!= TEXT_AREA
7138 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
7140 if (clear_mouse_face (dpyinfo
))
7145 pos
= glyph
->charpos
;
7146 object
= glyph
->object
;
7147 if (!STRINGP (object
) && !BUFFERP (object
))
7150 /* If we get an out-of-range value, return now; avoid an error. */
7151 if (BUFFERP (object
) && pos
> BUF_Z (b
))
7154 /* Make the window's buffer temporarily current for
7155 overlays_at and compute_char_face. */
7156 obuf
= current_buffer
;
7163 /* Is this char mouse-active or does it have help-echo? */
7164 position
= make_number (pos
);
7166 if (BUFFERP (object
))
7168 /* Put all the overlays we want in a vector in overlay_vec.
7169 Store the length in len. If there are more than 10, make
7170 enough space for all, and try again. */
7172 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7173 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
7174 if (noverlays
> len
)
7177 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
7178 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
7181 /* Sort overlays into increasing priority order. */
7182 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
7187 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
7188 && vpos
>= dpyinfo
->mouse_face_beg_row
7189 && vpos
<= dpyinfo
->mouse_face_end_row
7190 && (vpos
> dpyinfo
->mouse_face_beg_row
7191 || hpos
>= dpyinfo
->mouse_face_beg_col
)
7192 && (vpos
< dpyinfo
->mouse_face_end_row
7193 || hpos
< dpyinfo
->mouse_face_end_col
7194 || dpyinfo
->mouse_face_past_end
));
7199 /* Check mouse-face highlighting. */
7201 /* If there exists an overlay with mouse-face overlapping
7202 the one we are currently highlighting, we have to
7203 check if we enter the overlapping overlay, and then
7204 highlight only that. */
7205 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
7206 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
7208 /* Find the highest priority overlay that has a mouse-face
7211 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
7213 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
7214 if (!NILP (mouse_face
))
7215 overlay
= overlay_vec
[i
];
7218 /* If we're actually highlighting the same overlay as
7219 before, there's no need to do that again. */
7221 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
7222 goto check_help_echo
;
7224 dpyinfo
->mouse_face_overlay
= overlay
;
7226 /* Clear the display of the old active region, if any. */
7227 if (clear_mouse_face (dpyinfo
))
7230 /* If no overlay applies, get a text property. */
7232 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
7234 /* Handle the overlay case. */
7235 if (!NILP (overlay
))
7237 /* Find the range of text around this char that
7238 should be active. */
7239 Lisp_Object before
, after
;
7242 before
= Foverlay_start (overlay
);
7243 after
= Foverlay_end (overlay
);
7244 /* Record this as the current active region. */
7245 fast_find_position (w
, XFASTINT (before
),
7246 &dpyinfo
->mouse_face_beg_col
,
7247 &dpyinfo
->mouse_face_beg_row
,
7248 &dpyinfo
->mouse_face_beg_x
,
7249 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7251 dpyinfo
->mouse_face_past_end
7252 = !fast_find_position (w
, XFASTINT (after
),
7253 &dpyinfo
->mouse_face_end_col
,
7254 &dpyinfo
->mouse_face_end_row
,
7255 &dpyinfo
->mouse_face_end_x
,
7256 &dpyinfo
->mouse_face_end_y
, Qnil
);
7257 dpyinfo
->mouse_face_window
= window
;
7258 dpyinfo
->mouse_face_face_id
7259 = face_at_buffer_position (w
, pos
, 0, 0,
7260 &ignore
, pos
+ 1, 1);
7262 /* Display it as active. */
7263 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7266 /* Handle the text property case. */
7267 else if (!NILP (mouse_face
) && BUFFERP (object
))
7269 /* Find the range of text around this char that
7270 should be active. */
7271 Lisp_Object before
, after
, beginning
, end
;
7274 beginning
= Fmarker_position (w
->start
);
7275 end
= make_number (BUF_Z (XBUFFER (object
))
7276 - XFASTINT (w
->window_end_pos
));
7278 = Fprevious_single_property_change (make_number (pos
+ 1),
7282 = Fnext_single_property_change (position
, Qmouse_face
,
7285 /* Record this as the current active region. */
7286 fast_find_position (w
, XFASTINT (before
),
7287 &dpyinfo
->mouse_face_beg_col
,
7288 &dpyinfo
->mouse_face_beg_row
,
7289 &dpyinfo
->mouse_face_beg_x
,
7290 &dpyinfo
->mouse_face_beg_y
, Qnil
);
7291 dpyinfo
->mouse_face_past_end
7292 = !fast_find_position (w
, XFASTINT (after
),
7293 &dpyinfo
->mouse_face_end_col
,
7294 &dpyinfo
->mouse_face_end_row
,
7295 &dpyinfo
->mouse_face_end_x
,
7296 &dpyinfo
->mouse_face_end_y
, Qnil
);
7297 dpyinfo
->mouse_face_window
= window
;
7299 if (BUFFERP (object
))
7300 dpyinfo
->mouse_face_face_id
7301 = face_at_buffer_position (w
, pos
, 0, 0,
7302 &ignore
, pos
+ 1, 1);
7304 /* Display it as active. */
7305 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7308 else if (!NILP (mouse_face
) && STRINGP (object
))
7313 b
= Fprevious_single_property_change (make_number (pos
+ 1),
7316 e
= Fnext_single_property_change (position
, Qmouse_face
,
7319 b
= make_number (0);
7321 e
= make_number (SCHARS (object
) - 1);
7322 fast_find_string_pos (w
, XINT (b
), object
,
7323 &dpyinfo
->mouse_face_beg_col
,
7324 &dpyinfo
->mouse_face_beg_row
,
7325 &dpyinfo
->mouse_face_beg_x
,
7326 &dpyinfo
->mouse_face_beg_y
, 0);
7327 fast_find_string_pos (w
, XINT (e
), object
,
7328 &dpyinfo
->mouse_face_end_col
,
7329 &dpyinfo
->mouse_face_end_row
,
7330 &dpyinfo
->mouse_face_end_x
,
7331 &dpyinfo
->mouse_face_end_y
, 1);
7332 dpyinfo
->mouse_face_past_end
= 0;
7333 dpyinfo
->mouse_face_window
= window
;
7334 dpyinfo
->mouse_face_face_id
7335 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
7337 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7340 else if (STRINGP (object
) && NILP (mouse_face
))
7342 /* A string which doesn't have mouse-face, but
7343 the text ``under'' it might have. */
7344 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
7345 int start
= MATRIX_ROW_START_CHARPOS (r
);
7347 pos
= string_buffer_position (w
, object
, start
);
7349 mouse_face
= get_char_property_and_overlay (make_number (pos
),
7353 if (!NILP (mouse_face
) && !NILP (overlay
))
7355 Lisp_Object before
= Foverlay_start (overlay
);
7356 Lisp_Object after
= Foverlay_end (overlay
);
7359 /* Note that we might not be able to find position
7360 BEFORE in the glyph matrix if the overlay is
7361 entirely covered by a `display' property. In
7362 this case, we overshoot. So let's stop in
7363 the glyph matrix before glyphs for OBJECT. */
7364 fast_find_position (w
, XFASTINT (before
),
7365 &dpyinfo
->mouse_face_beg_col
,
7366 &dpyinfo
->mouse_face_beg_row
,
7367 &dpyinfo
->mouse_face_beg_x
,
7368 &dpyinfo
->mouse_face_beg_y
,
7371 dpyinfo
->mouse_face_past_end
7372 = !fast_find_position (w
, XFASTINT (after
),
7373 &dpyinfo
->mouse_face_end_col
,
7374 &dpyinfo
->mouse_face_end_row
,
7375 &dpyinfo
->mouse_face_end_x
,
7376 &dpyinfo
->mouse_face_end_y
,
7378 dpyinfo
->mouse_face_window
= window
;
7379 dpyinfo
->mouse_face_face_id
7380 = face_at_buffer_position (w
, pos
, 0, 0,
7381 &ignore
, pos
+ 1, 1);
7383 /* Display it as active. */
7384 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
7392 /* Look for a `help-echo' property. */
7394 Lisp_Object help
, overlay
;
7396 /* Check overlays first. */
7397 help
= overlay
= Qnil
;
7398 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
7400 overlay
= overlay_vec
[i
];
7401 help
= Foverlay_get (overlay
, Qhelp_echo
);
7407 help_echo_window
= window
;
7408 help_echo_object
= overlay
;
7409 help_echo_pos
= pos
;
7413 Lisp_Object object
= glyph
->object
;
7414 int charpos
= glyph
->charpos
;
7416 /* Try text properties. */
7417 if (STRINGP (object
)
7419 && charpos
< SCHARS (object
))
7421 help
= Fget_text_property (make_number (charpos
),
7422 Qhelp_echo
, object
);
7425 /* If the string itself doesn't specify a help-echo,
7426 see if the buffer text ``under'' it does. */
7428 = MATRIX_ROW (w
->current_matrix
, vpos
);
7429 int start
= MATRIX_ROW_START_CHARPOS (r
);
7430 int pos
= string_buffer_position (w
, object
, start
);
7433 help
= Fget_char_property (make_number (pos
),
7434 Qhelp_echo
, w
->buffer
);
7443 else if (BUFFERP (object
)
7446 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
7452 help_echo_window
= window
;
7453 help_echo_object
= object
;
7454 help_echo_pos
= charpos
;
7461 current_buffer
= obuf
;
7467 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7471 redo_mouse_highlight ()
7473 if (!NILP (last_mouse_motion_frame
)
7474 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
7475 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
7476 last_mouse_motion_event
.x
,
7477 last_mouse_motion_event
.y
);
7482 /***********************************************************************
7484 ***********************************************************************/
7486 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
7487 struct glyph
**, int *, int *, int *));
7489 /* Tool-bar item index of the item on which a mouse button was pressed
7492 static int last_tool_bar_item
;
7495 /* Get information about the tool-bar item at position X/Y on frame F.
7496 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7497 the current matrix of the tool-bar window of F, or NULL if not
7498 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7499 item in F->tool_bar_items. Value is
7501 -1 if X/Y is not on a tool-bar item
7502 0 if X/Y is on the same item that was highlighted before.
7506 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
7509 struct glyph
**glyph
;
7510 int *hpos
, *vpos
, *prop_idx
;
7512 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7513 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7516 /* Find the glyph under X/Y. */
7517 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
7521 /* Get the start of this tool-bar item's properties in
7522 f->tool_bar_items. */
7523 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
7526 /* Is mouse on the highlighted item? */
7527 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
7528 && *vpos
>= dpyinfo
->mouse_face_beg_row
7529 && *vpos
<= dpyinfo
->mouse_face_end_row
7530 && (*vpos
> dpyinfo
->mouse_face_beg_row
7531 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
7532 && (*vpos
< dpyinfo
->mouse_face_end_row
7533 || *hpos
< dpyinfo
->mouse_face_end_col
7534 || dpyinfo
->mouse_face_past_end
))
7541 /* Handle mouse button event on the tool-bar of frame F, at
7542 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7546 x_handle_tool_bar_click (f
, button_event
)
7548 XButtonEvent
*button_event
;
7550 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7551 struct window
*w
= XWINDOW (f
->tool_bar_window
);
7552 int hpos
, vpos
, prop_idx
;
7553 struct glyph
*glyph
;
7554 Lisp_Object enabled_p
;
7555 int x
= button_event
->x
;
7556 int y
= button_event
->y
;
7558 /* If not on the highlighted tool-bar item, return. */
7559 frame_to_window_pixel_xy (w
, &x
, &y
);
7560 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
7563 /* If item is disabled, do nothing. */
7564 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7565 if (NILP (enabled_p
))
7568 if (button_event
->type
== ButtonPress
)
7570 /* Show item in pressed state. */
7571 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
7572 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
7573 last_tool_bar_item
= prop_idx
;
7577 Lisp_Object key
, frame
;
7578 struct input_event event
;
7580 /* Show item in released state. */
7581 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
7582 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
7584 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
7586 XSETFRAME (frame
, f
);
7587 event
.kind
= TOOL_BAR_EVENT
;
7588 event
.frame_or_window
= frame
;
7590 kbd_buffer_store_event (&event
);
7592 event
.kind
= TOOL_BAR_EVENT
;
7593 event
.frame_or_window
= frame
;
7595 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
7596 button_event
->state
);
7597 kbd_buffer_store_event (&event
);
7598 last_tool_bar_item
= -1;
7603 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7604 tool-bar window-relative coordinates X/Y. Called from
7605 note_mouse_highlight. */
7608 note_tool_bar_highlight (f
, x
, y
)
7612 Lisp_Object window
= f
->tool_bar_window
;
7613 struct window
*w
= XWINDOW (window
);
7614 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7616 struct glyph
*glyph
;
7617 struct glyph_row
*row
;
7619 Lisp_Object enabled_p
;
7621 enum draw_glyphs_face draw
;
7622 int mouse_down_p
, rc
;
7624 /* Function note_mouse_highlight is called with negative x(y
7625 values when mouse moves outside of the frame. */
7626 if (x
<= 0 || y
<= 0)
7628 clear_mouse_face (dpyinfo
);
7632 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
7635 /* Not on tool-bar item. */
7636 clear_mouse_face (dpyinfo
);
7642 clear_mouse_face (dpyinfo
);
7644 /* Mouse is down, but on different tool-bar item? */
7645 mouse_down_p
= (dpyinfo
->grabbed
7646 && f
== last_mouse_frame
7647 && FRAME_LIVE_P (f
));
7649 && last_tool_bar_item
!= prop_idx
)
7652 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
7653 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
7655 /* If tool-bar item is not enabled, don't highlight it. */
7656 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7657 if (!NILP (enabled_p
))
7659 /* Compute the x-position of the glyph. In front and past the
7660 image is a space. We include this is the highlighted area. */
7661 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
7662 for (i
= x
= 0; i
< hpos
; ++i
)
7663 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
7665 /* Record this as the current active region. */
7666 dpyinfo
->mouse_face_beg_col
= hpos
;
7667 dpyinfo
->mouse_face_beg_row
= vpos
;
7668 dpyinfo
->mouse_face_beg_x
= x
;
7669 dpyinfo
->mouse_face_beg_y
= row
->y
;
7670 dpyinfo
->mouse_face_past_end
= 0;
7672 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
7673 dpyinfo
->mouse_face_end_row
= vpos
;
7674 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
7675 dpyinfo
->mouse_face_end_y
= row
->y
;
7676 dpyinfo
->mouse_face_window
= window
;
7677 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
7679 /* Display it as active. */
7680 show_mouse_face (dpyinfo
, draw
);
7681 dpyinfo
->mouse_face_image_state
= draw
;
7686 /* Set help_echo to a help string to display for this tool-bar item.
7687 XTread_socket does the rest. */
7688 help_echo_object
= help_echo_window
= Qnil
;
7690 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
7691 if (NILP (help_echo
))
7692 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
7697 /* Find the glyph matrix position of buffer position CHARPOS in window
7698 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7699 current glyphs must be up to date. If CHARPOS is above window
7700 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7701 of last line in W. In the row containing CHARPOS, stop before glyphs
7702 having STOP as object. */
7704 #if 0 /* This is a version of fast_find_position that's more correct
7705 in the presence of hscrolling, for example. I didn't install
7706 it right away because the problem fixed is minor, it failed
7707 in 20.x as well, and I think it's too risky to install
7708 so near the release of 21.1. 2001-09-25 gerd. */
7711 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
7714 int *hpos
, *vpos
, *x
, *y
;
7717 struct glyph_row
*row
, *first
;
7718 struct glyph
*glyph
, *end
;
7719 int i
, past_end
= 0;
7721 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7722 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
7725 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
7727 *x
= *y
= *hpos
= *vpos
= 0;
7732 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
7739 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7741 glyph
= row
->glyphs
[TEXT_AREA
];
7742 end
= glyph
+ row
->used
[TEXT_AREA
];
7744 /* Skip over glyphs not having an object at the start of the row.
7745 These are special glyphs like truncation marks on terminal
7747 if (row
->displays_text_p
)
7749 && INTEGERP (glyph
->object
)
7750 && !EQ (stop
, glyph
->object
)
7751 && glyph
->charpos
< 0)
7753 *x
+= glyph
->pixel_width
;
7758 && !INTEGERP (glyph
->object
)
7759 && !EQ (stop
, glyph
->object
)
7760 && (!BUFFERP (glyph
->object
)
7761 || glyph
->charpos
< charpos
))
7763 *x
+= glyph
->pixel_width
;
7767 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
7774 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
7777 int *hpos
, *vpos
, *x
, *y
;
7782 int maybe_next_line_p
= 0;
7783 int line_start_position
;
7784 int yb
= window_text_bottom_y (w
);
7785 struct glyph_row
*row
, *best_row
;
7786 int row_vpos
, best_row_vpos
;
7789 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7790 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
7794 if (row
->used
[TEXT_AREA
])
7795 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
7797 line_start_position
= 0;
7799 if (line_start_position
> pos
)
7801 /* If the position sought is the end of the buffer,
7802 don't include the blank lines at the bottom of the window. */
7803 else if (line_start_position
== pos
7804 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
7806 maybe_next_line_p
= 1;
7809 else if (line_start_position
> 0)
7812 best_row_vpos
= row_vpos
;
7815 if (row
->y
+ row
->height
>= yb
)
7822 /* Find the right column within BEST_ROW. */
7824 current_x
= best_row
->x
;
7825 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
7827 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
7828 int charpos
= glyph
->charpos
;
7830 if (BUFFERP (glyph
->object
))
7835 *vpos
= best_row_vpos
;
7840 else if (charpos
> pos
)
7843 else if (EQ (glyph
->object
, stop
))
7848 current_x
+= glyph
->pixel_width
;
7851 /* If we're looking for the end of the buffer,
7852 and we didn't find it in the line we scanned,
7853 use the start of the following line. */
7854 if (maybe_next_line_p
)
7859 current_x
= best_row
->x
;
7862 *vpos
= best_row_vpos
;
7863 *hpos
= lastcol
+ 1;
7872 /* Find the position of the glyph for position POS in OBJECT in
7873 window W's current matrix, and return in *X, *Y the pixel
7874 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7876 RIGHT_P non-zero means return the position of the right edge of the
7877 glyph, RIGHT_P zero means return the left edge position.
7879 If no glyph for POS exists in the matrix, return the position of
7880 the glyph with the next smaller position that is in the matrix, if
7881 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7882 exists in the matrix, return the position of the glyph with the
7883 next larger position in OBJECT.
7885 Value is non-zero if a glyph was found. */
7888 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
7892 int *hpos
, *vpos
, *x
, *y
;
7895 int yb
= window_text_bottom_y (w
);
7896 struct glyph_row
*r
;
7897 struct glyph
*best_glyph
= NULL
;
7898 struct glyph_row
*best_row
= NULL
;
7901 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
7902 r
->enabled_p
&& r
->y
< yb
;
7905 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
7906 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
7909 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
7910 if (EQ (g
->object
, object
))
7912 if (g
->charpos
== pos
)
7919 else if (best_glyph
== NULL
7920 || ((abs (g
->charpos
- pos
)
7921 < abs (best_glyph
->charpos
- pos
))
7924 : g
->charpos
> pos
)))
7938 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
7942 *x
+= best_glyph
->pixel_width
;
7947 *vpos
= best_row
- w
->current_matrix
->rows
;
7950 return best_glyph
!= NULL
;
7954 /* Display the active region described by mouse_face_*
7955 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7958 show_mouse_face (dpyinfo
, draw
)
7959 struct x_display_info
*dpyinfo
;
7960 enum draw_glyphs_face draw
;
7962 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
7963 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7965 if (/* If window is in the process of being destroyed, don't bother
7967 w
->current_matrix
!= NULL
7968 /* Don't update mouse highlight if hidden */
7969 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
7970 /* Recognize when we are called to operate on rows that don't exist
7971 anymore. This can happen when a window is split. */
7972 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
7974 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
7975 struct glyph_row
*row
, *first
, *last
;
7977 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
7978 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
7980 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
7982 int start_hpos
, end_hpos
, start_x
;
7984 /* For all but the first row, the highlight starts at column 0. */
7987 start_hpos
= dpyinfo
->mouse_face_beg_col
;
7988 start_x
= dpyinfo
->mouse_face_beg_x
;
7997 end_hpos
= dpyinfo
->mouse_face_end_col
;
7999 end_hpos
= row
->used
[TEXT_AREA
];
8001 if (end_hpos
> start_hpos
)
8003 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
8004 start_hpos
, end_hpos
, draw
, 0);
8007 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
8011 /* When we've written over the cursor, arrange for it to
8012 be displayed again. */
8013 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
8014 x_display_cursor (w
, 1,
8015 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
8016 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
8019 /* Change the mouse cursor. */
8020 if (draw
== DRAW_NORMAL_TEXT
)
8021 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8022 f
->output_data
.x
->text_cursor
);
8023 else if (draw
== DRAW_MOUSE_FACE
)
8024 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8025 f
->output_data
.x
->cross_cursor
);
8027 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8028 f
->output_data
.x
->nontext_cursor
);
8031 /* Clear out the mouse-highlighted active region.
8032 Redraw it un-highlighted first. Value is non-zero if mouse
8033 face was actually drawn unhighlighted. */
8036 clear_mouse_face (dpyinfo
)
8037 struct x_display_info
*dpyinfo
;
8041 if (!NILP (dpyinfo
->mouse_face_window
))
8043 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
8047 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8048 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8049 dpyinfo
->mouse_face_window
= Qnil
;
8050 dpyinfo
->mouse_face_overlay
= Qnil
;
8055 /* Clear any mouse-face on window W. This function is part of the
8056 redisplay interface, and is called from try_window_id and similar
8057 functions to ensure the mouse-highlight is off. */
8060 x_clear_mouse_face (w
)
8063 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
8067 XSETWINDOW (window
, w
);
8068 if (EQ (window
, dpyinfo
->mouse_face_window
))
8069 clear_mouse_face (dpyinfo
);
8074 /* Just discard the mouse face information for frame F, if any.
8075 This is used when the size of F is changed. */
8078 cancel_mouse_face (f
)
8082 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8084 window
= dpyinfo
->mouse_face_window
;
8085 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
8087 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8088 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8089 dpyinfo
->mouse_face_window
= Qnil
;
8094 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
8097 /* Try to determine frame pixel position and size of the glyph under
8098 frame pixel coordinates X/Y on frame F . Return the position and
8099 size in *RECT. Value is non-zero if we could compute these
8103 glyph_rect (f
, x
, y
, rect
)
8109 int part
, found
= 0;
8111 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
8114 struct window
*w
= XWINDOW (window
);
8115 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
8116 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
8118 frame_to_window_pixel_xy (w
, &x
, &y
);
8120 for (; !found
&& r
< end
&& r
->enabled_p
; ++r
)
8123 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
8124 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
8127 for (gx
= r
->x
; !found
&& g
< end
; gx
+= g
->pixel_width
, ++g
)
8130 rect
->width
= g
->pixel_width
;
8131 rect
->height
= r
->height
;
8132 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
8133 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
8143 /* Return the current position of the mouse.
8144 *FP should be a frame which indicates which display to ask about.
8146 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
8147 and *PART to the frame, window, and scroll bar part that the mouse
8148 is over. Set *X and *Y to the portion and whole of the mouse's
8149 position on the scroll bar.
8151 If the mouse movement started elsewhere, set *FP to the frame the
8152 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
8155 Set *TIME to the server time-stamp for the time at which the mouse
8156 was at this position.
8158 Don't store anything if we don't have a valid set of values to report.
8160 This clears the mouse_moved flag, so we can wait for the next mouse
8164 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
8167 Lisp_Object
*bar_window
;
8168 enum scroll_bar_part
*part
;
8170 unsigned long *time
;
8176 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
8177 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
8183 Window dummy_window
;
8186 Lisp_Object frame
, tail
;
8188 /* Clear the mouse-moved flag for every frame on this display. */
8189 FOR_EACH_FRAME (tail
, frame
)
8190 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
8191 XFRAME (frame
)->mouse_moved
= 0;
8193 last_mouse_scroll_bar
= Qnil
;
8195 /* Figure out which root window we're on. */
8196 XQueryPointer (FRAME_X_DISPLAY (*fp
),
8197 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
8199 /* The root window which contains the pointer. */
8202 /* Trash which we can't trust if the pointer is on
8203 a different screen. */
8206 /* The position on that root window. */
8209 /* More trash we can't trust. */
8212 /* Modifier keys and pointer buttons, about which
8214 (unsigned int *) &dummy
);
8216 /* Now we have a position on the root; find the innermost window
8217 containing the pointer. */
8221 int parent_x
= 0, parent_y
= 0;
8226 /* XTranslateCoordinates can get errors if the window
8227 structure is changing at the same time this function
8228 is running. So at least we must not crash from them. */
8230 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
8232 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
8233 && FRAME_LIVE_P (last_mouse_frame
))
8235 /* If mouse was grabbed on a frame, give coords for that frame
8236 even if the mouse is now outside it. */
8237 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
8239 /* From-window, to-window. */
8240 root
, FRAME_X_WINDOW (last_mouse_frame
),
8242 /* From-position, to-position. */
8243 root_x
, root_y
, &win_x
, &win_y
,
8247 f1
= last_mouse_frame
;
8253 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
8255 /* From-window, to-window. */
8258 /* From-position, to-position. */
8259 root_x
, root_y
, &win_x
, &win_y
,
8264 if (child
== None
|| child
== win
)
8272 /* Now we know that:
8273 win is the innermost window containing the pointer
8274 (XTC says it has no child containing the pointer),
8275 win_x and win_y are the pointer's position in it
8276 (XTC did this the last time through), and
8277 parent_x and parent_y are the pointer's position in win's parent.
8278 (They are what win_x and win_y were when win was child.
8279 If win is the root window, it has no parent, and
8280 parent_{x,y} are invalid, but that's okay, because we'll
8281 never use them in that case.) */
8283 /* Is win one of our frames? */
8284 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
8286 #ifdef USE_X_TOOLKIT
8287 /* If we end up with the menu bar window, say it's not
8290 && f1
->output_data
.x
->menubar_widget
8291 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
8293 #endif /* USE_X_TOOLKIT */
8296 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
8299 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
8301 /* If not, is it one of our scroll bars? */
8304 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
8308 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8314 if (f1
== 0 && insist
> 0)
8315 f1
= SELECTED_FRAME ();
8319 /* Ok, we found a frame. Store all the values.
8320 last_mouse_glyph is a rectangle used to reduce the
8321 generation of mouse events. To not miss any motion
8322 events, we must divide the frame into rectangles of the
8323 size of the smallest character that could be displayed
8324 on it, i.e. into the same rectangles that matrices on
8325 the frame are divided into. */
8327 int width
, height
, gx
, gy
;
8330 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
8331 last_mouse_glyph
= rect
;
8334 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
8335 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
8339 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8340 round down even for negative values. */
8345 gx
= (gx
+ width
- 1) / width
* width
;
8346 gy
= (gy
+ height
- 1) / height
* height
;
8348 last_mouse_glyph
.width
= width
;
8349 last_mouse_glyph
.height
= height
;
8350 last_mouse_glyph
.x
= gx
;
8351 last_mouse_glyph
.y
= gy
;
8357 XSETINT (*x
, win_x
);
8358 XSETINT (*y
, win_y
);
8359 *time
= last_mouse_movement_time
;
8368 #ifdef USE_X_TOOLKIT
8370 /* Atimer callback function for TIMER. Called every 0.1s to process
8371 Xt timeouts, if needed. We must avoid calling XtAppPending as
8372 much as possible because that function does an implicit XFlush
8373 that slows us down. */
8376 x_process_timeouts (timer
)
8377 struct atimer
*timer
;
8379 if (toolkit_scroll_bar_interaction
|| popup_activated_flag
)
8382 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
8383 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
8388 #endif /* USE_X_TOOLKIT */
8391 /* Scroll bar support. */
8393 /* Given an X window ID, find the struct scroll_bar which manages it.
8394 This can be called in GC, so we have to make sure to strip off mark
8397 static struct scroll_bar
*
8398 x_window_to_scroll_bar (window_id
)
8403 for (tail
= Vframe_list
;
8404 XGCTYPE (tail
) == Lisp_Cons
;
8407 Lisp_Object frame
, bar
, condemned
;
8409 frame
= XCAR (tail
);
8410 /* All elements of Vframe_list should be frames. */
8411 if (! GC_FRAMEP (frame
))
8414 /* Scan this frame's scroll bar list for a scroll bar with the
8416 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
8417 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
8418 /* This trick allows us to search both the ordinary and
8419 condemned scroll bar lists with one loop. */
8420 ! GC_NILP (bar
) || (bar
= condemned
,
8423 bar
= XSCROLL_BAR (bar
)->next
)
8424 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
8425 return XSCROLL_BAR (bar
);
8432 #if defined USE_LUCID
8434 /* Return the Lucid menu bar WINDOW is part of. Return null
8435 if WINDOW is not part of a menu bar. */
8438 x_window_to_menu_bar (window
)
8443 for (tail
= Vframe_list
;
8444 XGCTYPE (tail
) == Lisp_Cons
;
8447 Lisp_Object frame
= XCAR (tail
);
8448 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
8450 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
8457 #endif /* USE_LUCID */
8460 /************************************************************************
8462 ************************************************************************/
8464 #ifdef USE_TOOLKIT_SCROLL_BARS
8466 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
8467 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
8468 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
8469 struct scroll_bar
*));
8470 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
8474 /* Id of action hook installed for scroll bars. */
8476 static XtActionHookId action_hook_id
;
8478 /* Lisp window being scrolled. Set when starting to interact with
8479 a toolkit scroll bar, reset to nil when ending the interaction. */
8481 static Lisp_Object window_being_scrolled
;
8483 /* Last scroll bar part sent in xm_scroll_callback. */
8485 static int last_scroll_bar_part
;
8487 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8488 that movements of 1/20 of the screen size are mapped to up/down. */
8490 static Boolean xaw3d_arrow_scroll
;
8492 /* Whether the drag scrolling maintains the mouse at the top of the
8493 thumb. If not, resizing the thumb needs to be done more carefully
8494 to avoid jerkyness. */
8496 static Boolean xaw3d_pick_top
;
8499 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8500 bars are used.. The hook is responsible for detecting when
8501 the user ends an interaction with the scroll bar, and generates
8502 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
8505 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
8508 XtPointer client_data
;
8512 Cardinal
*num_params
;
8518 scroll_bar_p
= XmIsScrollBar (widget
);
8519 end_action
= "Release";
8520 #else /* !USE_MOTIF i.e. use Xaw */
8521 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
8522 end_action
= "EndScroll";
8523 #endif /* USE_MOTIF */
8526 && strcmp (action_name
, end_action
) == 0
8527 && WINDOWP (window_being_scrolled
))
8531 x_send_scroll_bar_event (window_being_scrolled
,
8532 scroll_bar_end_scroll
, 0, 0);
8533 w
= XWINDOW (window_being_scrolled
);
8534 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
8535 window_being_scrolled
= Qnil
;
8536 last_scroll_bar_part
= -1;
8538 /* Xt timeouts no longer needed. */
8539 toolkit_scroll_bar_interaction
= 0;
8543 /* A vector of windows used for communication between
8544 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8546 static struct window
**scroll_bar_windows
;
8547 static int scroll_bar_windows_size
;
8550 /* Send a client message with message type Xatom_Scrollbar for a
8551 scroll action to the frame of WINDOW. PART is a value identifying
8552 the part of the scroll bar that was clicked on. PORTION is the
8553 amount to scroll of a whole of WHOLE. */
8556 x_send_scroll_bar_event (window
, part
, portion
, whole
)
8558 int part
, portion
, whole
;
8561 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
8562 struct window
*w
= XWINDOW (window
);
8563 struct frame
*f
= XFRAME (w
->frame
);
8568 /* Construct a ClientMessage event to send to the frame. */
8569 ev
->type
= ClientMessage
;
8570 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
8571 ev
->display
= FRAME_X_DISPLAY (f
);
8572 ev
->window
= FRAME_X_WINDOW (f
);
8575 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8576 not enough to store a pointer or Lisp_Object on a 64 bit system.
8577 So, store the window in scroll_bar_windows and pass the index
8578 into that array in the event. */
8579 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
8580 if (scroll_bar_windows
[i
] == NULL
)
8583 if (i
== scroll_bar_windows_size
)
8585 int new_size
= max (10, 2 * scroll_bar_windows_size
);
8586 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
8587 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
8589 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
8591 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
8592 scroll_bar_windows_size
= new_size
;
8595 scroll_bar_windows
[i
] = w
;
8596 ev
->data
.l
[0] = (long) i
;
8597 ev
->data
.l
[1] = (long) part
;
8598 ev
->data
.l
[2] = (long) 0;
8599 ev
->data
.l
[3] = (long) portion
;
8600 ev
->data
.l
[4] = (long) whole
;
8602 /* Make Xt timeouts work while the scroll bar is active. */
8603 toolkit_scroll_bar_interaction
= 1;
8605 /* Setting the event mask to zero means that the message will
8606 be sent to the client that created the window, and if that
8607 window no longer exists, no event will be sent. */
8608 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
8613 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8617 x_scroll_bar_to_input_event (event
, ievent
)
8619 struct input_event
*ievent
;
8621 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
8626 w
= scroll_bar_windows
[ev
->data
.l
[0]];
8627 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
8629 XSETWINDOW (window
, w
);
8630 f
= XFRAME (w
->frame
);
8632 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
8633 ievent
->frame_or_window
= window
;
8635 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
8636 ievent
->part
= ev
->data
.l
[1];
8637 ievent
->code
= ev
->data
.l
[2];
8638 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
8639 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
8640 ievent
->modifiers
= 0;
8646 /* Minimum and maximum values used for Motif scroll bars. */
8649 #define XM_SB_MAX 10000000
8650 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8653 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8654 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8655 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
8658 xm_scroll_callback (widget
, client_data
, call_data
)
8660 XtPointer client_data
, call_data
;
8662 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8663 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
8664 int part
= -1, whole
= 0, portion
= 0;
8668 case XmCR_DECREMENT
:
8669 bar
->dragging
= Qnil
;
8670 part
= scroll_bar_up_arrow
;
8673 case XmCR_INCREMENT
:
8674 bar
->dragging
= Qnil
;
8675 part
= scroll_bar_down_arrow
;
8678 case XmCR_PAGE_DECREMENT
:
8679 bar
->dragging
= Qnil
;
8680 part
= scroll_bar_above_handle
;
8683 case XmCR_PAGE_INCREMENT
:
8684 bar
->dragging
= Qnil
;
8685 part
= scroll_bar_below_handle
;
8689 bar
->dragging
= Qnil
;
8690 part
= scroll_bar_to_top
;
8693 case XmCR_TO_BOTTOM
:
8694 bar
->dragging
= Qnil
;
8695 part
= scroll_bar_to_bottom
;
8701 int dragging_down_p
= (INTEGERP (bar
->dragging
)
8702 && XINT (bar
->dragging
) <= cs
->value
);
8704 /* Get the slider size. */
8706 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
8709 whole
= XM_SB_RANGE
- slider_size
;
8710 portion
= min (cs
->value
- XM_SB_MIN
, whole
);
8711 part
= scroll_bar_handle
;
8712 bar
->dragging
= make_number (cs
->value
);
8716 case XmCR_VALUE_CHANGED
:
8722 window_being_scrolled
= bar
->window
;
8723 last_scroll_bar_part
= part
;
8724 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
8729 #else /* !USE_MOTIF, i.e. Xaw. */
8732 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8733 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8734 scroll bar struct. CALL_DATA is a pointer to a float saying where
8738 xaw_jump_callback (widget
, client_data
, call_data
)
8740 XtPointer client_data
, call_data
;
8742 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8743 float top
= *(float *) call_data
;
8745 int whole
, portion
, height
;
8748 /* Get the size of the thumb, a value between 0 and 1. */
8750 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
8754 portion
= shown
< 1 ? top
* whole
: 0;
8756 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
8757 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8758 the bottom, so we force the scrolling whenever we see that we're
8759 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8760 we try to ensure that we always stay two pixels away from the
8762 part
= scroll_bar_down_arrow
;
8764 part
= scroll_bar_handle
;
8766 window_being_scrolled
= bar
->window
;
8767 bar
->dragging
= make_number (portion
);
8768 last_scroll_bar_part
= part
;
8769 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
8773 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8774 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8775 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8776 the scroll bar. CALL_DATA is an integer specifying the action that
8777 has taken place. It's magnitude is in the range 0..height of the
8778 scroll bar. Negative values mean scroll towards buffer start.
8779 Values < height of scroll bar mean line-wise movement. */
8782 xaw_scroll_callback (widget
, client_data
, call_data
)
8784 XtPointer client_data
, call_data
;
8786 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
8787 int position
= (int) call_data
;
8791 /* Get the height of the scroll bar. */
8793 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
8796 if (abs (position
) >= height
)
8797 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
8799 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8800 it maps line-movement to call_data = max(5, height/20). */
8801 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
8802 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
8804 part
= scroll_bar_move_ratio
;
8806 window_being_scrolled
= bar
->window
;
8807 bar
->dragging
= Qnil
;
8808 last_scroll_bar_part
= part
;
8809 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
8813 #endif /* not USE_MOTIF */
8816 /* Create the widget for scroll bar BAR on frame F. Record the widget
8817 and X window of the scroll bar in BAR. */
8820 x_create_toolkit_scroll_bar (f
, bar
)
8822 struct scroll_bar
*bar
;
8828 char *scroll_bar_name
= "verticalScrollBar";
8829 unsigned long pixel
;
8834 /* Set resources. Create the widget. */
8835 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8836 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
8837 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
8838 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
8839 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
8840 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
8841 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
8843 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8846 XtSetArg (av
[ac
], XmNforeground
, pixel
);
8850 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8853 XtSetArg (av
[ac
], XmNbackground
, pixel
);
8857 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
8858 scroll_bar_name
, av
, ac
);
8860 /* Add one callback for everything that can happen. */
8861 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
8863 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
8865 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
8867 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
8869 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
8871 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
8873 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
8876 /* Realize the widget. Only after that is the X window created. */
8877 XtRealizeWidget (widget
);
8879 /* Set the cursor to an arrow. I didn't find a resource to do that.
8880 And I'm wondering why it hasn't an arrow cursor by default. */
8881 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
8882 f
->output_data
.x
->nontext_cursor
);
8884 #else /* !USE_MOTIF i.e. use Xaw */
8886 /* Set resources. Create the widget. The background of the
8887 Xaw3d scroll bar widget is a little bit light for my taste.
8888 We don't alter it here to let users change it according
8889 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8890 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8891 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
8892 /* For smoother scrolling with Xaw3d -sm */
8893 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8895 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8898 XtSetArg (av
[ac
], XtNforeground
, pixel
);
8902 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8905 XtSetArg (av
[ac
], XtNbackground
, pixel
);
8909 /* Top/bottom shadow colors. */
8911 /* Allocate them, if necessary. */
8912 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
8914 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8915 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
8916 &pixel
, 1.2, 0x8000))
8918 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
8920 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
8922 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8923 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
8924 &pixel
, 0.6, 0x4000))
8926 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
8929 /* Tell the toolkit about them. */
8930 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
8931 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
8932 /* We tried to allocate a color for the top/bottom shadow, and
8933 failed, so tell Xaw3d to use dithering instead. */
8935 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
8939 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8940 be more consistent with other emacs 3d colors, and since Xaw3d is
8941 not good at dealing with allocation failure. */
8943 /* This tells Xaw3d to use real colors instead of dithering for
8945 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
8948 /* Specify the colors. */
8949 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
8952 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
8955 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
8958 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
8963 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
8964 f
->output_data
.x
->edit_widget
, av
, ac
);
8968 char *val
= initial
;
8969 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
8970 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
8972 { /* ARROW_SCROLL */
8973 xaw3d_arrow_scroll
= True
;
8974 /* Isn't that just a personal preference ? -sm */
8975 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
8979 /* Define callbacks. */
8980 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
8981 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
8984 /* Realize the widget. Only after that is the X window created. */
8985 XtRealizeWidget (widget
);
8987 #endif /* !USE_MOTIF */
8989 /* Install an action hook that lets us detect when the user
8990 finishes interacting with a scroll bar. */
8991 if (action_hook_id
== 0)
8992 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
8994 /* Remember X window and widget in the scroll bar vector. */
8995 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
8996 xwindow
= XtWindow (widget
);
8997 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
9003 /* Set the thumb size and position of scroll bar BAR. We are currently
9004 displaying PORTION out of a whole WHOLE, and our position POSITION. */
9007 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
9008 struct scroll_bar
*bar
;
9009 int portion
, position
, whole
;
9011 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9012 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
9019 /* We use an estimate of 30 chars per line rather than the real
9020 `portion' value. This has the disadvantage that the thumb size
9021 is not very representative, but it makes our life a lot easier.
9022 Otherwise, we have to constantly adjust the thumb size, which
9023 we can't always do quickly enough: while dragging, the size of
9024 the thumb might prevent the user from dragging the thumb all the
9025 way to the end. but Motif and some versions of Xaw3d don't allow
9026 updating the thumb size while dragging. Also, even if we can update
9027 its size, the update will often happen too late.
9028 If you don't believe it, check out revision 1.650 of xterm.c to see
9029 what hoops we were going through and the still poor behavior we got. */
9030 portion
= XFASTINT (XWINDOW (bar
->window
)->height
) * 30;
9031 /* When the thumb is at the bottom, position == whole.
9032 So we need to increase `whole' to make space for the thumb. */
9039 top
= (float) position
/ whole
;
9040 shown
= (float) portion
/ whole
;
9043 if (NILP (bar
->dragging
))
9047 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
9048 is the scroll bar's maximum and MIN is the scroll bar's minimum
9050 size
= shown
* XM_SB_RANGE
;
9051 size
= min (size
, XM_SB_RANGE
);
9052 size
= max (size
, 1);
9054 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
9055 value
= top
* XM_SB_RANGE
;
9056 value
= min (value
, XM_SB_MAX
- size
);
9057 value
= max (value
, XM_SB_MIN
);
9059 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
9061 #else /* !USE_MOTIF i.e. use Xaw */
9067 top
= (float) position
/ whole
;
9068 shown
= (float) portion
/ whole
;
9072 float old_top
, old_shown
;
9074 XtVaGetValues (widget
,
9075 XtNtopOfThumb
, &old_top
,
9076 XtNshown
, &old_shown
,
9080 /* Massage the top+shown values. */
9081 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
9082 top
= max (0, min (1, top
));
9085 /* Keep two pixels available for moving the thumb down. */
9086 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
9088 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
9089 check that your system's configuration file contains a define
9090 for `NARROWPROTO'. See s/freebsd.h for an example. */
9091 if (top
!= old_top
|| shown
!= old_shown
)
9093 if (NILP (bar
->dragging
))
9094 XawScrollbarSetThumb (widget
, top
, shown
);
9098 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
9099 int scroll_mode
= 0;
9101 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
9102 if (xaw3d_arrow_scroll
)
9104 /* Xaw3d stupidly ignores resize requests while dragging
9105 so we have to make it believe it's not in dragging mode. */
9106 scroll_mode
= sb
->scrollbar
.scroll_mode
;
9107 if (scroll_mode
== 2)
9108 sb
->scrollbar
.scroll_mode
= 0;
9111 /* Try to make the scrolling a tad smoother. */
9112 if (!xaw3d_pick_top
)
9113 shown
= min (shown
, old_shown
);
9115 XawScrollbarSetThumb (widget
, top
, shown
);
9118 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
9119 sb
->scrollbar
.scroll_mode
= scroll_mode
;
9124 #endif /* !USE_MOTIF */
9129 #endif /* USE_TOOLKIT_SCROLL_BARS */
9133 /************************************************************************
9134 Scroll bars, general
9135 ************************************************************************/
9137 /* Create a scroll bar and return the scroll bar vector for it. W is
9138 the Emacs window on which to create the scroll bar. TOP, LEFT,
9139 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
9142 static struct scroll_bar
*
9143 x_scroll_bar_create (w
, top
, left
, width
, height
)
9145 int top
, left
, width
, height
;
9147 struct frame
*f
= XFRAME (w
->frame
);
9148 struct scroll_bar
*bar
9149 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
9153 #ifdef USE_TOOLKIT_SCROLL_BARS
9154 x_create_toolkit_scroll_bar (f
, bar
);
9155 #else /* not USE_TOOLKIT_SCROLL_BARS */
9157 XSetWindowAttributes a
;
9161 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
9162 if (a
.background_pixel
== -1)
9163 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
9165 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
9166 | ButtonMotionMask
| PointerMotionHintMask
9168 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
9170 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
9172 /* Clear the area of W that will serve as a scroll bar. This is
9173 for the case that a window has been split horizontally. In
9174 this case, no clear_frame is generated to reduce flickering. */
9175 if (width
> 0 && height
> 0)
9176 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9178 window_box_height (w
), False
);
9180 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9181 /* Position and size of scroll bar. */
9182 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9184 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9186 /* Border width, depth, class, and visual. */
9193 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
9195 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9197 XSETWINDOW (bar
->window
, w
);
9198 XSETINT (bar
->top
, top
);
9199 XSETINT (bar
->left
, left
);
9200 XSETINT (bar
->width
, width
);
9201 XSETINT (bar
->height
, height
);
9202 XSETINT (bar
->start
, 0);
9203 XSETINT (bar
->end
, 0);
9204 bar
->dragging
= Qnil
;
9206 /* Add bar to its frame's list of scroll bars. */
9207 bar
->next
= FRAME_SCROLL_BARS (f
);
9209 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
9210 if (!NILP (bar
->next
))
9211 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
9213 /* Map the window/widget. */
9214 #ifdef USE_TOOLKIT_SCROLL_BARS
9216 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
9217 XtConfigureWidget (scroll_bar
,
9218 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9220 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9221 max (height
, 1), 0);
9222 XtMapWidget (scroll_bar
);
9224 #else /* not USE_TOOLKIT_SCROLL_BARS */
9225 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
9226 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9233 /* Draw BAR's handle in the proper position.
9235 If the handle is already drawn from START to END, don't bother
9236 redrawing it, unless REBUILD is non-zero; in that case, always
9237 redraw it. (REBUILD is handy for drawing the handle after expose
9240 Normally, we want to constrain the start and end of the handle to
9241 fit inside its rectangle, but if the user is dragging the scroll
9242 bar handle, we want to let them drag it down all the way, so that
9243 the bar's top is as far down as it goes; otherwise, there's no way
9244 to move to the very end of the buffer. */
9246 #ifndef USE_TOOLKIT_SCROLL_BARS
9249 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
9250 struct scroll_bar
*bar
;
9254 int dragging
= ! NILP (bar
->dragging
);
9255 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9256 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9257 GC gc
= f
->output_data
.x
->normal_gc
;
9259 /* If the display is already accurate, do nothing. */
9261 && start
== XINT (bar
->start
)
9262 && end
== XINT (bar
->end
))
9268 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
9269 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9270 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9272 /* Make sure the values are reasonable, and try to preserve
9273 the distance between start and end. */
9275 int length
= end
- start
;
9279 else if (start
> top_range
)
9281 end
= start
+ length
;
9285 else if (end
> top_range
&& ! dragging
)
9289 /* Store the adjusted setting in the scroll bar. */
9290 XSETINT (bar
->start
, start
);
9291 XSETINT (bar
->end
, end
);
9293 /* Clip the end position, just for display. */
9294 if (end
> top_range
)
9297 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9298 below top positions, to make sure the handle is always at least
9299 that many pixels tall. */
9300 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
9302 /* Draw the empty space above the handle. Note that we can't clear
9303 zero-height areas; that means "clear to end of window." */
9305 x_clear_area (FRAME_X_DISPLAY (f
), w
,
9306 /* x, y, width, height, and exposures. */
9307 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9308 VERTICAL_SCROLL_BAR_TOP_BORDER
,
9309 inside_width
, start
,
9312 /* Change to proper foreground color if one is specified. */
9313 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9314 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
9315 f
->output_data
.x
->scroll_bar_foreground_pixel
);
9317 /* Draw the handle itself. */
9318 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
9319 /* x, y, width, height */
9320 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9321 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
9322 inside_width
, end
- start
);
9324 /* Restore the foreground color of the GC if we changed it above. */
9325 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9326 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
9327 f
->output_data
.x
->foreground_pixel
);
9329 /* Draw the empty space below the handle. Note that we can't
9330 clear zero-height areas; that means "clear to end of window." */
9331 if (end
< inside_height
)
9332 x_clear_area (FRAME_X_DISPLAY (f
), w
,
9333 /* x, y, width, height, and exposures. */
9334 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
9335 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
9336 inside_width
, inside_height
- end
,
9344 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9346 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9350 x_scroll_bar_remove (bar
)
9351 struct scroll_bar
*bar
;
9353 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9356 #ifdef USE_TOOLKIT_SCROLL_BARS
9357 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
9359 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
9362 /* Disassociate this scroll bar from its window. */
9363 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
9369 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9370 that we are displaying PORTION characters out of a total of WHOLE
9371 characters, starting at POSITION. If WINDOW has no scroll bar,
9375 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
9377 int portion
, whole
, position
;
9379 struct frame
*f
= XFRAME (w
->frame
);
9380 struct scroll_bar
*bar
;
9381 int top
, height
, left
, sb_left
, width
, sb_width
;
9382 int window_x
, window_y
, window_width
, window_height
;
9384 /* Get window dimensions. */
9385 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9387 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
9388 height
= window_height
;
9390 /* Compute the left edge of the scroll bar area. */
9391 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9392 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
9394 left
= XFASTINT (w
->left
);
9395 left
*= CANON_X_UNIT (f
);
9396 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
9398 /* Compute the width of the scroll bar which might be less than
9399 the width of the area reserved for the scroll bar. */
9400 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
9401 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
9405 /* Compute the left edge of the scroll bar. */
9406 #ifdef USE_TOOLKIT_SCROLL_BARS
9407 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9408 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
9410 sb_left
= left
+ (width
- sb_width
) / 2;
9412 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
9413 sb_left
= left
+ width
- sb_width
;
9418 /* Does the scroll bar exist yet? */
9419 if (NILP (w
->vertical_scroll_bar
))
9421 if (width
> 0 && height
> 0)
9424 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9425 left
, top
, width
, height
, False
);
9429 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
9433 /* It may just need to be moved and resized. */
9434 unsigned int mask
= 0;
9436 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
9440 if (sb_left
!= XINT (bar
->left
))
9442 if (top
!= XINT (bar
->top
))
9444 if (sb_width
!= XINT (bar
->width
))
9446 if (height
!= XINT (bar
->height
))
9449 #ifdef USE_TOOLKIT_SCROLL_BARS
9451 /* Since toolkit scroll bars are smaller than the space reserved
9452 for them on the frame, we have to clear "under" them. */
9453 if (width
> 0 && height
> 0)
9454 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9455 left
, top
, width
, height
, False
);
9457 /* Move/size the scroll bar widget. */
9459 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
9460 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9462 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
9463 max (height
, 1), 0);
9465 #else /* not USE_TOOLKIT_SCROLL_BARS */
9467 /* Clear areas not covered by the scroll bar because of
9468 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9469 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
9471 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9472 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9474 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9475 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9476 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
9480 /* Clear areas not covered by the scroll bar because it's not as
9481 wide as the area reserved for it. This makes sure a
9482 previous mode line display is cleared after C-x 2 C-x 1, for
9485 int area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
9486 int rest
= area_width
- sb_width
;
9487 if (rest
> 0 && height
> 0)
9489 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
9490 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9491 left
+ area_width
- rest
, top
,
9492 rest
, height
, False
);
9494 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9495 left
, top
, rest
, height
, False
);
9499 /* Move/size the scroll bar window. */
9504 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
9506 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
9508 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
9512 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9514 /* Remember new settings. */
9515 XSETINT (bar
->left
, sb_left
);
9516 XSETINT (bar
->top
, top
);
9517 XSETINT (bar
->width
, sb_width
);
9518 XSETINT (bar
->height
, height
);
9523 #ifdef USE_TOOLKIT_SCROLL_BARS
9524 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
9525 #else /* not USE_TOOLKIT_SCROLL_BARS */
9526 /* Set the scroll bar's current state, unless we're currently being
9528 if (NILP (bar
->dragging
))
9530 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
9533 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
9536 int start
= ((double) position
* top_range
) / whole
;
9537 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
9538 x_scroll_bar_set_handle (bar
, start
, end
, 0);
9541 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9543 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
9547 /* The following three hooks are used when we're doing a thorough
9548 redisplay of the frame. We don't explicitly know which scroll bars
9549 are going to be deleted, because keeping track of when windows go
9550 away is a real pain - "Can you say set-window-configuration, boys
9551 and girls?" Instead, we just assert at the beginning of redisplay
9552 that *all* scroll bars are to be removed, and then save a scroll bar
9553 from the fiery pit when we actually redisplay its window. */
9555 /* Arrange for all scroll bars on FRAME to be removed at the next call
9556 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9557 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9560 XTcondemn_scroll_bars (frame
)
9563 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9564 while (! NILP (FRAME_SCROLL_BARS (frame
)))
9567 bar
= FRAME_SCROLL_BARS (frame
);
9568 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
9569 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
9570 XSCROLL_BAR (bar
)->prev
= Qnil
;
9571 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
9572 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
9573 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
9578 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9579 Note that WINDOW isn't necessarily condemned at all. */
9582 XTredeem_scroll_bar (window
)
9583 struct window
*window
;
9585 struct scroll_bar
*bar
;
9588 /* We can't redeem this window's scroll bar if it doesn't have one. */
9589 if (NILP (window
->vertical_scroll_bar
))
9592 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
9594 /* Unlink it from the condemned list. */
9595 f
= XFRAME (WINDOW_FRAME (window
));
9596 if (NILP (bar
->prev
))
9598 /* If the prev pointer is nil, it must be the first in one of
9600 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
9601 /* It's not condemned. Everything's fine. */
9603 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
9604 window
->vertical_scroll_bar
))
9605 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
9607 /* If its prev pointer is nil, it must be at the front of
9608 one or the other! */
9612 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
9614 if (! NILP (bar
->next
))
9615 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
9617 bar
->next
= FRAME_SCROLL_BARS (f
);
9619 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
9620 if (! NILP (bar
->next
))
9621 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
9624 /* Remove all scroll bars on FRAME that haven't been saved since the
9625 last call to `*condemn_scroll_bars_hook'. */
9628 XTjudge_scroll_bars (f
)
9631 Lisp_Object bar
, next
;
9633 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
9635 /* Clear out the condemned list now so we won't try to process any
9636 more events on the hapless scroll bars. */
9637 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
9639 for (; ! NILP (bar
); bar
= next
)
9641 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
9643 x_scroll_bar_remove (b
);
9646 b
->next
= b
->prev
= Qnil
;
9649 /* Now there should be no references to the condemned scroll bars,
9650 and they should get garbage-collected. */
9654 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9655 is a no-op when using toolkit scroll bars.
9657 This may be called from a signal handler, so we have to ignore GC
9661 x_scroll_bar_expose (bar
, event
)
9662 struct scroll_bar
*bar
;
9665 #ifndef USE_TOOLKIT_SCROLL_BARS
9667 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9668 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9669 GC gc
= f
->output_data
.x
->normal_gc
;
9670 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
9674 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
9676 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9677 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
9679 /* x, y, width, height */
9681 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
9682 XINT (bar
->height
) - 1);
9686 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9689 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9690 is set to something other than NO_EVENT, it is enqueued.
9692 This may be called from a signal handler, so we have to ignore GC
9695 #ifndef USE_TOOLKIT_SCROLL_BARS
9698 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
9699 struct scroll_bar
*bar
;
9701 struct input_event
*emacs_event
;
9703 if (! GC_WINDOWP (bar
->window
))
9706 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
9707 emacs_event
->code
= event
->xbutton
.button
- Button1
;
9708 emacs_event
->modifiers
9709 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9710 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
9711 event
->xbutton
.state
)
9712 | (event
->type
== ButtonRelease
9715 emacs_event
->frame_or_window
= bar
->window
;
9716 emacs_event
->arg
= Qnil
;
9717 emacs_event
->timestamp
= event
->xbutton
.time
;
9720 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9722 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9725 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9726 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
9729 if (y
> top_range
) y
= top_range
;
9731 if (y
< XINT (bar
->start
))
9732 emacs_event
->part
= scroll_bar_above_handle
;
9733 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
9734 emacs_event
->part
= scroll_bar_handle
;
9736 emacs_event
->part
= scroll_bar_below_handle
;
9738 /* Just because the user has clicked on the handle doesn't mean
9739 they want to drag it. Lisp code needs to be able to decide
9740 whether or not we're dragging. */
9742 /* If the user has just clicked on the handle, record where they're
9744 if (event
->type
== ButtonPress
9745 && emacs_event
->part
== scroll_bar_handle
)
9746 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
9749 /* If the user has released the handle, set it to its final position. */
9750 if (event
->type
== ButtonRelease
9751 && ! NILP (bar
->dragging
))
9753 int new_start
= y
- XINT (bar
->dragging
);
9754 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
9756 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
9757 bar
->dragging
= Qnil
;
9760 /* Same deal here as the other #if 0. */
9762 /* Clicks on the handle are always reported as occurring at the top of
9764 if (emacs_event
->part
== scroll_bar_handle
)
9765 emacs_event
->x
= bar
->start
;
9767 XSETINT (emacs_event
->x
, y
);
9769 XSETINT (emacs_event
->x
, y
);
9772 XSETINT (emacs_event
->y
, top_range
);
9776 /* Handle some mouse motion while someone is dragging the scroll bar.
9778 This may be called from a signal handler, so we have to ignore GC
9782 x_scroll_bar_note_movement (bar
, event
)
9783 struct scroll_bar
*bar
;
9786 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
9788 last_mouse_movement_time
= event
->xmotion
.time
;
9791 XSETVECTOR (last_mouse_scroll_bar
, bar
);
9793 /* If we're dragging the bar, display it. */
9794 if (! GC_NILP (bar
->dragging
))
9796 /* Where should the handle be now? */
9797 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
9799 if (new_start
!= XINT (bar
->start
))
9801 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
9803 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
9808 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9810 /* Return information to the user about the current position of the mouse
9811 on the scroll bar. */
9814 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
9816 Lisp_Object
*bar_window
;
9817 enum scroll_bar_part
*part
;
9819 unsigned long *time
;
9821 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
9822 Window w
= SCROLL_BAR_X_WINDOW (bar
);
9823 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
9825 Window dummy_window
;
9827 unsigned int dummy_mask
;
9831 /* Get the mouse's position relative to the scroll bar window, and
9833 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
9835 /* Root, child, root x and root y. */
9836 &dummy_window
, &dummy_window
,
9837 &dummy_coord
, &dummy_coord
,
9839 /* Position relative to scroll bar. */
9842 /* Mouse buttons and modifier keys. */
9849 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9852 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9854 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
9856 if (! NILP (bar
->dragging
))
9857 win_y
-= XINT (bar
->dragging
);
9861 if (win_y
> top_range
)
9865 *bar_window
= bar
->window
;
9867 if (! NILP (bar
->dragging
))
9868 *part
= scroll_bar_handle
;
9869 else if (win_y
< XINT (bar
->start
))
9870 *part
= scroll_bar_above_handle
;
9871 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
9872 *part
= scroll_bar_handle
;
9874 *part
= scroll_bar_below_handle
;
9876 XSETINT (*x
, win_y
);
9877 XSETINT (*y
, top_range
);
9880 last_mouse_scroll_bar
= Qnil
;
9883 *time
= last_mouse_movement_time
;
9889 /* The screen has been cleared so we may have changed foreground or
9890 background colors, and the scroll bars may need to be redrawn.
9891 Clear out the scroll bars, and ask for expose events, so we can
9895 x_scroll_bar_clear (f
)
9898 #ifndef USE_TOOLKIT_SCROLL_BARS
9901 /* We can have scroll bars even if this is 0,
9902 if we just turned off scroll bar mode.
9903 But in that case we should not clear them. */
9904 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
9905 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
9906 bar
= XSCROLL_BAR (bar
)->next
)
9907 XClearArea (FRAME_X_DISPLAY (f
),
9908 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
9910 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9913 /* This processes Expose events from the menu-bar specific X event
9914 loop in xmenu.c. This allows to redisplay the frame if necessary
9915 when handling menu-bar or pop-up items. */
9918 process_expose_from_menu (event
)
9922 struct x_display_info
*dpyinfo
;
9923 int frame_exposed_p
= 0;
9927 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
9928 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9931 if (f
->async_visible
== 0)
9933 f
->async_visible
= 1;
9934 f
->async_iconified
= 0;
9935 f
->output_data
.x
->has_been_visible
= 1;
9936 SET_FRAME_GARBAGED (f
);
9940 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
9941 event
.xexpose
.x
, event
.xexpose
.y
,
9942 event
.xexpose
.width
, event
.xexpose
.height
);
9943 frame_exposed_p
= 1;
9948 struct scroll_bar
*bar
9949 = x_window_to_scroll_bar (event
.xexpose
.window
);
9952 x_scroll_bar_expose (bar
, &event
);
9956 return frame_exposed_p
;
9959 /* Define a queue to save up SelectionRequest events for later handling. */
9961 struct selection_event_queue
9964 struct selection_event_queue
*next
;
9967 static struct selection_event_queue
*queue
;
9969 /* Nonzero means queue up certain events--don't process them yet. */
9971 static int x_queue_selection_requests
;
9973 /* Queue up an X event *EVENT, to be processed later. */
9976 x_queue_event (f
, event
)
9980 struct selection_event_queue
*queue_tmp
9981 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
9983 if (queue_tmp
!= NULL
)
9985 queue_tmp
->event
= *event
;
9986 queue_tmp
->next
= queue
;
9991 /* Take all the queued events and put them back
9992 so that they get processed afresh. */
9995 x_unqueue_events (display
)
9998 while (queue
!= NULL
)
10000 struct selection_event_queue
*queue_tmp
= queue
;
10001 XPutBackEvent (display
, &queue_tmp
->event
);
10002 queue
= queue_tmp
->next
;
10003 xfree ((char *)queue_tmp
);
10007 /* Start queuing SelectionRequest events. */
10010 x_start_queuing_selection_requests (display
)
10013 x_queue_selection_requests
++;
10016 /* Stop queuing SelectionRequest events. */
10019 x_stop_queuing_selection_requests (display
)
10022 x_queue_selection_requests
--;
10023 x_unqueue_events (display
);
10026 /* The main X event-reading loop - XTread_socket. */
10029 /* Time stamp of enter window event. This is only used by XTread_socket,
10030 but we have to put it out here, since static variables within functions
10031 sometimes don't work. */
10033 static Time enter_timestamp
;
10036 /* This holds the state XLookupString needs to implement dead keys
10037 and other tricks known as "compose processing". _X Window System_
10038 says that a portable program can't use this, but Stephen Gildea assures
10039 me that letting the compiler initialize it to zeros will work okay.
10041 This must be defined outside of XTread_socket, for the same reasons
10042 given for enter_timestamp, above. */
10044 static XComposeStatus compose_status
;
10046 /* Record the last 100 characters stored
10047 to help debug the loss-of-chars-during-GC problem. */
10049 static int temp_index
;
10050 static short temp_buffer
[100];
10052 /* Set this to nonzero to fake an "X I/O error"
10053 on a particular display. */
10055 struct x_display_info
*XTread_socket_fake_io_error
;
10057 /* When we find no input here, we occasionally do a no-op command
10058 to verify that the X server is still running and we can still talk with it.
10059 We try all the open displays, one by one.
10060 This variable is used for cycling thru the displays. */
10062 static struct x_display_info
*next_noop_dpyinfo
;
10064 #define SET_SAVED_MENU_EVENT(size) \
10067 if (f->output_data.x->saved_menu_event == 0) \
10068 f->output_data.x->saved_menu_event \
10069 = (XEvent *) xmalloc (sizeof (XEvent)); \
10070 bcopy (&event, f->output_data.x->saved_menu_event, size); \
10071 if (numchars >= 1) \
10073 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
10074 XSETFRAME (bufp->frame_or_window, f); \
10075 bufp->arg = Qnil; \
10083 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10084 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10086 /* Read events coming from the X server.
10087 This routine is called by the SIGIO handler.
10088 We return as soon as there are no more events to be read.
10090 Events representing keys are stored in buffer BUFP,
10091 which can hold up to NUMCHARS characters.
10092 We return the number of characters stored into the buffer,
10093 thus pretending to be `read'.
10095 EXPECTED is nonzero if the caller knows input is available. */
10098 XTread_socket (sd
, bufp
, numchars
, expected
)
10100 /* register */ struct input_event
*bufp
;
10101 /* register */ int numchars
;
10108 int event_found
= 0;
10109 struct x_display_info
*dpyinfo
;
10110 struct coding_system coding
;
10112 if (interrupt_input_blocked
)
10114 interrupt_input_pending
= 1;
10118 interrupt_input_pending
= 0;
10121 /* So people can tell when we have read the available input. */
10122 input_signal_count
++;
10125 abort (); /* Don't think this happens. */
10129 /* Find the display we are supposed to read input for.
10130 It's the one communicating on descriptor SD. */
10131 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
10133 #if 0 /* This ought to be unnecessary; let's verify it. */
10135 /* If available, Xlib uses FIOSNBIO to make the socket
10136 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
10137 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
10138 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
10139 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
10140 #endif /* ! defined (FIOSNBIO) */
10143 #if 0 /* This code can't be made to work, with multiple displays,
10144 and appears not to be used on any system any more.
10145 Also keyboard.c doesn't turn O_NDELAY on and off
10146 for X connections. */
10148 #ifndef HAVE_SELECT
10149 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
10151 extern int read_alarm_should_throw
;
10152 read_alarm_should_throw
= 1;
10153 XPeekEvent (dpyinfo
->display
, &event
);
10154 read_alarm_should_throw
= 0;
10156 #endif /* HAVE_SELECT */
10160 /* For debugging, this gives a way to fake an I/O error. */
10161 if (dpyinfo
== XTread_socket_fake_io_error
)
10163 XTread_socket_fake_io_error
= 0;
10164 x_io_error_quitter (dpyinfo
->display
);
10169 count
+= x_session_check_input (bufp
, &numchars
);
10173 while (XPending (dpyinfo
->display
))
10175 XNextEvent (dpyinfo
->display
, &event
);
10179 /* Filter events for the current X input method.
10180 XFilterEvent returns non-zero if the input method has
10181 consumed the event. We pass the frame's X window to
10182 XFilterEvent because that's the one for which the IC
10184 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
10185 event
.xclient
.window
);
10186 if (XFilterEvent (&event
, f1
? FRAME_X_WINDOW (f1
) : None
))
10192 switch (event
.type
)
10194 case ClientMessage
:
10196 if (event
.xclient
.message_type
10197 == dpyinfo
->Xatom_wm_protocols
10198 && event
.xclient
.format
== 32)
10200 if (event
.xclient
.data
.l
[0]
10201 == dpyinfo
->Xatom_wm_take_focus
)
10203 /* Use x_any_window_to_frame because this
10204 could be the shell widget window
10205 if the frame has no title bar. */
10206 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
10208 /* Not quite sure this is needed -pd */
10209 if (f
&& FRAME_XIC (f
))
10210 XSetICFocus (FRAME_XIC (f
));
10212 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10213 instructs the WM to set the input focus automatically for
10214 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10215 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10216 it has set the focus. So, XSetInputFocus below is not
10219 The call to XSetInputFocus below has also caused trouble. In
10220 cases where the XSetInputFocus done by the WM and the one
10221 below are temporally close (on a fast machine), the call
10222 below can generate additional FocusIn events which confuse
10225 /* Since we set WM_TAKE_FOCUS, we must call
10226 XSetInputFocus explicitly. But not if f is null,
10227 since that might be an event for a deleted frame. */
10230 Display
*d
= event
.xclient
.display
;
10231 /* Catch and ignore errors, in case window has been
10232 iconified by a window manager such as GWM. */
10233 int count
= x_catch_errors (d
);
10234 XSetInputFocus (d
, event
.xclient
.window
,
10235 /* The ICCCM says this is
10236 the only valid choice. */
10238 event
.xclient
.data
.l
[1]);
10239 /* This is needed to detect the error
10240 if there is an error. */
10242 x_uncatch_errors (d
, count
);
10244 /* Not certain about handling scroll bars here */
10247 else if (event
.xclient
.data
.l
[0]
10248 == dpyinfo
->Xatom_wm_save_yourself
)
10250 /* Save state modify the WM_COMMAND property to
10251 something which can reinstate us. This notifies
10252 the session manager, who's looking for such a
10253 PropertyNotify. Can restart processing when
10254 a keyboard or mouse event arrives. */
10255 /* If we have a session manager, don't set this.
10256 KDE will then start two Emacsen, one for the
10257 session manager and one for this. */
10260 && ! x_session_have_connection ()
10264 f
= x_top_window_to_frame (dpyinfo
,
10265 event
.xclient
.window
);
10266 /* This is just so we only give real data once
10267 for a single Emacs process. */
10268 if (f
== SELECTED_FRAME ())
10269 XSetCommand (FRAME_X_DISPLAY (f
),
10270 event
.xclient
.window
,
10271 initial_argv
, initial_argc
);
10273 XSetCommand (FRAME_X_DISPLAY (f
),
10274 event
.xclient
.window
,
10278 else if (event
.xclient
.data
.l
[0]
10279 == dpyinfo
->Xatom_wm_delete_window
)
10282 = x_any_window_to_frame (dpyinfo
,
10283 event
.xclient
.window
);
10290 bufp
->kind
= DELETE_WINDOW_EVENT
;
10291 XSETFRAME (bufp
->frame_or_window
, f
);
10300 else if (event
.xclient
.message_type
10301 == dpyinfo
->Xatom_wm_configure_denied
)
10304 else if (event
.xclient
.message_type
10305 == dpyinfo
->Xatom_wm_window_moved
)
10309 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
10311 new_x
= event
.xclient
.data
.s
[0];
10312 new_y
= event
.xclient
.data
.s
[1];
10316 f
->output_data
.x
->left_pos
= new_x
;
10317 f
->output_data
.x
->top_pos
= new_y
;
10320 #ifdef HACK_EDITRES
10321 else if (event
.xclient
.message_type
10322 == dpyinfo
->Xatom_editres
)
10325 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
10326 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
10329 #endif /* HACK_EDITRES */
10330 else if ((event
.xclient
.message_type
10331 == dpyinfo
->Xatom_DONE
)
10332 || (event
.xclient
.message_type
10333 == dpyinfo
->Xatom_PAGE
))
10335 /* Ghostview job completed. Kill it. We could
10336 reply with "Next" if we received "Page", but we
10337 currently never do because we are interested in
10338 images, only, which should have 1 page. */
10339 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
10341 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
10342 x_kill_gs_process (pixmap
, f
);
10343 expose_frame (f
, 0, 0, 0, 0);
10345 #ifdef USE_TOOLKIT_SCROLL_BARS
10346 /* Scroll bar callbacks send a ClientMessage from which
10347 we construct an input_event. */
10348 else if (event
.xclient
.message_type
10349 == dpyinfo
->Xatom_Scrollbar
)
10351 x_scroll_bar_to_input_event (&event
, bufp
);
10352 ++bufp
, ++count
, --numchars
;
10355 #endif /* USE_TOOLKIT_SCROLL_BARS */
10361 case SelectionNotify
:
10362 #ifdef USE_X_TOOLKIT
10363 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
10365 #endif /* not USE_X_TOOLKIT */
10366 x_handle_selection_notify (&event
.xselection
);
10369 case SelectionClear
: /* Someone has grabbed ownership. */
10370 #ifdef USE_X_TOOLKIT
10371 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
10373 #endif /* USE_X_TOOLKIT */
10375 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
10380 bufp
->kind
= SELECTION_CLEAR_EVENT
;
10381 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
10382 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
10383 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
10384 bufp
->frame_or_window
= Qnil
;
10393 case SelectionRequest
: /* Someone wants our selection. */
10394 #ifdef USE_X_TOOLKIT
10395 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
10397 #endif /* USE_X_TOOLKIT */
10398 if (x_queue_selection_requests
)
10399 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
10403 XSelectionRequestEvent
*eventp
10404 = (XSelectionRequestEvent
*) &event
;
10409 bufp
->kind
= SELECTION_REQUEST_EVENT
;
10410 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
10411 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
10412 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
10413 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
10414 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
10415 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
10416 bufp
->frame_or_window
= Qnil
;
10425 case PropertyNotify
:
10426 #if 0 /* This is plain wrong. In the case that we are waiting for a
10427 PropertyNotify used as an ACK in incremental selection
10428 transfer, the property will be on the receiver's window. */
10429 #if defined USE_X_TOOLKIT
10430 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
10434 x_handle_property_notify (&event
.xproperty
);
10437 case ReparentNotify
:
10438 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
10442 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
10443 x_real_positions (f
, &x
, &y
);
10444 f
->output_data
.x
->left_pos
= x
;
10445 f
->output_data
.x
->top_pos
= y
;
10451 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
10454 x_check_fullscreen (f
);
10456 if (f
->async_visible
== 0)
10458 f
->async_visible
= 1;
10459 f
->async_iconified
= 0;
10460 f
->output_data
.x
->has_been_visible
= 1;
10461 SET_FRAME_GARBAGED (f
);
10464 expose_frame (x_window_to_frame (dpyinfo
,
10465 event
.xexpose
.window
),
10466 event
.xexpose
.x
, event
.xexpose
.y
,
10467 event
.xexpose
.width
, event
.xexpose
.height
);
10471 #ifndef USE_TOOLKIT_SCROLL_BARS
10472 struct scroll_bar
*bar
;
10474 #if defined USE_LUCID
10475 /* Submenus of the Lucid menu bar aren't widgets
10476 themselves, so there's no way to dispatch events
10477 to them. Recognize this case separately. */
10480 = x_window_to_menu_bar (event
.xexpose
.window
);
10482 xlwmenu_redisplay (widget
);
10484 #endif /* USE_LUCID */
10486 #ifdef USE_TOOLKIT_SCROLL_BARS
10487 /* Dispatch event to the widget. */
10489 #else /* not USE_TOOLKIT_SCROLL_BARS */
10490 bar
= x_window_to_scroll_bar (event
.xexpose
.window
);
10493 x_scroll_bar_expose (bar
, &event
);
10494 #ifdef USE_X_TOOLKIT
10497 #endif /* USE_X_TOOLKIT */
10498 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10502 case GraphicsExpose
: /* This occurs when an XCopyArea's
10503 source area was obscured or not
10505 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
10509 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
10510 event
.xgraphicsexpose
.width
,
10511 event
.xgraphicsexpose
.height
);
10513 #ifdef USE_X_TOOLKIT
10516 #endif /* USE_X_TOOLKIT */
10519 case NoExpose
: /* This occurs when an XCopyArea's
10520 source area was completely
10525 /* Redo the mouse-highlight after the tooltip has gone. */
10526 if (event
.xmap
.window
== tip_window
)
10529 redo_mouse_highlight ();
10532 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
10533 if (f
) /* F may no longer exist if
10534 the frame was deleted. */
10536 /* While a frame is unmapped, display generation is
10537 disabled; you don't want to spend time updating a
10538 display that won't ever be seen. */
10539 f
->async_visible
= 0;
10540 /* We can't distinguish, from the event, whether the window
10541 has become iconified or invisible. So assume, if it
10542 was previously visible, than now it is iconified.
10543 But x_make_frame_invisible clears both
10544 the visible flag and the iconified flag;
10545 and that way, we know the window is not iconified now. */
10546 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
10548 f
->async_iconified
= 1;
10550 bufp
->kind
= ICONIFY_EVENT
;
10551 XSETFRAME (bufp
->frame_or_window
, f
);
10561 if (event
.xmap
.window
== tip_window
)
10562 /* The tooltip has been drawn already. Avoid
10563 the SET_FRAME_GARBAGED below. */
10566 /* We use x_top_window_to_frame because map events can
10567 come for sub-windows and they don't mean that the
10568 frame is visible. */
10569 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
10572 f
->async_visible
= 1;
10573 f
->async_iconified
= 0;
10574 f
->output_data
.x
->has_been_visible
= 1;
10576 /* wait_reading_process_input will notice this and update
10577 the frame's display structures. */
10578 SET_FRAME_GARBAGED (f
);
10582 bufp
->kind
= DEICONIFY_EVENT
;
10583 XSETFRAME (bufp
->frame_or_window
, f
);
10589 else if (! NILP (Vframe_list
)
10590 && ! NILP (XCDR (Vframe_list
)))
10591 /* Force a redisplay sooner or later
10592 to update the frame titles
10593 in case this is the second frame. */
10594 record_asynch_buffer_change ();
10600 /* Dispatch KeyPress events when in menu. */
10601 if (popup_activated_flag
)
10604 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
10606 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10608 dpyinfo
->mouse_face_hidden
= 1;
10609 clear_mouse_face (dpyinfo
);
10612 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10615 /* Scroll bars consume key events, but we want
10616 the keys to go to the scroll bar's frame. */
10617 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
10618 event
.xkey
.window
);
10619 if (widget
&& XmIsScrollBar (widget
))
10621 widget
= XtParent (widget
);
10622 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
10625 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10629 KeySym keysym
, orig_keysym
;
10630 /* al%imercury@uunet.uu.net says that making this 81
10631 instead of 80 fixed a bug whereby meta chars made
10634 It seems that some version of XmbLookupString has
10635 a bug of not returning XBufferOverflow in
10636 status_return even if the input is too long to
10637 fit in 81 bytes. So, we must prepare sufficient
10638 bytes for copy_buffer. 513 bytes (256 chars for
10639 two-byte character set) seems to be a fairly good
10640 approximation. -- 2000.8.10 handa@etl.go.jp */
10641 unsigned char copy_buffer
[513];
10642 unsigned char *copy_bufptr
= copy_buffer
;
10643 int copy_bufsiz
= sizeof (copy_buffer
);
10645 Lisp_Object coding_system
= Qlatin_1
;
10648 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
10649 extra_keyboard_modifiers
);
10650 modifiers
= event
.xkey
.state
;
10652 /* This will have to go some day... */
10654 /* make_lispy_event turns chars into control chars.
10655 Don't do it here because XLookupString is too eager. */
10656 event
.xkey
.state
&= ~ControlMask
;
10657 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
10658 | dpyinfo
->super_mod_mask
10659 | dpyinfo
->hyper_mod_mask
10660 | dpyinfo
->alt_mod_mask
);
10662 /* In case Meta is ComposeCharacter,
10663 clear its status. According to Markus Ehrnsperger
10664 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10665 this enables ComposeCharacter to work whether or
10666 not it is combined with Meta. */
10667 if (modifiers
& dpyinfo
->meta_mod_mask
)
10668 bzero (&compose_status
, sizeof (compose_status
));
10673 Status status_return
;
10675 coding_system
= Vlocale_coding_system
;
10676 nbytes
= XmbLookupString (FRAME_XIC (f
),
10677 &event
.xkey
, copy_bufptr
,
10678 copy_bufsiz
, &keysym
,
10680 if (status_return
== XBufferOverflow
)
10682 copy_bufsiz
= nbytes
+ 1;
10683 copy_bufptr
= (char *) alloca (copy_bufsiz
);
10684 nbytes
= XmbLookupString (FRAME_XIC (f
),
10685 &event
.xkey
, copy_bufptr
,
10686 copy_bufsiz
, &keysym
,
10689 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10690 #if 0 && defined X_HAVE_UTF8_STRING
10691 else if (status_return
== XLookupKeySym
)
10692 { /* Try again but with utf-8. */
10693 coding_system
= Qutf_8
;
10694 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
10695 &event
.xkey
, copy_bufptr
,
10696 copy_bufsiz
, &keysym
,
10698 if (status_return
== XBufferOverflow
)
10700 copy_bufsiz
= nbytes
+ 1;
10701 copy_bufptr
= (char *) alloca (copy_bufsiz
);
10702 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
10705 copy_bufsiz
, &keysym
,
10711 if (status_return
== XLookupNone
)
10713 else if (status_return
== XLookupChars
)
10718 else if (status_return
!= XLookupKeySym
10719 && status_return
!= XLookupBoth
)
10723 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
10724 copy_bufsiz
, &keysym
,
10727 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
10728 copy_bufsiz
, &keysym
,
10732 orig_keysym
= keysym
;
10736 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
10737 || keysym
== XK_Delete
10738 #ifdef XK_ISO_Left_Tab
10739 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
10741 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
10742 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
10743 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
10745 /* This recognizes the "extended function keys".
10746 It seems there's no cleaner way.
10747 Test IsModifierKey to avoid handling mode_switch
10749 || ((unsigned) (keysym
) >= XK_Select
10750 && (unsigned)(keysym
) < XK_KP_Space
)
10752 #ifdef XK_dead_circumflex
10753 || orig_keysym
== XK_dead_circumflex
10755 #ifdef XK_dead_grave
10756 || orig_keysym
== XK_dead_grave
10758 #ifdef XK_dead_tilde
10759 || orig_keysym
== XK_dead_tilde
10761 #ifdef XK_dead_diaeresis
10762 || orig_keysym
== XK_dead_diaeresis
10764 #ifdef XK_dead_macron
10765 || orig_keysym
== XK_dead_macron
10767 #ifdef XK_dead_degree
10768 || orig_keysym
== XK_dead_degree
10770 #ifdef XK_dead_acute
10771 || orig_keysym
== XK_dead_acute
10773 #ifdef XK_dead_cedilla
10774 || orig_keysym
== XK_dead_cedilla
10776 #ifdef XK_dead_breve
10777 || orig_keysym
== XK_dead_breve
10779 #ifdef XK_dead_ogonek
10780 || orig_keysym
== XK_dead_ogonek
10782 #ifdef XK_dead_caron
10783 || orig_keysym
== XK_dead_caron
10785 #ifdef XK_dead_doubleacute
10786 || orig_keysym
== XK_dead_doubleacute
10788 #ifdef XK_dead_abovedot
10789 || orig_keysym
== XK_dead_abovedot
10791 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
10792 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
10793 /* Any "vendor-specific" key is ok. */
10794 || (orig_keysym
& (1 << 28))
10795 || (keysym
!= NoSymbol
&& nbytes
== 0))
10796 && ! (IsModifierKey (orig_keysym
)
10798 #ifdef XK_Mode_switch
10799 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
10802 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
10804 #endif /* not HAVE_X11R5 */
10805 /* The symbols from XK_ISO_Lock to
10806 XK_ISO_Last_Group_Lock doesn't have real
10807 modifiers but should be treated similarly
10808 to Mode_switch by Emacs. */
10809 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10810 || ((unsigned)(orig_keysym
) >= XK_ISO_Lock
10811 && (unsigned)(orig_keysym
) <= XK_ISO_Last_Group_Lock
)
10815 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
10817 temp_buffer
[temp_index
++] = keysym
;
10818 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
10819 bufp
->code
= keysym
;
10820 XSETFRAME (bufp
->frame_or_window
, f
);
10823 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
10825 bufp
->timestamp
= event
.xkey
.time
;
10830 else if (numchars
> nbytes
)
10836 /* The input should be decoded with `coding_system'
10837 which depends on which X*LookupString function
10838 we used just above and the locale. */
10839 setup_coding_system (coding_system
, &coding
);
10840 coding
.src_multibyte
= 0;
10841 coding
.dst_multibyte
= 1;
10842 /* The input is converted to events, thus we can't
10843 handle composition. Anyway, there's no XIM that
10844 gives us composition information. */
10845 coding
.composing
= COMPOSITION_DISABLED
;
10847 for (i
= 0; i
< nbytes
; i
++)
10849 if (temp_index
== (sizeof temp_buffer
10852 temp_buffer
[temp_index
++] = copy_bufptr
[i
];
10856 /* Decode the input data. */
10860 require
= decoding_buffer_size (&coding
, nbytes
);
10861 p
= (unsigned char *) alloca (require
);
10862 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
10863 /* We explicitely disable composition
10864 handling because key data should
10865 not contain any composition
10867 coding
.composing
= COMPOSITION_DISABLED
;
10868 decode_coding (&coding
, copy_bufptr
, p
,
10870 nbytes
= coding
.produced
;
10871 nchars
= coding
.produced_char
;
10875 /* Convert the input data to a sequence of
10876 character events. */
10877 for (i
= 0; i
< nbytes
; i
+= len
)
10879 if (nchars
== nbytes
)
10880 c
= copy_bufptr
[i
], len
= 1;
10882 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
10885 bufp
->kind
= (SINGLE_BYTE_CHAR_P (c
)
10886 ? ASCII_KEYSTROKE_EVENT
10887 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
10889 XSETFRAME (bufp
->frame_or_window
, f
);
10892 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
10894 bufp
->timestamp
= event
.xkey
.time
;
10899 numchars
-= nchars
;
10901 if (keysym
== NoSymbol
)
10911 /* Don't dispatch this event since XtDispatchEvent calls
10912 XFilterEvent, and two calls in a row may freeze the
10921 /* Don't dispatch this event since XtDispatchEvent calls
10922 XFilterEvent, and two calls in a row may freeze the
10933 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
10936 bufp
+= n
, count
+= n
, numchars
-= n
;
10939 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10942 if (event
.xcrossing
.focus
)
10944 /* Avoid nasty pop/raise loops. */
10945 if (f
&& (!(f
->auto_raise
)
10946 || !(f
->auto_lower
)
10947 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
10949 x_new_focus_frame (dpyinfo
, f
);
10950 enter_timestamp
= event
.xcrossing
.time
;
10953 else if (f
== dpyinfo
->x_focus_frame
)
10954 x_new_focus_frame (dpyinfo
, 0);
10957 /* EnterNotify counts as mouse movement,
10958 so update things that depend on mouse position. */
10959 if (f
&& !f
->output_data
.x
->hourglass_p
)
10960 note_mouse_movement (f
, &event
.xmotion
);
10968 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
10971 bufp
+= n
, count
+= n
, numchars
-= n
;
10981 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
10984 bufp
+= n
, count
+= n
, numchars
-= n
;
10988 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10991 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10993 /* If we move outside the frame, then we're
10994 certainly no longer on any text in the frame. */
10995 clear_mouse_face (dpyinfo
);
10996 dpyinfo
->mouse_face_mouse_frame
= 0;
10999 /* Generate a nil HELP_EVENT to cancel a help-echo.
11000 Do it only if there's something to cancel.
11001 Otherwise, the startup message is cleared when
11002 the mouse leaves the frame. */
11003 if (any_help_event_p
)
11008 XSETFRAME (frame
, f
);
11010 n
= gen_help_event (bufp
, numchars
,
11011 Qnil
, frame
, Qnil
, Qnil
, 0);
11012 bufp
+= n
, count
+= n
, numchars
-= n
;
11022 n
= x_detect_focus_change (dpyinfo
, &event
, bufp
, numchars
);
11025 bufp
+= n
, count
+= n
, numchars
-= n
;
11033 previous_help_echo
= help_echo
;
11034 help_echo
= help_echo_object
= help_echo_window
= Qnil
;
11035 help_echo_pos
= -1;
11037 if (dpyinfo
->grabbed
&& last_mouse_frame
11038 && FRAME_LIVE_P (last_mouse_frame
))
11039 f
= last_mouse_frame
;
11041 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
11043 if (dpyinfo
->mouse_face_hidden
)
11045 dpyinfo
->mouse_face_hidden
= 0;
11046 clear_mouse_face (dpyinfo
);
11052 /* Generate SELECT_WINDOW_EVENTs when needed. */
11053 if (mouse_autoselect_window
)
11055 Lisp_Object window
;
11058 window
= window_from_coordinates (f
,
11059 event
.xmotion
.x
, event
.xmotion
.y
,
11062 /* Window will be selected only when it is not selected now and
11063 last mouse movement event was not in it. Minibuffer window
11064 will be selected iff it is active. */
11065 if (WINDOWP(window
)
11066 && !EQ (window
, last_window
)
11067 && !EQ (window
, selected_window
)
11070 bufp
->kind
= SELECT_WINDOW_EVENT
;
11071 bufp
->frame_or_window
= window
;
11073 ++bufp
, ++count
, --numchars
;
11076 last_window
=window
;
11078 note_mouse_movement (f
, &event
.xmotion
);
11082 #ifndef USE_TOOLKIT_SCROLL_BARS
11083 struct scroll_bar
*bar
11084 = x_window_to_scroll_bar (event
.xmotion
.window
);
11087 x_scroll_bar_note_movement (bar
, &event
);
11088 #endif /* USE_TOOLKIT_SCROLL_BARS */
11090 /* If we move outside the frame, then we're
11091 certainly no longer on any text in the frame. */
11092 clear_mouse_face (dpyinfo
);
11095 /* If the contents of the global variable help_echo
11096 has changed, generate a HELP_EVENT. */
11097 if (!NILP (help_echo
)
11098 || !NILP (previous_help_echo
))
11104 XSETFRAME (frame
, f
);
11108 any_help_event_p
= 1;
11109 n
= gen_help_event (bufp
, numchars
, help_echo
, frame
,
11110 help_echo_window
, help_echo_object
,
11112 bufp
+= n
, count
+= n
, numchars
-= n
;
11118 case ConfigureNotify
:
11119 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
11122 #ifndef USE_X_TOOLKIT
11123 /* If there is a pending resize for fullscreen, don't
11124 do this one, the right one will come later.
11125 The toolkit version doesn't seem to need this, but we
11126 need to reset it below. */
11128 ((f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WAIT
)
11129 && FRAME_NEW_WIDTH (f
) != 0);
11130 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
11131 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
11135 /* In the toolkit version, change_frame_size
11136 is called by the code that handles resizing
11137 of the EmacsFrame widget. */
11139 /* Even if the number of character rows and columns has
11140 not changed, the font size may have changed, so we need
11141 to check the pixel dimensions as well. */
11142 if (columns
!= f
->width
11143 || rows
!= f
->height
11144 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
11145 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
11147 change_frame_size (f
, rows
, columns
, 0, 1, 0);
11148 SET_FRAME_GARBAGED (f
);
11149 cancel_mouse_face (f
);
11153 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
11154 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
11156 /* What we have now is the position of Emacs's own window.
11157 Convert that to the position of the window manager window. */
11158 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
11159 &f
->output_data
.x
->top_pos
);
11161 x_check_fullscreen_move(f
);
11162 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WAIT
)
11163 f
->output_data
.x
->want_fullscreen
&=
11164 ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
11166 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
11167 xic_set_statusarea (f
);
11170 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
11172 /* Since the WM decorations come below top_pos now,
11173 we must put them below top_pos in the future. */
11174 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11175 x_wm_set_size_hint (f
, (long) 0, 0);
11181 case ButtonRelease
:
11183 /* If we decide we want to generate an event to be seen
11184 by the rest of Emacs, we put it here. */
11185 struct input_event emacs_event
;
11186 int tool_bar_p
= 0;
11188 emacs_event
.kind
= NO_EVENT
;
11189 bzero (&compose_status
, sizeof (compose_status
));
11191 if (dpyinfo
->grabbed
11192 && last_mouse_frame
11193 && FRAME_LIVE_P (last_mouse_frame
))
11194 f
= last_mouse_frame
;
11196 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
11200 /* Is this in the tool-bar? */
11201 if (WINDOWP (f
->tool_bar_window
)
11202 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
11204 Lisp_Object window
;
11207 x
= event
.xbutton
.x
;
11208 y
= event
.xbutton
.y
;
11211 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
11212 if (EQ (window
, f
->tool_bar_window
))
11214 x_handle_tool_bar_click (f
, &event
.xbutton
);
11220 if (!dpyinfo
->x_focus_frame
11221 || f
== dpyinfo
->x_focus_frame
)
11222 construct_mouse_click (&emacs_event
, &event
, f
);
11226 #ifndef USE_TOOLKIT_SCROLL_BARS
11227 struct scroll_bar
*bar
11228 = x_window_to_scroll_bar (event
.xbutton
.window
);
11231 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
11232 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11235 if (event
.type
== ButtonPress
)
11237 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
11238 last_mouse_frame
= f
;
11239 /* Ignore any mouse motion that happened
11240 before this event; any subsequent mouse-movement
11241 Emacs events should reflect only motion after
11242 the ButtonPress. */
11244 f
->mouse_moved
= 0;
11247 last_tool_bar_item
= -1;
11251 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
11254 if (numchars
>= 1 && emacs_event
.kind
!= NO_EVENT
)
11256 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
11262 #ifdef USE_X_TOOLKIT
11263 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
11264 /* For a down-event in the menu bar,
11265 don't pass it to Xt right now.
11266 Instead, save it away
11267 and we will pass it to Xt from kbd_buffer_get_event.
11268 That way, we can run some Lisp code first. */
11269 if (f
&& event
.type
== ButtonPress
11270 /* Verify the event is really within the menu bar
11271 and not just sent to it due to grabbing. */
11272 && event
.xbutton
.x
>= 0
11273 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
11274 && event
.xbutton
.y
>= 0
11275 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
11276 && event
.xbutton
.same_screen
)
11278 SET_SAVED_BUTTON_EVENT
;
11279 XSETFRAME (last_mouse_press_frame
, f
);
11281 else if (event
.type
== ButtonPress
)
11283 last_mouse_press_frame
= Qnil
;
11287 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11288 but I am trying to be cautious. */
11289 else if (event
.type
== ButtonRelease
)
11291 if (!NILP (last_mouse_press_frame
))
11293 f
= XFRAME (last_mouse_press_frame
);
11294 if (f
->output_data
.x
)
11295 SET_SAVED_BUTTON_EVENT
;
11300 #endif /* USE_MOTIF */
11303 #endif /* USE_X_TOOLKIT */
11307 case CirculateNotify
:
11310 case CirculateRequest
:
11313 case VisibilityNotify
:
11316 case MappingNotify
:
11317 /* Someone has changed the keyboard mapping - update the
11319 switch (event
.xmapping
.request
)
11321 case MappingModifier
:
11322 x_find_modifier_meanings (dpyinfo
);
11323 /* This is meant to fall through. */
11324 case MappingKeyboard
:
11325 XRefreshKeyboardMapping (&event
.xmapping
);
11331 #ifdef USE_X_TOOLKIT
11333 XtDispatchEvent (&event
);
11335 #endif /* USE_X_TOOLKIT */
11343 /* On some systems, an X bug causes Emacs to get no more events
11344 when the window is destroyed. Detect that. (1994.) */
11347 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11348 One XNOOP in 100 loops will make Emacs terminate.
11349 B. Bretthauer, 1994 */
11351 if (x_noop_count
>= 100)
11355 if (next_noop_dpyinfo
== 0)
11356 next_noop_dpyinfo
= x_display_list
;
11358 XNoOp (next_noop_dpyinfo
->display
);
11360 /* Each time we get here, cycle through the displays now open. */
11361 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
11365 /* If the focus was just given to an auto-raising frame,
11367 /* ??? This ought to be able to handle more than one such frame. */
11368 if (pending_autoraise_frame
)
11370 x_raise_frame (pending_autoraise_frame
);
11371 pending_autoraise_frame
= 0;
11382 /***********************************************************************
11384 ***********************************************************************/
11386 /* Notice when the text cursor of window W has been completely
11387 overwritten by a drawing operation that outputs glyphs in AREA
11388 starting at X0 and ending at X1 in the line starting at Y0 and
11389 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11390 the rest of the line after X0 has been written. Y coordinates
11391 are window-relative. */
11394 notice_overwritten_cursor (w
, area
, x0
, x1
, y0
, y1
)
11396 enum glyph_row_area area
;
11397 int x0
, y0
, x1
, y1
;
11399 if (area
== TEXT_AREA
&& w
->phys_cursor_on_p
)
11401 int cx0
= w
->phys_cursor
.x
;
11402 int cx1
= cx0
+ w
->phys_cursor_width
;
11403 int cy0
= w
->phys_cursor
.y
;
11404 int cy1
= cy0
+ w
->phys_cursor_height
;
11406 if (x0
<= cx0
&& (x1
< 0 || x1
>= cx1
))
11408 /* The cursor image will be completely removed from the
11409 screen if the output area intersects the cursor area in
11410 y-direction. When we draw in [y0 y1[, and some part of
11411 the cursor is at y < y0, that part must have been drawn
11412 before. When scrolling, the cursor is erased before
11413 actually scrolling, so we don't come here. When not
11414 scrolling, the rows above the old cursor row must have
11415 changed, and in this case these rows must have written
11416 over the cursor image.
11418 Likewise if part of the cursor is below y1, with the
11419 exception of the cursor being in the first blank row at
11420 the buffer and window end because update_text_area
11421 doesn't draw that row. (Except when it does, but
11422 that's handled in update_text_area.) */
11424 if (((y0
>= cy0
&& y0
< cy1
) || (y1
> cy0
&& y1
< cy1
))
11425 && w
->current_matrix
->rows
[w
->phys_cursor
.vpos
].displays_text_p
)
11426 w
->phys_cursor_on_p
= 0;
11432 /* Set clipping for output in glyph row ROW. W is the window in which
11433 we operate. GC is the graphics context to set clipping in.
11434 WHOLE_LINE_P non-zero means include the areas used for truncation
11435 mark display and alike in the clipping rectangle.
11437 ROW may be a text row or, e.g., a mode line. Text rows must be
11438 clipped to the interior of the window dedicated to text display,
11439 mode lines must be clipped to the whole window. */
11442 x_clip_to_row (w
, row
, gc
, whole_line_p
)
11444 struct glyph_row
*row
;
11448 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
11449 XRectangle clip_rect
;
11450 int window_x
, window_y
, window_width
, window_height
;
11452 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
11454 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
11455 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
11456 clip_rect
.y
= max (clip_rect
.y
, window_y
);
11457 clip_rect
.width
= window_width
;
11458 clip_rect
.height
= row
->visible_height
;
11460 /* If clipping to the whole line, including trunc marks, extend
11461 the rectangle to the left and increase its width. */
11464 clip_rect
.x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
11465 clip_rect
.width
+= FRAME_X_FRINGE_WIDTH (f
);
11468 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
11472 /* Draw a hollow box cursor on window W in glyph row ROW. */
11475 x_draw_hollow_cursor (w
, row
)
11477 struct glyph_row
*row
;
11479 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
11480 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11481 Display
*dpy
= FRAME_X_DISPLAY (f
);
11484 struct glyph
*cursor_glyph
;
11487 /* Compute frame-relative coordinates from window-relative
11489 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
11490 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
11491 + row
->ascent
- w
->phys_cursor_ascent
);
11492 h
= row
->height
- 1;
11494 /* Get the glyph the cursor is on. If we can't tell because
11495 the current matrix is invalid or such, give up. */
11496 cursor_glyph
= get_phys_cursor_glyph (w
);
11497 if (cursor_glyph
== NULL
)
11500 /* Compute the width of the rectangle to draw. If on a stretch
11501 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11502 rectangle as wide as the glyph, but use a canonical character
11504 wd
= cursor_glyph
->pixel_width
- 1;
11505 if (cursor_glyph
->type
== STRETCH_GLYPH
11506 && !x_stretch_cursor_p
)
11507 wd
= min (CANON_X_UNIT (f
), wd
);
11508 w
->phys_cursor_width
= wd
;
11510 /* The foreground of cursor_gc is typically the same as the normal
11511 background color, which can cause the cursor box to be invisible. */
11512 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
11513 if (dpyinfo
->scratch_cursor_gc
)
11514 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
11516 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
11517 GCForeground
, &xgcv
);
11518 gc
= dpyinfo
->scratch_cursor_gc
;
11520 /* Set clipping, draw the rectangle, and reset clipping again. */
11521 x_clip_to_row (w
, row
, gc
, 0);
11522 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
11523 XSetClipMask (dpy
, gc
, None
);
11527 /* Draw a bar cursor on window W in glyph row ROW.
11529 Implementation note: One would like to draw a bar cursor with an
11530 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11531 Unfortunately, I didn't find a font yet that has this property set.
11535 x_draw_bar_cursor (w
, row
, width
, kind
)
11537 struct glyph_row
*row
;
11539 enum text_cursor_kinds kind
;
11541 struct frame
*f
= XFRAME (w
->frame
);
11542 struct glyph
*cursor_glyph
;
11544 /* If cursor is out of bounds, don't draw garbage. This can happen
11545 in mini-buffer windows when switching between echo area glyphs
11546 and mini-buffer. */
11547 cursor_glyph
= get_phys_cursor_glyph (w
);
11548 if (cursor_glyph
== NULL
)
11551 /* If on an image, draw like a normal cursor. That's usually better
11552 visible than drawing a bar, esp. if the image is large so that
11553 the bar might not be in the window. */
11554 if (cursor_glyph
->type
== IMAGE_GLYPH
)
11556 struct glyph_row
*row
;
11557 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
11558 x_draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
11562 Display
*dpy
= FRAME_X_DISPLAY (f
);
11563 Window window
= FRAME_X_WINDOW (f
);
11564 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
11565 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
11566 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
11569 /* If the glyph's background equals the color we normally draw
11570 the bar cursor in, the bar cursor in its normal color is
11571 invisible. Use the glyph's foreground color instead in this
11572 case, on the assumption that the glyph's colors are chosen so
11573 that the glyph is legible. */
11574 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
11575 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
11577 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
11578 xgcv
.graphics_exposures
= 0;
11581 XChangeGC (dpy
, gc
, mask
, &xgcv
);
11584 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
11585 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
11589 width
= FRAME_CURSOR_WIDTH (f
);
11590 width
= min (cursor_glyph
->pixel_width
, width
);
11592 w
->phys_cursor_width
= width
;
11593 x_clip_to_row (w
, row
, gc
, 0);
11595 if (kind
== BAR_CURSOR
)
11596 XFillRectangle (dpy
, window
, gc
,
11597 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
11598 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
11599 width
, row
->height
);
11601 XFillRectangle (dpy
, window
, gc
,
11602 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
11603 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
11604 row
->height
- width
),
11605 cursor_glyph
->pixel_width
,
11608 XSetClipMask (dpy
, gc
, None
);
11613 /* Clear the cursor of window W to background color, and mark the
11614 cursor as not shown. This is used when the text where the cursor
11615 is is about to be rewritten. */
11621 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
11622 x_update_window_cursor (w
, 0);
11626 /* Draw the cursor glyph of window W in glyph row ROW. See the
11627 comment of x_draw_glyphs for the meaning of HL. */
11630 x_draw_phys_cursor_glyph (w
, row
, hl
)
11632 struct glyph_row
*row
;
11633 enum draw_glyphs_face hl
;
11635 /* If cursor hpos is out of bounds, don't draw garbage. This can
11636 happen in mini-buffer windows when switching between echo area
11637 glyphs and mini-buffer. */
11638 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
11640 int on_p
= w
->phys_cursor_on_p
;
11643 x1
= x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
11644 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
11646 w
->phys_cursor_on_p
= on_p
;
11648 if (hl
== DRAW_CURSOR
)
11649 w
->phys_cursor_width
= x1
- w
->phys_cursor
.x
;
11651 /* When we erase the cursor, and ROW is overlapped by other
11652 rows, make sure that these overlapping parts of other rows
11654 else if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
11656 if (row
> w
->current_matrix
->rows
11657 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
11658 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
11660 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
11661 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
11662 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
11668 /* Erase the image of a cursor of window W from the screen. */
11671 x_erase_phys_cursor (w
)
11674 struct frame
*f
= XFRAME (w
->frame
);
11675 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11676 int hpos
= w
->phys_cursor
.hpos
;
11677 int vpos
= w
->phys_cursor
.vpos
;
11678 int mouse_face_here_p
= 0;
11679 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
11680 struct glyph_row
*cursor_row
;
11681 struct glyph
*cursor_glyph
;
11682 enum draw_glyphs_face hl
;
11684 /* No cursor displayed or row invalidated => nothing to do on the
11686 if (w
->phys_cursor_type
== NO_CURSOR
)
11687 goto mark_cursor_off
;
11689 /* VPOS >= active_glyphs->nrows means that window has been resized.
11690 Don't bother to erase the cursor. */
11691 if (vpos
>= active_glyphs
->nrows
)
11692 goto mark_cursor_off
;
11694 /* If row containing cursor is marked invalid, there is nothing we
11696 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
11697 if (!cursor_row
->enabled_p
)
11698 goto mark_cursor_off
;
11700 /* If row is completely invisible, don't attempt to delete a cursor which
11701 isn't there. This can happen if cursor is at top of a window, and
11702 we switch to a buffer with a header line in that window. */
11703 if (cursor_row
->visible_height
<= 0)
11704 goto mark_cursor_off
;
11706 /* This can happen when the new row is shorter than the old one.
11707 In this case, either x_draw_glyphs or clear_end_of_line
11708 should have cleared the cursor. Note that we wouldn't be
11709 able to erase the cursor in this case because we don't have a
11710 cursor glyph at hand. */
11711 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
11712 goto mark_cursor_off
;
11714 /* If the cursor is in the mouse face area, redisplay that when
11715 we clear the cursor. */
11716 if (! NILP (dpyinfo
->mouse_face_window
)
11717 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
11718 && (vpos
> dpyinfo
->mouse_face_beg_row
11719 || (vpos
== dpyinfo
->mouse_face_beg_row
11720 && hpos
>= dpyinfo
->mouse_face_beg_col
))
11721 && (vpos
< dpyinfo
->mouse_face_end_row
11722 || (vpos
== dpyinfo
->mouse_face_end_row
11723 && hpos
< dpyinfo
->mouse_face_end_col
))
11724 /* Don't redraw the cursor's spot in mouse face if it is at the
11725 end of a line (on a newline). The cursor appears there, but
11726 mouse highlighting does not. */
11727 && cursor_row
->used
[TEXT_AREA
] > hpos
)
11728 mouse_face_here_p
= 1;
11730 /* Maybe clear the display under the cursor. */
11731 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
11734 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
11736 cursor_glyph
= get_phys_cursor_glyph (w
);
11737 if (cursor_glyph
== NULL
)
11738 goto mark_cursor_off
;
11740 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
11742 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11744 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
11746 cursor_glyph
->pixel_width
,
11747 cursor_row
->visible_height
,
11751 /* Erase the cursor by redrawing the character underneath it. */
11752 if (mouse_face_here_p
)
11753 hl
= DRAW_MOUSE_FACE
;
11755 hl
= DRAW_NORMAL_TEXT
;
11756 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
11759 w
->phys_cursor_on_p
= 0;
11760 w
->phys_cursor_type
= NO_CURSOR
;
11764 /* Non-zero if physical cursor of window W is within mouse face. */
11767 cursor_in_mouse_face_p (w
)
11770 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
11771 int in_mouse_face
= 0;
11773 if (WINDOWP (dpyinfo
->mouse_face_window
)
11774 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
11776 int hpos
= w
->phys_cursor
.hpos
;
11777 int vpos
= w
->phys_cursor
.vpos
;
11779 if (vpos
>= dpyinfo
->mouse_face_beg_row
11780 && vpos
<= dpyinfo
->mouse_face_end_row
11781 && (vpos
> dpyinfo
->mouse_face_beg_row
11782 || hpos
>= dpyinfo
->mouse_face_beg_col
)
11783 && (vpos
< dpyinfo
->mouse_face_end_row
11784 || hpos
< dpyinfo
->mouse_face_end_col
11785 || dpyinfo
->mouse_face_past_end
))
11789 return in_mouse_face
;
11793 /* Display or clear cursor of window W. If ON is zero, clear the
11794 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11795 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11798 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
11800 int on
, hpos
, vpos
, x
, y
;
11802 struct frame
*f
= XFRAME (w
->frame
);
11803 int new_cursor_type
;
11804 int new_cursor_width
;
11805 struct glyph_matrix
*current_glyphs
;
11806 struct glyph_row
*glyph_row
;
11807 struct glyph
*glyph
;
11809 /* This is pointless on invisible frames, and dangerous on garbaged
11810 windows and frames; in the latter case, the frame or window may
11811 be in the midst of changing its size, and x and y may be off the
11813 if (! FRAME_VISIBLE_P (f
)
11814 || FRAME_GARBAGED_P (f
)
11815 || vpos
>= w
->current_matrix
->nrows
11816 || hpos
>= w
->current_matrix
->matrix_w
)
11819 /* If cursor is off and we want it off, return quickly. */
11820 if (!on
&& !w
->phys_cursor_on_p
)
11823 current_glyphs
= w
->current_matrix
;
11824 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
11825 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
11827 /* If cursor row is not enabled, we don't really know where to
11828 display the cursor. */
11829 if (!glyph_row
->enabled_p
)
11831 w
->phys_cursor_on_p
= 0;
11835 xassert (interrupt_input_blocked
);
11837 /* Set new_cursor_type to the cursor we want to be displayed. */
11838 new_cursor_type
= get_window_cursor_type (w
, &new_cursor_width
);
11840 /* If cursor is currently being shown and we don't want it to be or
11841 it is in the wrong place, or the cursor type is not what we want,
11843 if (w
->phys_cursor_on_p
11845 || w
->phys_cursor
.x
!= x
11846 || w
->phys_cursor
.y
!= y
11847 || new_cursor_type
!= w
->phys_cursor_type
11848 || ((new_cursor_type
== BAR_CURSOR
|| new_cursor_type
== HBAR_CURSOR
)
11849 && new_cursor_width
!= w
->phys_cursor_width
)))
11850 x_erase_phys_cursor (w
);
11852 /* Don't check phys_cursor_on_p here because that flag is only set
11853 to zero in some cases where we know that the cursor has been
11854 completely erased, to avoid the extra work of erasing the cursor
11855 twice. In other words, phys_cursor_on_p can be 1 and the cursor
11856 still not be visible, or it has only been partly erased. */
11859 w
->phys_cursor_ascent
= glyph_row
->ascent
;
11860 w
->phys_cursor_height
= glyph_row
->height
;
11862 /* Set phys_cursor_.* before x_draw_.* is called because some
11863 of them may need the information. */
11864 w
->phys_cursor
.x
= x
;
11865 w
->phys_cursor
.y
= glyph_row
->y
;
11866 w
->phys_cursor
.hpos
= hpos
;
11867 w
->phys_cursor
.vpos
= vpos
;
11868 w
->phys_cursor_type
= new_cursor_type
;
11869 w
->phys_cursor_on_p
= 1;
11871 switch (new_cursor_type
)
11873 case HOLLOW_BOX_CURSOR
:
11874 x_draw_hollow_cursor (w
, glyph_row
);
11877 case FILLED_BOX_CURSOR
:
11878 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
11882 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
, BAR_CURSOR
);
11886 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
, HBAR_CURSOR
);
11890 w
->phys_cursor_width
= 0;
11898 if (w
== XWINDOW (f
->selected_window
))
11899 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
11900 xic_set_preeditarea (w
, x
, y
);
11905 if (updating_frame
!= f
)
11906 XFlush (FRAME_X_DISPLAY (f
));
11911 /* Display the cursor on window W, or clear it. X and Y are window
11912 relative pixel coordinates. HPOS and VPOS are glyph matrix
11913 positions. If W is not the selected window, display a hollow
11914 cursor. ON non-zero means display the cursor at X, Y which
11915 correspond to HPOS, VPOS, otherwise it is cleared. */
11918 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
11920 int on
, hpos
, vpos
, x
, y
;
11923 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
11928 /* Display the cursor on window W, or clear it, according to ON_P.
11929 Don't change the cursor's position. */
11932 x_update_cursor (f
, on_p
)
11935 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
11939 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11940 in the window tree rooted at W. */
11943 x_update_cursor_in_window_tree (w
, on_p
)
11949 if (!NILP (w
->hchild
))
11950 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
11951 else if (!NILP (w
->vchild
))
11952 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
11954 x_update_window_cursor (w
, on_p
);
11956 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
11961 /* Switch the display of W's cursor on or off, according to the value
11965 x_update_window_cursor (w
, on
)
11969 /* Don't update cursor in windows whose frame is in the process
11970 of being deleted. */
11971 if (w
->current_matrix
)
11974 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
11975 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
11985 /* Make the x-window of frame F use the gnu icon bitmap. */
11988 x_bitmap_icon (f
, file
)
11994 if (FRAME_X_WINDOW (f
) == 0)
11997 /* Free up our existing icon bitmap if any. */
11998 if (f
->output_data
.x
->icon_bitmap
> 0)
11999 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
12000 f
->output_data
.x
->icon_bitmap
= 0;
12002 if (STRINGP (file
))
12003 bitmap_id
= x_create_bitmap_from_file (f
, file
);
12006 /* Create the GNU bitmap if necessary. */
12007 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
12008 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
12009 = x_create_bitmap_from_data (f
, gnu_bits
,
12010 gnu_width
, gnu_height
);
12012 /* The first time we create the GNU bitmap,
12013 this increments the ref-count one extra time.
12014 As a result, the GNU bitmap is never freed.
12015 That way, we don't have to worry about allocating it again. */
12016 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
12018 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
12021 x_wm_set_icon_pixmap (f
, bitmap_id
);
12022 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
12028 /* Make the x-window of frame F use a rectangle with text.
12029 Use ICON_NAME as the text. */
12032 x_text_icon (f
, icon_name
)
12036 if (FRAME_X_WINDOW (f
) == 0)
12041 XTextProperty text
;
12042 text
.value
= (unsigned char *) icon_name
;
12043 text
.encoding
= XA_STRING
;
12045 text
.nitems
= strlen (icon_name
);
12046 #ifdef USE_X_TOOLKIT
12047 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
12049 #else /* not USE_X_TOOLKIT */
12050 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
12051 #endif /* not USE_X_TOOLKIT */
12053 #else /* not HAVE_X11R4 */
12054 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
12055 #endif /* not HAVE_X11R4 */
12057 if (f
->output_data
.x
->icon_bitmap
> 0)
12058 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
12059 f
->output_data
.x
->icon_bitmap
= 0;
12060 x_wm_set_icon_pixmap (f
, 0);
12065 #define X_ERROR_MESSAGE_SIZE 200
12067 /* If non-nil, this should be a string.
12068 It means catch X errors and store the error message in this string. */
12070 static Lisp_Object x_error_message_string
;
12072 /* An X error handler which stores the error message in
12073 x_error_message_string. This is called from x_error_handler if
12074 x_catch_errors is in effect. */
12077 x_error_catcher (display
, error
)
12079 XErrorEvent
*error
;
12081 XGetErrorText (display
, error
->error_code
,
12082 SDATA (x_error_message_string
),
12083 X_ERROR_MESSAGE_SIZE
);
12086 /* Begin trapping X errors for display DPY. Actually we trap X errors
12087 for all displays, but DPY should be the display you are actually
12090 After calling this function, X protocol errors no longer cause
12091 Emacs to exit; instead, they are recorded in the string
12092 stored in x_error_message_string.
12094 Calling x_check_errors signals an Emacs error if an X error has
12095 occurred since the last call to x_catch_errors or x_check_errors.
12097 Calling x_uncatch_errors resumes the normal error handling. */
12099 void x_check_errors ();
12100 static Lisp_Object
x_catch_errors_unwind ();
12103 x_catch_errors (dpy
)
12106 int count
= SPECPDL_INDEX ();
12108 /* Make sure any errors from previous requests have been dealt with. */
12109 XSync (dpy
, False
);
12111 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
12113 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
12114 SSET (x_error_message_string
, 0, 0);
12119 /* Unbind the binding that we made to check for X errors. */
12122 x_catch_errors_unwind (old_val
)
12123 Lisp_Object old_val
;
12125 x_error_message_string
= old_val
;
12129 /* If any X protocol errors have arrived since the last call to
12130 x_catch_errors or x_check_errors, signal an Emacs error using
12131 sprintf (a buffer, FORMAT, the x error message text) as the text. */
12134 x_check_errors (dpy
, format
)
12138 /* Make sure to catch any errors incurred so far. */
12139 XSync (dpy
, False
);
12141 if (SREF (x_error_message_string
, 0))
12142 error (format
, SDATA (x_error_message_string
));
12145 /* Nonzero if we had any X protocol errors
12146 since we did x_catch_errors on DPY. */
12149 x_had_errors_p (dpy
)
12152 /* Make sure to catch any errors incurred so far. */
12153 XSync (dpy
, False
);
12155 return SREF (x_error_message_string
, 0) != 0;
12158 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
12161 x_clear_errors (dpy
)
12164 SSET (x_error_message_string
, 0, 0);
12167 /* Stop catching X protocol errors and let them make Emacs die.
12168 DPY should be the display that was passed to x_catch_errors.
12169 COUNT should be the value that was returned by
12170 the corresponding call to x_catch_errors. */
12173 x_uncatch_errors (dpy
, count
)
12177 unbind_to (count
, Qnil
);
12181 static unsigned int x_wire_count
;
12184 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
12189 /* Handle SIGPIPE, which can happen when the connection to a server
12190 simply goes away. SIGPIPE is handled by x_connection_signal.
12191 Don't need to do anything, because the write which caused the
12192 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12193 which will do the appropriate cleanup for us. */
12196 x_connection_signal (signalnum
) /* If we don't have an argument, */
12197 int signalnum
; /* some compilers complain in signal calls. */
12200 /* USG systems forget handlers when they are used;
12201 must reestablish each time */
12202 signal (signalnum
, x_connection_signal
);
12207 /************************************************************************
12209 ************************************************************************/
12211 /* Error message passed to x_connection_closed. */
12213 static char *error_msg
;
12215 /* Function installed as fatal_error_signal_hook in
12216 x_connection_closed. Print the X error message, and exit normally,
12217 instead of dumping core when XtCloseDisplay fails. */
12220 x_fatal_error_signal ()
12222 fprintf (stderr
, "%s\n", error_msg
);
12226 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12227 the text of an error message that lead to the connection loss. */
12230 x_connection_closed (dpy
, error_message
)
12232 char *error_message
;
12234 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
12235 Lisp_Object frame
, tail
;
12238 error_msg
= (char *) alloca (strlen (error_message
) + 1);
12239 strcpy (error_msg
, error_message
);
12240 handling_signal
= 0;
12242 /* Prevent being called recursively because of an error condition
12243 below. Otherwise, we might end up with printing ``can't find per
12244 display information'' in the recursive call instead of printing
12245 the original message here. */
12246 count
= x_catch_errors (dpy
);
12248 /* We have to close the display to inform Xt that it doesn't
12249 exist anymore. If we don't, Xt will continue to wait for
12250 events from the display. As a consequence, a sequence of
12252 M-x make-frame-on-display RET :1 RET
12253 ...kill the new frame, so that we get an IO error...
12254 M-x make-frame-on-display RET :1 RET
12256 will indefinitely wait in Xt for events for display `:1', opened
12257 in the first class to make-frame-on-display.
12259 Closing the display is reported to lead to a bus error on
12260 OpenWindows in certain situations. I suspect that is a bug
12261 in OpenWindows. I don't know how to cicumvent it here. */
12263 #ifdef USE_X_TOOLKIT
12264 /* If DPYINFO is null, this means we didn't open the display
12265 in the first place, so don't try to close it. */
12268 extern void (*fatal_error_signal_hook
) P_ ((void));
12269 fatal_error_signal_hook
= x_fatal_error_signal
;
12270 XtCloseDisplay (dpy
);
12271 fatal_error_signal_hook
= NULL
;
12275 /* Indicate that this display is dead. */
12277 dpyinfo
->display
= 0;
12279 /* First delete frames whose mini-buffers are on frames
12280 that are on the dead display. */
12281 FOR_EACH_FRAME (tail
, frame
)
12283 Lisp_Object minibuf_frame
;
12285 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
12286 if (FRAME_X_P (XFRAME (frame
))
12287 && FRAME_X_P (XFRAME (minibuf_frame
))
12288 && ! EQ (frame
, minibuf_frame
)
12289 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
12290 Fdelete_frame (frame
, Qt
);
12293 /* Now delete all remaining frames on the dead display.
12294 We are now sure none of these is used as the mini-buffer
12295 for another frame that we need to delete. */
12296 FOR_EACH_FRAME (tail
, frame
)
12297 if (FRAME_X_P (XFRAME (frame
))
12298 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
12300 /* Set this to t so that Fdelete_frame won't get confused
12301 trying to find a replacement. */
12302 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
12303 Fdelete_frame (frame
, Qt
);
12307 x_delete_display (dpyinfo
);
12309 x_uncatch_errors (dpy
, count
);
12311 if (x_display_list
== 0)
12313 fprintf (stderr
, "%s\n", error_msg
);
12314 shut_down_emacs (0, 0, Qnil
);
12318 /* Ordinary stack unwind doesn't deal with these. */
12320 sigunblock (sigmask (SIGIO
));
12322 sigunblock (sigmask (SIGALRM
));
12323 TOTALLY_UNBLOCK_INPUT
;
12325 clear_waiting_for_input ();
12326 error ("%s", error_msg
);
12330 /* This is the usual handler for X protocol errors.
12331 It kills all frames on the display that we got the error for.
12332 If that was the only one, it prints an error message and kills Emacs. */
12335 x_error_quitter (display
, error
)
12337 XErrorEvent
*error
;
12339 char buf
[256], buf1
[356];
12341 /* Note that there is no real way portable across R3/R4 to get the
12342 original error handler. */
12344 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
12345 sprintf (buf1
, "X protocol error: %s on protocol request %d",
12346 buf
, error
->request_code
);
12347 x_connection_closed (display
, buf1
);
12351 /* This is the first-level handler for X protocol errors.
12352 It calls x_error_quitter or x_error_catcher. */
12355 x_error_handler (display
, error
)
12357 XErrorEvent
*error
;
12359 if (! NILP (x_error_message_string
))
12360 x_error_catcher (display
, error
);
12362 x_error_quitter (display
, error
);
12366 /* This is the handler for X IO errors, always.
12367 It kills all frames on the display that we lost touch with.
12368 If that was the only one, it prints an error message and kills Emacs. */
12371 x_io_error_quitter (display
)
12376 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
12377 x_connection_closed (display
, buf
);
12381 /* Changing the font of the frame. */
12383 /* Give frame F the font named FONTNAME as its default font, and
12384 return the full name of that font. FONTNAME may be a wildcard
12385 pattern; in that case, we choose some font that fits the pattern.
12386 The return value shows which font we chose. */
12389 x_new_font (f
, fontname
)
12391 register char *fontname
;
12393 struct font_info
*fontp
12394 = FS_LOAD_FONT (f
, 0, fontname
, -1);
12399 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
12400 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
12401 f
->output_data
.x
->fontset
= -1;
12403 x_compute_fringe_widths (f
, 1);
12405 /* Compute the scroll bar width in character columns. */
12406 if (f
->scroll_bar_pixel_width
> 0)
12408 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12409 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
12413 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12414 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
12417 /* Now make the frame display the given font. */
12418 if (FRAME_X_WINDOW (f
) != 0)
12420 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
12421 f
->output_data
.x
->font
->fid
);
12422 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
12423 f
->output_data
.x
->font
->fid
);
12424 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
12425 f
->output_data
.x
->font
->fid
);
12427 frame_update_line_height (f
);
12429 /* Don't change the size of a tip frame; there's no point in
12430 doing it because it's done in Fx_show_tip, and it leads to
12431 problems because the tip frame has no widget. */
12432 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
12433 x_set_window_size (f
, 0, f
->width
, f
->height
);
12436 /* If we are setting a new frame's font for the first time,
12437 there are no faces yet, so this font's height is the line height. */
12438 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
12440 return build_string (fontp
->full_name
);
12443 /* Give frame F the fontset named FONTSETNAME as its default font, and
12444 return the full name of that fontset. FONTSETNAME may be a wildcard
12445 pattern; in that case, we choose some fontset that fits the pattern.
12446 The return value shows which fontset we chose. */
12449 x_new_fontset (f
, fontsetname
)
12453 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
12454 Lisp_Object result
;
12459 if (f
->output_data
.x
->fontset
== fontset
)
12460 /* This fontset is already set in frame F. There's nothing more
12462 return fontset_name (fontset
);
12464 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
12466 if (!STRINGP (result
))
12467 /* Can't load ASCII font. */
12470 /* Since x_new_font doesn't update any fontset information, do it now. */
12471 f
->output_data
.x
->fontset
= fontset
;
12475 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
12476 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
12479 return build_string (fontsetname
);
12482 /* Compute actual fringe widths */
12485 x_compute_fringe_widths (f
, redraw
)
12489 int o_left
= f
->output_data
.x
->left_fringe_width
;
12490 int o_right
= f
->output_data
.x
->right_fringe_width
;
12491 int o_cols
= f
->output_data
.x
->fringe_cols
;
12493 Lisp_Object left_fringe
= Fassq (Qleft_fringe
, f
->param_alist
);
12494 Lisp_Object right_fringe
= Fassq (Qright_fringe
, f
->param_alist
);
12495 int left_fringe_width
, right_fringe_width
;
12497 if (!NILP (left_fringe
))
12498 left_fringe
= Fcdr (left_fringe
);
12499 if (!NILP (right_fringe
))
12500 right_fringe
= Fcdr (right_fringe
);
12502 left_fringe_width
= ((NILP (left_fringe
) || !INTEGERP (left_fringe
)) ? 8 :
12503 XINT (left_fringe
));
12504 right_fringe_width
= ((NILP (right_fringe
) || !INTEGERP (right_fringe
)) ? 8 :
12505 XINT (right_fringe
));
12507 if (left_fringe_width
|| right_fringe_width
)
12509 int left_wid
= left_fringe_width
>= 0 ? left_fringe_width
: -left_fringe_width
;
12510 int right_wid
= right_fringe_width
>= 0 ? right_fringe_width
: -right_fringe_width
;
12511 int conf_wid
= left_wid
+ right_wid
;
12512 int font_wid
= FONT_WIDTH (f
->output_data
.x
->font
);
12513 int cols
= (left_wid
+ right_wid
+ font_wid
-1) / font_wid
;
12514 int real_wid
= cols
* font_wid
;
12515 if (left_wid
&& right_wid
)
12517 if (left_fringe_width
< 0)
12519 /* Left fringe width is fixed, adjust right fringe if necessary */
12520 f
->output_data
.x
->left_fringe_width
= left_wid
;
12521 f
->output_data
.x
->right_fringe_width
= real_wid
- left_wid
;
12523 else if (right_fringe_width
< 0)
12525 /* Right fringe width is fixed, adjust left fringe if necessary */
12526 f
->output_data
.x
->left_fringe_width
= real_wid
- right_wid
;
12527 f
->output_data
.x
->right_fringe_width
= right_wid
;
12531 /* Adjust both fringes with an equal amount.
12532 Note that we are doing integer arithmetic here, so don't
12533 lose a pixel if the total width is an odd number. */
12534 int fill
= real_wid
- conf_wid
;
12535 f
->output_data
.x
->left_fringe_width
= left_wid
+ fill
/2;
12536 f
->output_data
.x
->right_fringe_width
= right_wid
+ fill
- fill
/2;
12539 else if (left_fringe_width
)
12541 f
->output_data
.x
->left_fringe_width
= real_wid
;
12542 f
->output_data
.x
->right_fringe_width
= 0;
12546 f
->output_data
.x
->left_fringe_width
= 0;
12547 f
->output_data
.x
->right_fringe_width
= real_wid
;
12549 f
->output_data
.x
->fringe_cols
= cols
;
12550 f
->output_data
.x
->fringes_extra
= real_wid
;
12554 f
->output_data
.x
->left_fringe_width
= 0;
12555 f
->output_data
.x
->right_fringe_width
= 0;
12556 f
->output_data
.x
->fringe_cols
= 0;
12557 f
->output_data
.x
->fringes_extra
= 0;
12560 if (redraw
&& FRAME_VISIBLE_P (f
))
12561 if (o_left
!= f
->output_data
.x
->left_fringe_width
||
12562 o_right
!= f
->output_data
.x
->right_fringe_width
||
12563 o_cols
!= f
->output_data
.x
->fringe_cols
)
12567 /***********************************************************************
12569 ***********************************************************************/
12575 /* XIM destroy callback function, which is called whenever the
12576 connection to input method XIM dies. CLIENT_DATA contains a
12577 pointer to the x_display_info structure corresponding to XIM. */
12580 xim_destroy_callback (xim
, client_data
, call_data
)
12582 XPointer client_data
;
12583 XPointer call_data
;
12585 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
12586 Lisp_Object frame
, tail
;
12590 /* No need to call XDestroyIC.. */
12591 FOR_EACH_FRAME (tail
, frame
)
12593 struct frame
*f
= XFRAME (frame
);
12594 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
12596 FRAME_XIC (f
) = NULL
;
12597 if (FRAME_XIC_FONTSET (f
))
12599 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
12600 FRAME_XIC_FONTSET (f
) = NULL
;
12605 /* No need to call XCloseIM. */
12606 dpyinfo
->xim
= NULL
;
12607 XFree (dpyinfo
->xim_styles
);
12611 #endif /* HAVE_X11R6 */
12613 /* Open the connection to the XIM server on display DPYINFO.
12614 RESOURCE_NAME is the resource name Emacs uses. */
12617 xim_open_dpy (dpyinfo
, resource_name
)
12618 struct x_display_info
*dpyinfo
;
12619 char *resource_name
;
12624 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
, EMACS_CLASS
);
12625 dpyinfo
->xim
= xim
;
12630 XIMCallback destroy
;
12633 /* Get supported styles and XIM values. */
12634 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
12637 destroy
.callback
= xim_destroy_callback
;
12638 destroy
.client_data
= (XPointer
)dpyinfo
;
12639 /* This isn't prototyped in OSF 5.0. */
12640 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
12644 #else /* not USE_XIM */
12645 dpyinfo
->xim
= NULL
;
12646 #endif /* not USE_XIM */
12650 #ifdef HAVE_X11R6_XIM
12654 struct x_display_info
*dpyinfo
;
12655 char *resource_name
;
12658 /* XIM instantiate callback function, which is called whenever an XIM
12659 server is available. DISPLAY is teh display of the XIM.
12660 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12661 when the callback was registered. */
12664 xim_instantiate_callback (display
, client_data
, call_data
)
12666 XPointer client_data
;
12667 XPointer call_data
;
12669 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
12670 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
12672 /* We don't support multiple XIM connections. */
12676 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
12678 /* Create XIC for the existing frames on the same display, as long
12679 as they have no XIC. */
12680 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
12682 Lisp_Object tail
, frame
;
12685 FOR_EACH_FRAME (tail
, frame
)
12687 struct frame
*f
= XFRAME (frame
);
12689 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
12690 if (FRAME_XIC (f
) == NULL
)
12692 create_frame_xic (f
);
12693 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
12694 xic_set_statusarea (f
);
12695 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
12697 struct window
*w
= XWINDOW (f
->selected_window
);
12698 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
12707 #endif /* HAVE_X11R6_XIM */
12710 /* Open a connection to the XIM server on display DPYINFO.
12711 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12712 connection only at the first time. On X11R6, open the connection
12713 in the XIM instantiate callback function. */
12716 xim_initialize (dpyinfo
, resource_name
)
12717 struct x_display_info
*dpyinfo
;
12718 char *resource_name
;
12721 #ifdef HAVE_X11R6_XIM
12722 struct xim_inst_t
*xim_inst
;
12725 dpyinfo
->xim
= NULL
;
12726 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
12727 xim_inst
->dpyinfo
= dpyinfo
;
12728 len
= strlen (resource_name
);
12729 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
12730 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
12731 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
12732 resource_name
, EMACS_CLASS
,
12733 xim_instantiate_callback
,
12734 /* Fixme: This is XPointer in
12735 XFree86 but (XPointer *) on
12736 Tru64, at least. */
12737 (XPointer
) xim_inst
);
12738 #else /* not HAVE_X11R6_XIM */
12739 dpyinfo
->xim
= NULL
;
12740 xim_open_dpy (dpyinfo
, resource_name
);
12741 #endif /* not HAVE_X11R6_XIM */
12743 #else /* not USE_XIM */
12744 dpyinfo
->xim
= NULL
;
12745 #endif /* not USE_XIM */
12749 /* Close the connection to the XIM server on display DPYINFO. */
12752 xim_close_dpy (dpyinfo
)
12753 struct x_display_info
*dpyinfo
;
12756 #ifdef HAVE_X11R6_XIM
12757 if (dpyinfo
->display
)
12758 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
12760 xim_instantiate_callback
, NULL
);
12761 #endif /* not HAVE_X11R6_XIM */
12762 if (dpyinfo
->display
)
12763 XCloseIM (dpyinfo
->xim
);
12764 dpyinfo
->xim
= NULL
;
12765 XFree (dpyinfo
->xim_styles
);
12766 #endif /* USE_XIM */
12769 #endif /* not HAVE_X11R6_XIM */
12773 /* Calculate the absolute position in frame F
12774 from its current recorded position values and gravity. */
12777 x_calc_absolute_position (f
)
12781 int win_x
= 0, win_y
= 0;
12782 int flags
= f
->output_data
.x
->size_hint_flags
;
12785 /* We have nothing to do if the current position
12786 is already for the top-left corner. */
12787 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
12790 #ifdef USE_X_TOOLKIT
12791 this_window
= XtWindow (f
->output_data
.x
->widget
);
12793 this_window
= FRAME_X_WINDOW (f
);
12796 /* Find the position of the outside upper-left corner of
12797 the inner window, with respect to the outer window.
12798 But do this only if we will need the results. */
12799 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
12804 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12807 x_clear_errors (FRAME_X_DISPLAY (f
));
12808 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
12810 /* From-window, to-window. */
12812 f
->output_data
.x
->parent_desc
,
12814 /* From-position, to-position. */
12815 0, 0, &win_x
, &win_y
,
12817 /* Child of win. */
12819 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12821 Window newroot
, newparent
= 0xdeadbeef;
12822 Window
*newchildren
;
12823 unsigned int nchildren
;
12825 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
12826 &newparent
, &newchildren
, &nchildren
))
12829 XFree ((char *) newchildren
);
12831 f
->output_data
.x
->parent_desc
= newparent
;
12837 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12841 /* Treat negative positions as relative to the leftmost bottommost
12842 position that fits on the screen. */
12843 if (flags
& XNegative
)
12844 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
12845 - 2 * f
->output_data
.x
->border_width
- win_x
12847 + f
->output_data
.x
->left_pos
);
12850 int height
= PIXEL_HEIGHT (f
);
12852 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12853 /* Something is fishy here. When using Motif, starting Emacs with
12854 `-g -0-0', the frame appears too low by a few pixels.
12856 This seems to be so because initially, while Emacs is starting,
12857 the column widget's height and the frame's pixel height are
12858 different. The column widget's height is the right one. In
12859 later invocations, when Emacs is up, the frame's pixel height
12862 It's not obvious where the initial small difference comes from.
12863 2000-12-01, gerd. */
12865 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
12868 if (flags
& YNegative
)
12869 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
12870 - 2 * f
->output_data
.x
->border_width
12873 + f
->output_data
.x
->top_pos
);
12876 /* The left_pos and top_pos
12877 are now relative to the top and left screen edges,
12878 so the flags should correspond. */
12879 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
12882 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12883 to really change the position, and 0 when calling from
12884 x_make_frame_visible (in that case, XOFF and YOFF are the current
12885 position values). It is -1 when calling from x_set_frame_parameters,
12886 which means, do adjust for borders but don't change the gravity. */
12889 x_set_offset (f
, xoff
, yoff
, change_gravity
)
12891 register int xoff
, yoff
;
12892 int change_gravity
;
12894 int modified_top
, modified_left
;
12896 if (change_gravity
> 0)
12898 f
->output_data
.x
->top_pos
= yoff
;
12899 f
->output_data
.x
->left_pos
= xoff
;
12900 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
12902 f
->output_data
.x
->size_hint_flags
|= XNegative
;
12904 f
->output_data
.x
->size_hint_flags
|= YNegative
;
12905 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
12907 x_calc_absolute_position (f
);
12910 x_wm_set_size_hint (f
, (long) 0, 0);
12912 modified_left
= f
->output_data
.x
->left_pos
;
12913 modified_top
= f
->output_data
.x
->top_pos
;
12914 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12915 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12916 /* It is a mystery why we need to add the border_width here
12917 when the frame is already visible, but experiment says we do. */
12918 if (change_gravity
!= 0)
12920 modified_left
+= f
->output_data
.x
->border_width
;
12921 modified_top
+= f
->output_data
.x
->border_width
;
12925 #ifdef USE_X_TOOLKIT
12926 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
12927 modified_left
, modified_top
);
12928 #else /* not USE_X_TOOLKIT */
12929 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
12930 modified_left
, modified_top
);
12931 #endif /* not USE_X_TOOLKIT */
12935 /* Check if we need to resize the frame due to a fullscreen request.
12936 If so needed, resize the frame. */
12938 x_check_fullscreen (f
)
12941 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_BOTH
)
12943 int width
, height
, ign
;
12945 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
12946 &f
->output_data
.x
->top_pos
);
12948 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
12950 /* We do not need to move the window, it shall be taken care of
12951 when setting WM manager hints.
12952 If the frame is visible already, the position is checked by
12953 x_check_fullscreen_move. */
12954 if (f
->width
!= width
|| f
->height
!= height
)
12956 change_frame_size (f
, height
, width
, 0, 1, 0);
12957 SET_FRAME_GARBAGED (f
);
12958 cancel_mouse_face (f
);
12960 /* Wait for the change of frame size to occur */
12961 f
->output_data
.x
->want_fullscreen
|= FULLSCREEN_WAIT
;
12967 /* If frame parameters are set after the frame is mapped, we need to move
12968 the window. This is done in xfns.c.
12969 Some window managers moves the window to the right position, some
12970 moves the outer window manager window to the specified position.
12971 Here we check that we are in the right spot. If not, make a second
12972 move, assuming we are dealing with the second kind of window manager. */
12974 x_check_fullscreen_move (f
)
12977 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_MOVE_WAIT
)
12979 int expect_top
= f
->output_data
.x
->top_pos
;
12980 int expect_left
= f
->output_data
.x
->left_pos
;
12982 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_HEIGHT
)
12984 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WIDTH
)
12987 if (expect_top
!= f
->output_data
.x
->top_pos
12988 || expect_left
!= f
->output_data
.x
->left_pos
)
12989 x_set_offset (f
, expect_left
, expect_top
, 1);
12991 /* Just do this once */
12992 f
->output_data
.x
->want_fullscreen
&= ~FULLSCREEN_MOVE_WAIT
;
12997 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
12998 wanted positions of the WM window (not emacs window).
12999 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
13000 window (FRAME_X_WINDOW).
13003 x_fullscreen_adjust (f
, width
, height
, top_pos
, left_pos
)
13010 int newwidth
= f
->width
, newheight
= f
->height
;
13012 *top_pos
= f
->output_data
.x
->top_pos
;
13013 *left_pos
= f
->output_data
.x
->left_pos
;
13015 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_HEIGHT
)
13019 ph
= FRAME_X_DISPLAY_INFO (f
)->height
;
13020 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
13021 ph
= CHAR_TO_PIXEL_HEIGHT (f
, newheight
)
13022 - f
->output_data
.x
->y_pixels_diff
;
13023 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
13027 if (f
->output_data
.x
->want_fullscreen
& FULLSCREEN_WIDTH
)
13031 pw
= FRAME_X_DISPLAY_INFO (f
)->width
;
13032 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
13033 pw
= CHAR_TO_PIXEL_WIDTH (f
, newwidth
)
13034 - f
->output_data
.x
->x_pixels_diff
;
13035 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
13040 *height
= newheight
;
13044 /* Change the size of frame F's X window to COLS/ROWS in the case F
13045 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
13046 top-left-corner window gravity for this size change and subsequent
13047 size changes. Otherwise we leave the window gravity unchanged. */
13050 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
13052 int change_gravity
;
13055 int pixelwidth
, pixelheight
;
13057 check_frame_size (f
, &rows
, &cols
);
13058 f
->output_data
.x
->vertical_scroll_bar_extra
13059 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
13061 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
13062 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
13063 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
13065 x_compute_fringe_widths (f
, 0);
13067 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
13068 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
13070 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
13071 x_wm_set_size_hint (f
, (long) 0, 0);
13073 XSync (FRAME_X_DISPLAY (f
), False
);
13074 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
13075 pixelwidth
, pixelheight
);
13077 /* Now, strictly speaking, we can't be sure that this is accurate,
13078 but the window manager will get around to dealing with the size
13079 change request eventually, and we'll hear how it went when the
13080 ConfigureNotify event gets here.
13082 We could just not bother storing any of this information here,
13083 and let the ConfigureNotify event set everything up, but that
13084 might be kind of confusing to the Lisp code, since size changes
13085 wouldn't be reported in the frame parameters until some random
13086 point in the future when the ConfigureNotify event arrives.
13088 We pass 1 for DELAY since we can't run Lisp code inside of
13090 change_frame_size (f
, rows
, cols
, 0, 1, 0);
13091 PIXEL_WIDTH (f
) = pixelwidth
;
13092 PIXEL_HEIGHT (f
) = pixelheight
;
13094 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
13095 receive in the ConfigureNotify event; if we get what we asked
13096 for, then the event won't cause the screen to become garbaged, so
13097 we have to make sure to do it here. */
13098 SET_FRAME_GARBAGED (f
);
13100 XFlush (FRAME_X_DISPLAY (f
));
13104 /* Call this to change the size of frame F's x-window.
13105 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
13106 for this size change and subsequent size changes.
13107 Otherwise we leave the window gravity unchanged. */
13110 x_set_window_size (f
, change_gravity
, cols
, rows
)
13112 int change_gravity
;
13117 #ifdef USE_X_TOOLKIT
13119 if (f
->output_data
.x
->widget
!= NULL
)
13121 /* The x and y position of the widget is clobbered by the
13122 call to XtSetValues within EmacsFrameSetCharSize.
13123 This is a real kludge, but I don't understand Xt so I can't
13124 figure out a correct fix. Can anyone else tell me? -- rms. */
13125 int xpos
= f
->output_data
.x
->widget
->core
.x
;
13126 int ypos
= f
->output_data
.x
->widget
->core
.y
;
13127 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
13128 f
->output_data
.x
->widget
->core
.x
= xpos
;
13129 f
->output_data
.x
->widget
->core
.y
= ypos
;
13132 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
13134 #else /* not USE_X_TOOLKIT */
13136 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
13138 #endif /* not USE_X_TOOLKIT */
13140 /* If cursor was outside the new size, mark it as off. */
13141 mark_window_cursors_off (XWINDOW (f
->root_window
));
13143 /* Clear out any recollection of where the mouse highlighting was,
13144 since it might be in a place that's outside the new frame size.
13145 Actually checking whether it is outside is a pain in the neck,
13146 so don't try--just let the highlighting be done afresh with new size. */
13147 cancel_mouse_face (f
);
13152 /* Mouse warping. */
13155 x_set_mouse_position (f
, x
, y
)
13161 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
13162 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
13164 if (pix_x
< 0) pix_x
= 0;
13165 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
13167 if (pix_y
< 0) pix_y
= 0;
13168 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
13172 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
13173 0, 0, 0, 0, pix_x
, pix_y
);
13177 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13180 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
13186 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
13187 0, 0, 0, 0, pix_x
, pix_y
);
13191 /* focus shifting, raising and lowering. */
13194 x_focus_on_frame (f
)
13197 #if 0 /* This proves to be unpleasant. */
13201 /* I don't think that the ICCCM allows programs to do things like this
13202 without the interaction of the window manager. Whatever you end up
13203 doing with this code, do it to x_unfocus_frame too. */
13204 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
13205 RevertToPointerRoot
, CurrentTime
);
13210 x_unfocus_frame (f
)
13214 /* Look at the remarks in x_focus_on_frame. */
13215 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
13216 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
13217 RevertToPointerRoot
, CurrentTime
);
13221 /* Raise frame F. */
13227 if (f
->async_visible
)
13230 #ifdef USE_X_TOOLKIT
13231 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
13232 #else /* not USE_X_TOOLKIT */
13233 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13234 #endif /* not USE_X_TOOLKIT */
13235 XFlush (FRAME_X_DISPLAY (f
));
13240 /* Lower frame F. */
13246 if (f
->async_visible
)
13249 #ifdef USE_X_TOOLKIT
13250 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
13251 #else /* not USE_X_TOOLKIT */
13252 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13253 #endif /* not USE_X_TOOLKIT */
13254 XFlush (FRAME_X_DISPLAY (f
));
13260 XTframe_raise_lower (f
, raise_flag
)
13270 /* Change of visibility. */
13272 /* This tries to wait until the frame is really visible.
13273 However, if the window manager asks the user where to position
13274 the frame, this will return before the user finishes doing that.
13275 The frame will not actually be visible at that time,
13276 but it will become visible later when the window manager
13277 finishes with it. */
13280 x_make_frame_visible (f
)
13284 int original_top
, original_left
;
13285 int retry_count
= 2;
13291 type
= x_icon_type (f
);
13293 x_bitmap_icon (f
, type
);
13295 if (! FRAME_VISIBLE_P (f
))
13297 /* We test FRAME_GARBAGED_P here to make sure we don't
13298 call x_set_offset a second time
13299 if we get to x_make_frame_visible a second time
13300 before the window gets really visible. */
13301 if (! FRAME_ICONIFIED_P (f
)
13302 && ! f
->output_data
.x
->asked_for_visible
)
13303 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
13305 f
->output_data
.x
->asked_for_visible
= 1;
13307 if (! EQ (Vx_no_window_manager
, Qt
))
13308 x_wm_set_window_state (f
, NormalState
);
13309 #ifdef USE_X_TOOLKIT
13310 /* This was XtPopup, but that did nothing for an iconified frame. */
13311 XtMapWidget (f
->output_data
.x
->widget
);
13312 #else /* not USE_X_TOOLKIT */
13313 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13314 #endif /* not USE_X_TOOLKIT */
13315 #if 0 /* This seems to bring back scroll bars in the wrong places
13316 if the window configuration has changed. They seem
13317 to come back ok without this. */
13318 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
13319 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13323 XFlush (FRAME_X_DISPLAY (f
));
13325 /* Synchronize to ensure Emacs knows the frame is visible
13326 before we do anything else. We do this loop with input not blocked
13327 so that incoming events are handled. */
13331 /* This must be before UNBLOCK_INPUT
13332 since events that arrive in response to the actions above
13333 will set it when they are handled. */
13334 int previously_visible
= f
->output_data
.x
->has_been_visible
;
13336 original_left
= f
->output_data
.x
->left_pos
;
13337 original_top
= f
->output_data
.x
->top_pos
;
13339 /* This must come after we set COUNT. */
13342 /* We unblock here so that arriving X events are processed. */
13344 /* Now move the window back to where it was "supposed to be".
13345 But don't do it if the gravity is negative.
13346 When the gravity is negative, this uses a position
13347 that is 3 pixels too low. Perhaps that's really the border width.
13349 Don't do this if the window has never been visible before,
13350 because the window manager may choose the position
13351 and we don't want to override it. */
13353 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
13354 && f
->output_data
.x
->win_gravity
== NorthWestGravity
13355 && previously_visible
)
13359 unsigned int width
, height
, border
, depth
;
13363 /* On some window managers (such as FVWM) moving an existing
13364 window, even to the same place, causes the window manager
13365 to introduce an offset. This can cause the window to move
13366 to an unexpected location. Check the geometry (a little
13367 slow here) and then verify that the window is in the right
13368 place. If the window is not in the right place, move it
13369 there, and take the potential window manager hit. */
13370 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
13371 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
13373 if (original_left
!= x
|| original_top
!= y
)
13374 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
13375 original_left
, original_top
);
13380 XSETFRAME (frame
, f
);
13382 /* Wait until the frame is visible. Process X events until a
13383 MapNotify event has been seen, or until we think we won't get a
13384 MapNotify at all.. */
13385 for (count
= input_signal_count
+ 10;
13386 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
13388 /* Force processing of queued events. */
13391 /* Machines that do polling rather than SIGIO have been
13392 observed to go into a busy-wait here. So we'll fake an
13393 alarm signal to let the handler know that there's something
13394 to be read. We used to raise a real alarm, but it seems
13395 that the handler isn't always enabled here. This is
13397 if (input_polling_used ())
13399 /* It could be confusing if a real alarm arrives while
13400 processing the fake one. Turn it off and let the
13401 handler reset it. */
13402 extern void poll_for_input_1
P_ ((void));
13403 int old_poll_suppress_count
= poll_suppress_count
;
13404 poll_suppress_count
= 1;
13405 poll_for_input_1 ();
13406 poll_suppress_count
= old_poll_suppress_count
;
13409 /* See if a MapNotify event has been processed. */
13410 FRAME_SAMPLE_VISIBILITY (f
);
13415 (let ((f (selected-frame)))
13419 the frame is not raised with various window managers on
13420 FreeBSD, Linux and Solaris. It turns out that, for some
13421 unknown reason, the call to XtMapWidget is completely ignored.
13422 Mapping the widget a second time works. */
13424 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
13429 /* Change from mapped state to withdrawn state. */
13431 /* Make the frame visible (mapped and not iconified). */
13434 x_make_frame_invisible (f
)
13439 #ifdef USE_X_TOOLKIT
13440 /* Use the frame's outermost window, not the one we normally draw on. */
13441 window
= XtWindow (f
->output_data
.x
->widget
);
13442 #else /* not USE_X_TOOLKIT */
13443 window
= FRAME_X_WINDOW (f
);
13444 #endif /* not USE_X_TOOLKIT */
13446 /* Don't keep the highlight on an invisible frame. */
13447 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
13448 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
13450 #if 0/* This might add unreliability; I don't trust it -- rms. */
13451 if (! f
->async_visible
&& ! f
->async_iconified
)
13457 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13458 that the current position of the window is user-specified, rather than
13459 program-specified, so that when the window is mapped again, it will be
13460 placed at the same location, without forcing the user to position it
13461 by hand again (they have already done that once for this window.) */
13462 x_wm_set_size_hint (f
, (long) 0, 1);
13466 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
13467 DefaultScreen (FRAME_X_DISPLAY (f
))))
13469 UNBLOCK_INPUT_RESIGNAL
;
13470 error ("Can't notify window manager of window withdrawal");
13472 #else /* ! defined (HAVE_X11R4) */
13474 /* Tell the window manager what we're going to do. */
13475 if (! EQ (Vx_no_window_manager
, Qt
))
13479 unmap
.xunmap
.type
= UnmapNotify
;
13480 unmap
.xunmap
.window
= window
;
13481 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
13482 unmap
.xunmap
.from_configure
= False
;
13483 if (! XSendEvent (FRAME_X_DISPLAY (f
),
13484 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
13486 SubstructureRedirectMaskSubstructureNotifyMask
,
13489 UNBLOCK_INPUT_RESIGNAL
;
13490 error ("Can't notify window manager of withdrawal");
13494 /* Unmap the window ourselves. Cheeky! */
13495 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
13496 #endif /* ! defined (HAVE_X11R4) */
13498 /* We can't distinguish this from iconification
13499 just by the event that we get from the server.
13500 So we can't win using the usual strategy of letting
13501 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13502 and synchronize with the server to make sure we agree. */
13504 FRAME_ICONIFIED_P (f
) = 0;
13505 f
->async_visible
= 0;
13506 f
->async_iconified
= 0;
13513 /* Change window state from mapped to iconified. */
13516 x_iconify_frame (f
)
13522 /* Don't keep the highlight on an invisible frame. */
13523 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
13524 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
13526 if (f
->async_iconified
)
13531 FRAME_SAMPLE_VISIBILITY (f
);
13533 type
= x_icon_type (f
);
13535 x_bitmap_icon (f
, type
);
13537 #ifdef USE_X_TOOLKIT
13539 if (! FRAME_VISIBLE_P (f
))
13541 if (! EQ (Vx_no_window_manager
, Qt
))
13542 x_wm_set_window_state (f
, IconicState
);
13543 /* This was XtPopup, but that did nothing for an iconified frame. */
13544 XtMapWidget (f
->output_data
.x
->widget
);
13545 /* The server won't give us any event to indicate
13546 that an invisible frame was changed to an icon,
13547 so we have to record it here. */
13550 f
->async_iconified
= 1;
13551 f
->async_visible
= 0;
13556 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
13557 XtWindow (f
->output_data
.x
->widget
),
13558 DefaultScreen (FRAME_X_DISPLAY (f
)));
13562 error ("Can't notify window manager of iconification");
13564 f
->async_iconified
= 1;
13565 f
->async_visible
= 0;
13569 XFlush (FRAME_X_DISPLAY (f
));
13571 #else /* not USE_X_TOOLKIT */
13573 /* Make sure the X server knows where the window should be positioned,
13574 in case the user deiconifies with the window manager. */
13575 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
13576 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
13578 /* Since we don't know which revision of X we're running, we'll use both
13579 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13581 /* X11R4: send a ClientMessage to the window manager using the
13582 WM_CHANGE_STATE type. */
13586 message
.xclient
.window
= FRAME_X_WINDOW (f
);
13587 message
.xclient
.type
= ClientMessage
;
13588 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
13589 message
.xclient
.format
= 32;
13590 message
.xclient
.data
.l
[0] = IconicState
;
13592 if (! XSendEvent (FRAME_X_DISPLAY (f
),
13593 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
13595 SubstructureRedirectMask
| SubstructureNotifyMask
,
13598 UNBLOCK_INPUT_RESIGNAL
;
13599 error ("Can't notify window manager of iconification");
13603 /* X11R3: set the initial_state field of the window manager hints to
13605 x_wm_set_window_state (f
, IconicState
);
13607 if (!FRAME_VISIBLE_P (f
))
13609 /* If the frame was withdrawn, before, we must map it. */
13610 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13613 f
->async_iconified
= 1;
13614 f
->async_visible
= 0;
13616 XFlush (FRAME_X_DISPLAY (f
));
13618 #endif /* not USE_X_TOOLKIT */
13622 /* Free X resources of frame F. */
13625 x_free_frame_resources (f
)
13628 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13630 struct scroll_bar
*b
;
13634 /* If a display connection is dead, don't try sending more
13635 commands to the X server. */
13636 if (dpyinfo
->display
)
13638 if (f
->output_data
.x
->icon_desc
)
13639 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
13641 #ifdef USE_X_TOOLKIT
13642 /* Explicitly destroy the scroll bars of the frame. Without
13643 this, we get "BadDrawable" errors from the toolkit later on,
13644 presumably from expose events generated for the disappearing
13645 toolkit scroll bars. */
13646 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
13648 b
= XSCROLL_BAR (bar
);
13649 x_scroll_bar_remove (b
);
13655 free_frame_xic (f
);
13658 #ifdef USE_X_TOOLKIT
13659 if (f
->output_data
.x
->widget
)
13661 XtDestroyWidget (f
->output_data
.x
->widget
);
13662 f
->output_data
.x
->widget
= NULL
;
13664 /* Tooltips don't have widgets, only a simple X window, even if
13665 we are using a toolkit. */
13666 else if (FRAME_X_WINDOW (f
))
13667 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13669 free_frame_menubar (f
);
13670 #else /* !USE_X_TOOLKIT */
13671 if (FRAME_X_WINDOW (f
))
13672 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
13673 #endif /* !USE_X_TOOLKIT */
13675 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
13676 unload_color (f
, f
->output_data
.x
->background_pixel
);
13677 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
13678 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
13679 unload_color (f
, f
->output_data
.x
->border_pixel
);
13680 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
13682 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
13683 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
13684 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
13685 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
13686 #ifdef USE_TOOLKIT_SCROLL_BARS
13687 /* Scrollbar shadow colors. */
13688 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
13689 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
13690 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
13691 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
13692 #endif /* USE_TOOLKIT_SCROLL_BARS */
13693 if (f
->output_data
.x
->white_relief
.allocated_p
)
13694 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
13695 if (f
->output_data
.x
->black_relief
.allocated_p
)
13696 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
13698 if (FRAME_FACE_CACHE (f
))
13699 free_frame_faces (f
);
13702 XFlush (FRAME_X_DISPLAY (f
));
13705 if (f
->output_data
.x
->saved_menu_event
)
13706 xfree (f
->output_data
.x
->saved_menu_event
);
13708 xfree (f
->output_data
.x
);
13709 f
->output_data
.x
= NULL
;
13711 if (f
== dpyinfo
->x_focus_frame
)
13712 dpyinfo
->x_focus_frame
= 0;
13713 if (f
== dpyinfo
->x_focus_event_frame
)
13714 dpyinfo
->x_focus_event_frame
= 0;
13715 if (f
== dpyinfo
->x_highlight_frame
)
13716 dpyinfo
->x_highlight_frame
= 0;
13718 if (f
== dpyinfo
->mouse_face_mouse_frame
)
13720 dpyinfo
->mouse_face_beg_row
13721 = dpyinfo
->mouse_face_beg_col
= -1;
13722 dpyinfo
->mouse_face_end_row
13723 = dpyinfo
->mouse_face_end_col
= -1;
13724 dpyinfo
->mouse_face_window
= Qnil
;
13725 dpyinfo
->mouse_face_deferred_gc
= 0;
13726 dpyinfo
->mouse_face_mouse_frame
= 0;
13733 /* Destroy the X window of frame F. */
13736 x_destroy_window (f
)
13739 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13741 /* If a display connection is dead, don't try sending more
13742 commands to the X server. */
13743 if (dpyinfo
->display
!= 0)
13744 x_free_frame_resources (f
);
13746 dpyinfo
->reference_count
--;
13750 /* Setting window manager hints. */
13752 /* Set the normal size hints for the window manager, for frame F.
13753 FLAGS is the flags word to use--or 0 meaning preserve the flags
13754 that the window now has.
13755 If USER_POSITION is nonzero, we set the USPosition
13756 flag (this is useful when FLAGS is 0). */
13759 x_wm_set_size_hint (f
, flags
, user_position
)
13764 XSizeHints size_hints
;
13766 #ifdef USE_X_TOOLKIT
13769 Dimension widget_width
, widget_height
;
13770 Window window
= XtWindow (f
->output_data
.x
->widget
);
13771 #else /* not USE_X_TOOLKIT */
13772 Window window
= FRAME_X_WINDOW (f
);
13773 #endif /* not USE_X_TOOLKIT */
13775 /* Setting PMaxSize caused various problems. */
13776 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
13778 size_hints
.x
= f
->output_data
.x
->left_pos
;
13779 size_hints
.y
= f
->output_data
.x
->top_pos
;
13781 #ifdef USE_X_TOOLKIT
13782 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
13783 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
13784 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
13785 size_hints
.height
= widget_height
;
13786 size_hints
.width
= widget_width
;
13787 #else /* not USE_X_TOOLKIT */
13788 size_hints
.height
= PIXEL_HEIGHT (f
);
13789 size_hints
.width
= PIXEL_WIDTH (f
);
13790 #endif /* not USE_X_TOOLKIT */
13792 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
13793 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
13794 size_hints
.max_width
13795 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
13796 size_hints
.max_height
13797 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
13799 /* Calculate the base and minimum sizes.
13801 (When we use the X toolkit, we don't do it here.
13802 Instead we copy the values that the widgets are using, below.) */
13803 #ifndef USE_X_TOOLKIT
13805 int base_width
, base_height
;
13806 int min_rows
= 0, min_cols
= 0;
13808 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
13809 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
13811 check_frame_size (f
, &min_rows
, &min_cols
);
13813 /* The window manager uses the base width hints to calculate the
13814 current number of rows and columns in the frame while
13815 resizing; min_width and min_height aren't useful for this
13816 purpose, since they might not give the dimensions for a
13817 zero-row, zero-column frame.
13819 We use the base_width and base_height members if we have
13820 them; otherwise, we set the min_width and min_height members
13821 to the size for a zero x zero frame. */
13824 size_hints
.flags
|= PBaseSize
;
13825 size_hints
.base_width
= base_width
;
13826 size_hints
.base_height
= base_height
;
13827 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
13828 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
13830 size_hints
.min_width
= base_width
;
13831 size_hints
.min_height
= base_height
;
13835 /* If we don't need the old flags, we don't need the old hint at all. */
13838 size_hints
.flags
|= flags
;
13841 #endif /* not USE_X_TOOLKIT */
13844 XSizeHints hints
; /* Sometimes I hate X Windows... */
13845 long supplied_return
;
13849 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
13852 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
13855 #ifdef USE_X_TOOLKIT
13856 size_hints
.base_height
= hints
.base_height
;
13857 size_hints
.base_width
= hints
.base_width
;
13858 size_hints
.min_height
= hints
.min_height
;
13859 size_hints
.min_width
= hints
.min_width
;
13863 size_hints
.flags
|= flags
;
13868 if (hints
.flags
& PSize
)
13869 size_hints
.flags
|= PSize
;
13870 if (hints
.flags
& PPosition
)
13871 size_hints
.flags
|= PPosition
;
13872 if (hints
.flags
& USPosition
)
13873 size_hints
.flags
|= USPosition
;
13874 if (hints
.flags
& USSize
)
13875 size_hints
.flags
|= USSize
;
13879 #ifndef USE_X_TOOLKIT
13884 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
13885 size_hints
.flags
|= PWinGravity
;
13889 size_hints
.flags
&= ~ PPosition
;
13890 size_hints
.flags
|= USPosition
;
13892 #endif /* PWinGravity */
13895 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
13897 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
13901 /* Used for IconicState or NormalState */
13904 x_wm_set_window_state (f
, state
)
13908 #ifdef USE_X_TOOLKIT
13911 XtSetArg (al
[0], XtNinitialState
, state
);
13912 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
13913 #else /* not USE_X_TOOLKIT */
13914 Window window
= FRAME_X_WINDOW (f
);
13916 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
13917 f
->output_data
.x
->wm_hints
.initial_state
= state
;
13919 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13920 #endif /* not USE_X_TOOLKIT */
13924 x_wm_set_icon_pixmap (f
, pixmap_id
)
13928 Pixmap icon_pixmap
;
13930 #ifndef USE_X_TOOLKIT
13931 Window window
= FRAME_X_WINDOW (f
);
13936 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
13937 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
13941 /* It seems there is no way to turn off use of an icon pixmap.
13942 The following line does it, only if no icon has yet been created,
13943 for some window managers. But with mwm it crashes.
13944 Some people say it should clear the IconPixmapHint bit in this case,
13945 but that doesn't work, and the X consortium said it isn't the
13946 right thing at all. Since there is no way to win,
13947 best to explicitly give up. */
13949 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
13955 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13959 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
13960 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
13963 #else /* not USE_X_TOOLKIT */
13965 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
13966 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13968 #endif /* not USE_X_TOOLKIT */
13972 x_wm_set_icon_position (f
, icon_x
, icon_y
)
13974 int icon_x
, icon_y
;
13976 #ifdef USE_X_TOOLKIT
13977 Window window
= XtWindow (f
->output_data
.x
->widget
);
13979 Window window
= FRAME_X_WINDOW (f
);
13982 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
13983 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
13984 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
13986 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
13990 /***********************************************************************
13992 ***********************************************************************/
13994 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13997 x_get_font_info (f
, font_idx
)
14001 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
14005 /* Return a list of names of available fonts matching PATTERN on frame F.
14007 If SIZE is > 0, it is the size (maximum bounds width) of fonts
14010 SIZE < 0 means include scalable fonts.
14012 Frame F null means we have not yet created any frame on X, and
14013 consult the first display in x_display_list. MAXNAMES sets a limit
14014 on how many fonts to match. */
14017 x_list_fonts (f
, pattern
, size
, maxnames
)
14019 Lisp_Object pattern
;
14023 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
14024 Lisp_Object tem
, second_best
;
14025 struct x_display_info
*dpyinfo
14026 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
14027 Display
*dpy
= dpyinfo
->display
;
14028 int try_XLoadQueryFont
= 0;
14030 int allow_scalable_fonts_p
= 0;
14034 allow_scalable_fonts_p
= 1;
14038 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
14039 if (NILP (patterns
))
14040 patterns
= Fcons (pattern
, Qnil
);
14042 if (maxnames
== 1 && !size
)
14043 /* We can return any single font matching PATTERN. */
14044 try_XLoadQueryFont
= 1;
14046 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
14049 char **names
= NULL
;
14051 pattern
= XCAR (patterns
);
14052 /* See if we cached the result for this particular query.
14053 The cache is an alist of the form:
14054 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
14055 tem
= XCDR (dpyinfo
->name_list_element
);
14056 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
14057 allow_scalable_fonts_p
? Qt
: Qnil
);
14058 list
= Fassoc (key
, tem
);
14061 list
= Fcdr_safe (list
);
14062 /* We have a cashed list. Don't have to get the list again. */
14066 /* At first, put PATTERN in the cache. */
14069 count
= x_catch_errors (dpy
);
14071 if (try_XLoadQueryFont
)
14074 unsigned long value
;
14076 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
14077 if (x_had_errors_p (dpy
))
14079 /* This error is perhaps due to insufficient memory on X
14080 server. Let's just ignore it. */
14082 x_clear_errors (dpy
);
14086 && XGetFontProperty (font
, XA_FONT
, &value
))
14088 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
14089 int len
= strlen (name
);
14092 /* If DXPC (a Differential X Protocol Compressor)
14093 Ver.3.7 is running, XGetAtomName will return null
14094 string. We must avoid such a name. */
14096 try_XLoadQueryFont
= 0;
14100 names
= (char **) alloca (sizeof (char *));
14101 /* Some systems only allow alloca assigned to a
14103 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
14104 bcopy (name
, names
[0], len
+ 1);
14109 try_XLoadQueryFont
= 0;
14112 XFreeFont (dpy
, font
);
14115 if (!try_XLoadQueryFont
)
14117 /* We try at least 10 fonts because XListFonts will return
14118 auto-scaled fonts at the head. */
14119 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
14121 if (x_had_errors_p (dpy
))
14123 /* This error is perhaps due to insufficient memory on X
14124 server. Let's just ignore it. */
14126 x_clear_errors (dpy
);
14130 x_uncatch_errors (dpy
, count
);
14137 /* Make a list of all the fonts we got back.
14138 Store that in the font cache for the display. */
14139 for (i
= 0; i
< num_fonts
; i
++)
14142 char *p
= names
[i
];
14143 int average_width
= -1, dashes
= 0;
14145 /* Count the number of dashes in NAMES[I]. If there are
14146 14 dashes, and the field value following 12th dash
14147 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
14148 is usually too ugly to be used for editing. Let's
14154 if (dashes
== 7) /* PIXEL_SIZE field */
14156 else if (dashes
== 12) /* AVERAGE_WIDTH field */
14157 average_width
= atoi (p
);
14160 if (allow_scalable_fonts_p
14161 || dashes
< 14 || average_width
!= 0)
14163 tem
= build_string (names
[i
]);
14164 if (NILP (Fassoc (tem
, list
)))
14166 if (STRINGP (Vx_pixel_size_width_font_regexp
)
14167 && ((fast_c_string_match_ignore_case
14168 (Vx_pixel_size_width_font_regexp
, names
[i
]))
14170 /* We can set the value of PIXEL_SIZE to the
14171 width of this font. */
14172 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
14174 /* For the moment, width is not known. */
14175 list
= Fcons (Fcons (tem
, Qnil
), list
);
14180 if (!try_XLoadQueryFont
)
14183 XFreeFontNames (names
);
14188 /* Now store the result in the cache. */
14189 XSETCDR (dpyinfo
->name_list_element
,
14190 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
14193 if (NILP (list
)) continue; /* Try the remaining alternatives. */
14195 newlist
= second_best
= Qnil
;
14196 /* Make a list of the fonts that have the right width. */
14197 for (; CONSP (list
); list
= XCDR (list
))
14203 if (!CONSP (tem
) || NILP (XCAR (tem
)))
14207 newlist
= Fcons (XCAR (tem
), newlist
);
14211 if (!INTEGERP (XCDR (tem
)))
14213 /* Since we have not yet known the size of this font, we
14214 must try slow function call XLoadQueryFont. */
14215 XFontStruct
*thisinfo
;
14218 count
= x_catch_errors (dpy
);
14219 thisinfo
= XLoadQueryFont (dpy
,
14220 SDATA (XCAR (tem
)));
14221 if (x_had_errors_p (dpy
))
14223 /* This error is perhaps due to insufficient memory on X
14224 server. Let's just ignore it. */
14226 x_clear_errors (dpy
);
14228 x_uncatch_errors (dpy
, count
);
14234 (thisinfo
->min_bounds
.width
== 0
14236 : make_number (thisinfo
->max_bounds
.width
)));
14238 XFreeFont (dpy
, thisinfo
);
14242 /* For unknown reason, the previous call of XListFont had
14243 returned a font which can't be opened. Record the size
14244 as 0 not to try to open it again. */
14245 XSETCDR (tem
, make_number (0));
14248 found_size
= XINT (XCDR (tem
));
14249 if (found_size
== size
)
14250 newlist
= Fcons (XCAR (tem
), newlist
);
14251 else if (found_size
> 0)
14253 if (NILP (second_best
))
14255 else if (found_size
< size
)
14257 if (XINT (XCDR (second_best
)) > size
14258 || XINT (XCDR (second_best
)) < found_size
)
14263 if (XINT (XCDR (second_best
)) > size
14264 && XINT (XCDR (second_best
)) > found_size
)
14269 if (!NILP (newlist
))
14271 else if (!NILP (second_best
))
14273 newlist
= Fcons (XCAR (second_best
), Qnil
);
14284 /* Check that FONT is valid on frame F. It is if it can be found in F's
14288 x_check_font (f
, font
)
14293 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14295 xassert (font
!= NULL
);
14297 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14298 if (dpyinfo
->font_table
[i
].name
14299 && font
== dpyinfo
->font_table
[i
].font
)
14302 xassert (i
< dpyinfo
->n_fonts
);
14305 #endif /* GLYPH_DEBUG != 0 */
14307 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14308 Note: There are (broken) X fonts out there with invalid XFontStruct
14309 min_bounds contents. For example, handa@etl.go.jp reports that
14310 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14311 have font->min_bounds.width == 0. */
14314 x_font_min_bounds (font
, w
, h
)
14318 *h
= FONT_HEIGHT (font
);
14319 *w
= font
->min_bounds
.width
;
14321 /* Try to handle the case where FONT->min_bounds has invalid
14322 contents. Since the only font known to have invalid min_bounds
14323 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14325 *w
= font
->max_bounds
.width
;
14329 /* Compute the smallest character width and smallest font height over
14330 all fonts available on frame F. Set the members smallest_char_width
14331 and smallest_font_height in F's x_display_info structure to
14332 the values computed. Value is non-zero if smallest_font_height or
14333 smallest_char_width become smaller than they were before. */
14336 x_compute_min_glyph_bounds (f
)
14340 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14342 int old_width
= dpyinfo
->smallest_char_width
;
14343 int old_height
= dpyinfo
->smallest_font_height
;
14345 dpyinfo
->smallest_font_height
= 100000;
14346 dpyinfo
->smallest_char_width
= 100000;
14348 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
14349 if (dpyinfo
->font_table
[i
].name
)
14351 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
14354 font
= (XFontStruct
*) fontp
->font
;
14355 xassert (font
!= (XFontStruct
*) ~0);
14356 x_font_min_bounds (font
, &w
, &h
);
14358 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
14359 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
14362 xassert (dpyinfo
->smallest_char_width
> 0
14363 && dpyinfo
->smallest_font_height
> 0);
14365 return (dpyinfo
->n_fonts
== 1
14366 || dpyinfo
->smallest_char_width
< old_width
14367 || dpyinfo
->smallest_font_height
< old_height
);
14371 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14372 pointer to the structure font_info while allocating it dynamically.
14373 If SIZE is 0, load any size of font.
14374 If loading is failed, return NULL. */
14377 x_load_font (f
, fontname
, size
)
14379 register char *fontname
;
14382 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14383 Lisp_Object font_names
;
14386 /* Get a list of all the fonts that match this name. Once we
14387 have a list of matching fonts, we compare them against the fonts
14388 we already have by comparing names. */
14389 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
14391 if (!NILP (font_names
))
14396 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14397 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
14398 if (dpyinfo
->font_table
[i
].name
14399 && (!strcmp (dpyinfo
->font_table
[i
].name
,
14400 SDATA (XCAR (tail
)))
14401 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
14402 SDATA (XCAR (tail
)))))
14403 return (dpyinfo
->font_table
+ i
);
14406 /* Load the font and add it to the table. */
14410 struct font_info
*fontp
;
14411 unsigned long value
;
14414 /* If we have found fonts by x_list_font, load one of them. If
14415 not, we still try to load a font by the name given as FONTNAME
14416 because XListFonts (called in x_list_font) of some X server has
14417 a bug of not finding a font even if the font surely exists and
14418 is loadable by XLoadQueryFont. */
14419 if (size
> 0 && !NILP (font_names
))
14420 fontname
= (char *) SDATA (XCAR (font_names
));
14423 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
14424 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
14425 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
14427 /* This error is perhaps due to insufficient memory on X
14428 server. Let's just ignore it. */
14430 x_clear_errors (FRAME_X_DISPLAY (f
));
14432 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
14437 /* Find a free slot in the font table. */
14438 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
14439 if (dpyinfo
->font_table
[i
].name
== NULL
)
14442 /* If no free slot found, maybe enlarge the font table. */
14443 if (i
== dpyinfo
->n_fonts
14444 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
14447 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
14448 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
14449 dpyinfo
->font_table
14450 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
14453 fontp
= dpyinfo
->font_table
+ i
;
14454 if (i
== dpyinfo
->n_fonts
)
14455 ++dpyinfo
->n_fonts
;
14457 /* Now fill in the slots of *FONTP. */
14459 fontp
->font
= font
;
14460 fontp
->font_idx
= i
;
14461 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
14462 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
14464 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14466 if (XGetFontProperty (font
, XA_FONT
, &value
))
14468 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
14472 /* Count the number of dashes in the "full name".
14473 If it is too few, this isn't really the font's full name,
14475 In X11R4, the fonts did not come with their canonical names
14486 full_name
= (char *) xmalloc (p
- name
+ 1);
14487 bcopy (name
, full_name
, p
- name
+ 1);
14493 if (full_name
!= 0)
14494 fontp
->full_name
= full_name
;
14496 fontp
->full_name
= fontp
->name
;
14498 fontp
->size
= font
->max_bounds
.width
;
14499 fontp
->height
= FONT_HEIGHT (font
);
14501 if (NILP (font_names
))
14503 /* We come here because of a bug of XListFonts mentioned at
14504 the head of this block. Let's store this information in
14505 the cache for x_list_fonts. */
14506 Lisp_Object lispy_name
= build_string (fontname
);
14507 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
14508 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
14511 XSETCDR (dpyinfo
->name_list_element
,
14513 Fcons (Fcons (lispy_full_name
,
14514 make_number (fontp
->size
)),
14516 XCDR (dpyinfo
->name_list_element
)));
14519 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
14521 XSETCDR (dpyinfo
->name_list_element
,
14523 Fcons (Fcons (lispy_full_name
,
14524 make_number (fontp
->size
)),
14526 XCDR (dpyinfo
->name_list_element
)));
14530 /* The slot `encoding' specifies how to map a character
14531 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14532 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14533 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14534 2:0xA020..0xFF7F). For the moment, we don't know which charset
14535 uses this font. So, we set information in fontp->encoding[1]
14536 which is never used by any charset. If mapping can't be
14537 decided, set FONT_ENCODING_NOT_DECIDED. */
14539 = (font
->max_byte1
== 0
14541 ? (font
->min_char_or_byte2
< 0x80
14542 ? (font
->max_char_or_byte2
< 0x80
14543 ? 0 /* 0x20..0x7F */
14544 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
14545 : 1) /* 0xA0..0xFF */
14547 : (font
->min_byte1
< 0x80
14548 ? (font
->max_byte1
< 0x80
14549 ? (font
->min_char_or_byte2
< 0x80
14550 ? (font
->max_char_or_byte2
< 0x80
14551 ? 0 /* 0x2020..0x7F7F */
14552 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
14553 : 3) /* 0x20A0..0x7FFF */
14554 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
14555 : (font
->min_char_or_byte2
< 0x80
14556 ? (font
->max_char_or_byte2
< 0x80
14557 ? 2 /* 0xA020..0xFF7F */
14558 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
14559 : 1))); /* 0xA0A0..0xFFFF */
14561 fontp
->baseline_offset
14562 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
14563 ? (long) value
: 0);
14564 fontp
->relative_compose
14565 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
14566 ? (long) value
: 0);
14567 fontp
->default_ascent
14568 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
14569 ? (long) value
: 0);
14571 /* Set global flag fonts_changed_p to non-zero if the font loaded
14572 has a character with a smaller width than any other character
14573 before, or if the font loaded has a smaller height than any
14574 other font loaded before. If this happens, it will make a
14575 glyph matrix reallocation necessary. */
14576 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
14583 /* Return a pointer to struct font_info of a font named FONTNAME for
14584 frame F. If no such font is loaded, return NULL. */
14587 x_query_font (f
, fontname
)
14589 register char *fontname
;
14591 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
14594 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
14595 if (dpyinfo
->font_table
[i
].name
14596 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
14597 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
14598 return (dpyinfo
->font_table
+ i
);
14603 /* Find a CCL program for a font specified by FONTP, and set the member
14604 `encoder' of the structure. */
14607 x_find_ccl_program (fontp
)
14608 struct font_info
*fontp
;
14610 Lisp_Object list
, elt
;
14613 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
14617 && STRINGP (XCAR (elt
))
14618 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
14620 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
14627 struct ccl_program
*ccl
14628 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
14630 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
14633 fontp
->font_encoder
= ccl
;
14639 /***********************************************************************
14641 ***********************************************************************/
14643 #ifdef USE_X_TOOLKIT
14644 static XrmOptionDescRec emacs_options
[] = {
14645 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
14646 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
14648 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14649 XrmoptionSepArg
, NULL
},
14650 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
14652 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14653 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14654 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
14655 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
14656 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
14657 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
14658 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
14660 #endif /* USE_X_TOOLKIT */
14662 static int x_initialized
;
14664 #ifdef MULTI_KBOARD
14665 /* Test whether two display-name strings agree up to the dot that separates
14666 the screen number from the server number. */
14668 same_x_server (name1
, name2
)
14669 const char *name1
, *name2
;
14671 int seen_colon
= 0;
14672 const unsigned char *system_name
= SDATA (Vsystem_name
);
14673 int system_name_length
= strlen (system_name
);
14674 int length_until_period
= 0;
14676 while (system_name
[length_until_period
] != 0
14677 && system_name
[length_until_period
] != '.')
14678 length_until_period
++;
14680 /* Treat `unix' like an empty host name. */
14681 if (! strncmp (name1
, "unix:", 5))
14683 if (! strncmp (name2
, "unix:", 5))
14685 /* Treat this host's name like an empty host name. */
14686 if (! strncmp (name1
, system_name
, system_name_length
)
14687 && name1
[system_name_length
] == ':')
14688 name1
+= system_name_length
;
14689 if (! strncmp (name2
, system_name
, system_name_length
)
14690 && name2
[system_name_length
] == ':')
14691 name2
+= system_name_length
;
14692 /* Treat this host's domainless name like an empty host name. */
14693 if (! strncmp (name1
, system_name
, length_until_period
)
14694 && name1
[length_until_period
] == ':')
14695 name1
+= length_until_period
;
14696 if (! strncmp (name2
, system_name
, length_until_period
)
14697 && name2
[length_until_period
] == ':')
14698 name2
+= length_until_period
;
14700 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
14704 if (seen_colon
&& *name1
== '.')
14708 && (*name1
== '.' || *name1
== '\0')
14709 && (*name2
== '.' || *name2
== '\0'));
14713 struct x_display_info
*
14714 x_term_init (display_name
, xrm_option
, resource_name
)
14715 Lisp_Object display_name
;
14717 char *resource_name
;
14721 struct x_display_info
*dpyinfo
;
14726 if (!x_initialized
)
14732 #ifdef USE_X_TOOLKIT
14733 /* weiner@footloose.sps.mot.com reports that this causes
14735 X protocol error: BadAtom (invalid Atom parameter)
14736 on protocol request 18skiloaf.
14737 So let's not use it until R6. */
14738 #ifdef HAVE_X11XTR6
14739 XtSetLanguageProc (NULL
, NULL
, NULL
);
14750 argv
[argc
++] = "-xrm";
14751 argv
[argc
++] = xrm_option
;
14754 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
14755 resource_name
, EMACS_CLASS
,
14756 emacs_options
, XtNumber (emacs_options
),
14760 #ifdef HAVE_X11XTR6
14761 /* I think this is to compensate for XtSetLanguageProc. */
14766 #else /* not USE_X_TOOLKIT */
14768 XSetLocaleModifiers ("");
14770 dpy
= XOpenDisplay (SDATA (display_name
));
14771 #endif /* not USE_X_TOOLKIT */
14773 /* Detect failure. */
14780 /* We have definitely succeeded. Record the new connection. */
14782 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
14783 bzero (dpyinfo
, sizeof *dpyinfo
);
14785 #ifdef MULTI_KBOARD
14787 struct x_display_info
*share
;
14790 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
14791 share
= share
->next
, tail
= XCDR (tail
))
14792 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
14793 SDATA (display_name
)))
14796 dpyinfo
->kboard
= share
->kboard
;
14799 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
14800 init_kboard (dpyinfo
->kboard
);
14801 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
14803 char *vendor
= ServerVendor (dpy
);
14805 dpyinfo
->kboard
->Vsystem_key_alist
14806 = call1 (Qvendor_specific_keysyms
,
14807 build_string (vendor
? vendor
: ""));
14811 dpyinfo
->kboard
->next_kboard
= all_kboards
;
14812 all_kboards
= dpyinfo
->kboard
;
14813 /* Don't let the initial kboard remain current longer than necessary.
14814 That would cause problems if a file loaded on startup tries to
14815 prompt in the mini-buffer. */
14816 if (current_kboard
== initial_kboard
)
14817 current_kboard
= dpyinfo
->kboard
;
14819 dpyinfo
->kboard
->reference_count
++;
14823 /* Put this display on the chain. */
14824 dpyinfo
->next
= x_display_list
;
14825 x_display_list
= dpyinfo
;
14827 /* Put it on x_display_name_list as well, to keep them parallel. */
14828 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
14829 x_display_name_list
);
14830 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
14832 dpyinfo
->display
= dpy
;
14835 XSetAfterFunction (x_current_display
, x_trace_wire
);
14839 = (char *) xmalloc (SBYTES (Vinvocation_name
)
14840 + SBYTES (Vsystem_name
)
14842 sprintf (dpyinfo
->x_id_name
, "%s@%s",
14843 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
14845 /* Figure out which modifier bits mean what. */
14846 x_find_modifier_meanings (dpyinfo
);
14848 /* Get the scroll bar cursor. */
14849 dpyinfo
->vertical_scroll_bar_cursor
14850 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
14852 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
14853 resource_name
, EMACS_CLASS
);
14854 #ifdef HAVE_XRMSETDATABASE
14855 XrmSetDatabase (dpyinfo
->display
, xrdb
);
14857 dpyinfo
->display
->db
= xrdb
;
14859 /* Put the rdb where we can find it in a way that works on
14861 dpyinfo
->xrdb
= xrdb
;
14863 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
14864 DefaultScreen (dpyinfo
->display
));
14865 select_visual (dpyinfo
);
14866 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
14867 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
14868 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
14869 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
14870 dpyinfo
->grabbed
= 0;
14871 dpyinfo
->reference_count
= 0;
14872 dpyinfo
->icon_bitmap_id
= -1;
14873 dpyinfo
->font_table
= NULL
;
14874 dpyinfo
->n_fonts
= 0;
14875 dpyinfo
->font_table_size
= 0;
14876 dpyinfo
->bitmaps
= 0;
14877 dpyinfo
->bitmaps_size
= 0;
14878 dpyinfo
->bitmaps_last
= 0;
14879 dpyinfo
->scratch_cursor_gc
= 0;
14880 dpyinfo
->mouse_face_mouse_frame
= 0;
14881 dpyinfo
->mouse_face_deferred_gc
= 0;
14882 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
14883 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
14884 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
14885 dpyinfo
->mouse_face_window
= Qnil
;
14886 dpyinfo
->mouse_face_overlay
= Qnil
;
14887 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
14888 dpyinfo
->mouse_face_defer
= 0;
14889 dpyinfo
->mouse_face_hidden
= 0;
14890 dpyinfo
->x_focus_frame
= 0;
14891 dpyinfo
->x_focus_event_frame
= 0;
14892 dpyinfo
->x_highlight_frame
= 0;
14893 dpyinfo
->image_cache
= make_image_cache ();
14895 /* See if a private colormap is requested. */
14896 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
14898 if (dpyinfo
->visual
->class == PseudoColor
)
14901 value
= display_x_get_resource (dpyinfo
,
14902 build_string ("privateColormap"),
14903 build_string ("PrivateColormap"),
14905 if (STRINGP (value
)
14906 && (!strcmp (SDATA (value
), "true")
14907 || !strcmp (SDATA (value
), "on")))
14908 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
14912 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
14913 dpyinfo
->visual
, AllocNone
);
14916 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
14917 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
14918 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
14919 dpyinfo
->resy
= pixels
* 25.4 / mm
;
14920 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
14921 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
14922 dpyinfo
->resx
= pixels
* 25.4 / mm
;
14925 dpyinfo
->Xatom_wm_protocols
14926 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
14927 dpyinfo
->Xatom_wm_take_focus
14928 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
14929 dpyinfo
->Xatom_wm_save_yourself
14930 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
14931 dpyinfo
->Xatom_wm_delete_window
14932 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
14933 dpyinfo
->Xatom_wm_change_state
14934 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
14935 dpyinfo
->Xatom_wm_configure_denied
14936 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
14937 dpyinfo
->Xatom_wm_window_moved
14938 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
14939 dpyinfo
->Xatom_editres
14940 = XInternAtom (dpyinfo
->display
, "Editres", False
);
14941 dpyinfo
->Xatom_CLIPBOARD
14942 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
14943 dpyinfo
->Xatom_TIMESTAMP
14944 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
14945 dpyinfo
->Xatom_TEXT
14946 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
14947 dpyinfo
->Xatom_COMPOUND_TEXT
14948 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
14949 dpyinfo
->Xatom_UTF8_STRING
14950 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
14951 dpyinfo
->Xatom_DELETE
14952 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
14953 dpyinfo
->Xatom_MULTIPLE
14954 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
14955 dpyinfo
->Xatom_INCR
14956 = XInternAtom (dpyinfo
->display
, "INCR", False
);
14957 dpyinfo
->Xatom_EMACS_TMP
14958 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
14959 dpyinfo
->Xatom_TARGETS
14960 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
14961 dpyinfo
->Xatom_NULL
14962 = XInternAtom (dpyinfo
->display
, "NULL", False
);
14963 dpyinfo
->Xatom_ATOM_PAIR
14964 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
14965 /* For properties of font. */
14966 dpyinfo
->Xatom_PIXEL_SIZE
14967 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
14968 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
14969 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
14970 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
14971 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
14972 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
14973 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
14975 /* Ghostscript support. */
14976 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
14977 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
14979 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
14982 dpyinfo
->cut_buffers_initialized
= 0;
14984 connection
= ConnectionNumber (dpyinfo
->display
);
14985 dpyinfo
->connection
= connection
;
14990 null_bits
[0] = 0x00;
14992 dpyinfo
->null_pixel
14993 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
14994 null_bits
, 1, 1, (long) 0, (long) 0,
14999 extern int gray_bitmap_width
, gray_bitmap_height
;
15000 extern char *gray_bitmap_bits
;
15002 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
15004 gray_bitmap_width
, gray_bitmap_height
,
15005 (unsigned long) 1, (unsigned long) 0, 1);
15009 xim_initialize (dpyinfo
, resource_name
);
15012 #ifdef subprocesses
15013 /* This is only needed for distinguishing keyboard and process input. */
15014 if (connection
!= 0)
15015 add_keyboard_wait_descriptor (connection
);
15018 #ifndef F_SETOWN_BUG
15020 #ifdef F_SETOWN_SOCK_NEG
15021 /* stdin is a socket here */
15022 fcntl (connection
, F_SETOWN
, -getpid ());
15023 #else /* ! defined (F_SETOWN_SOCK_NEG) */
15024 fcntl (connection
, F_SETOWN
, getpid ());
15025 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
15026 #endif /* ! defined (F_SETOWN) */
15027 #endif /* F_SETOWN_BUG */
15030 if (interrupt_input
)
15031 init_sigio (connection
);
15032 #endif /* ! defined (SIGIO) */
15035 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
15036 /* Make sure that we have a valid font for dialog boxes
15037 so that Xt does not crash. */
15039 Display
*dpy
= dpyinfo
->display
;
15040 XrmValue d
, fr
, to
;
15044 d
.addr
= (XPointer
)&dpy
;
15045 d
.size
= sizeof (Display
*);
15046 fr
.addr
= XtDefaultFont
;
15047 fr
.size
= sizeof (XtDefaultFont
);
15048 to
.size
= sizeof (Font
*);
15049 to
.addr
= (XPointer
)&font
;
15050 count
= x_catch_errors (dpy
);
15051 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
15053 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
15054 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
15055 x_uncatch_errors (dpy
, count
);
15060 /* See if we should run in synchronous mode. This is useful
15061 for debugging X code. */
15064 value
= display_x_get_resource (dpyinfo
,
15065 build_string ("synchronous"),
15066 build_string ("Synchronous"),
15068 if (STRINGP (value
)
15069 && (!strcmp (SDATA (value
), "true")
15070 || !strcmp (SDATA (value
), "on")))
15071 XSynchronize (dpyinfo
->display
, True
);
15079 /* Get rid of display DPYINFO, assuming all frames are already gone,
15080 and without sending any more commands to the X server. */
15083 x_delete_display (dpyinfo
)
15084 struct x_display_info
*dpyinfo
;
15086 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
15088 /* Discard this display from x_display_name_list and x_display_list.
15089 We can't use Fdelq because that can quit. */
15090 if (! NILP (x_display_name_list
)
15091 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
15092 x_display_name_list
= XCDR (x_display_name_list
);
15097 tail
= x_display_name_list
;
15098 while (CONSP (tail
) && CONSP (XCDR (tail
)))
15100 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
15102 XSETCDR (tail
, XCDR (XCDR (tail
)));
15105 tail
= XCDR (tail
);
15109 if (next_noop_dpyinfo
== dpyinfo
)
15110 next_noop_dpyinfo
= dpyinfo
->next
;
15112 if (x_display_list
== dpyinfo
)
15113 x_display_list
= dpyinfo
->next
;
15116 struct x_display_info
*tail
;
15118 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
15119 if (tail
->next
== dpyinfo
)
15120 tail
->next
= tail
->next
->next
;
15123 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
15124 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
15125 XrmDestroyDatabase (dpyinfo
->xrdb
);
15128 #ifdef MULTI_KBOARD
15129 if (--dpyinfo
->kboard
->reference_count
== 0)
15130 delete_kboard (dpyinfo
->kboard
);
15134 xim_close_dpy (dpyinfo
);
15137 xfree (dpyinfo
->font_table
);
15138 xfree (dpyinfo
->x_id_name
);
15139 xfree (dpyinfo
->color_cells
);
15144 /* Set up use of X before we make the first connection. */
15146 static struct redisplay_interface x_redisplay_interface
=
15151 x_clear_end_of_line
,
15153 x_after_update_window_line
,
15154 x_update_window_begin
,
15155 x_update_window_end
,
15158 x_clear_mouse_face
,
15159 x_get_glyph_overhangs
,
15160 x_fix_overlapping_area
15166 rif
= &x_redisplay_interface
;
15168 clear_frame_hook
= x_clear_frame
;
15169 ins_del_lines_hook
= x_ins_del_lines
;
15170 delete_glyphs_hook
= x_delete_glyphs
;
15171 ring_bell_hook
= XTring_bell
;
15172 reset_terminal_modes_hook
= XTreset_terminal_modes
;
15173 set_terminal_modes_hook
= XTset_terminal_modes
;
15174 update_begin_hook
= x_update_begin
;
15175 update_end_hook
= x_update_end
;
15176 set_terminal_window_hook
= XTset_terminal_window
;
15177 read_socket_hook
= XTread_socket
;
15178 frame_up_to_date_hook
= XTframe_up_to_date
;
15179 mouse_position_hook
= XTmouse_position
;
15180 frame_rehighlight_hook
= XTframe_rehighlight
;
15181 frame_raise_lower_hook
= XTframe_raise_lower
;
15182 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
15183 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
15184 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
15185 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
15186 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
15188 scroll_region_ok
= 1; /* we'll scroll partial frames */
15189 char_ins_del_ok
= 1;
15190 line_ins_del_ok
= 1; /* we'll just blt 'em */
15191 fast_clear_end_of_line
= 1; /* X does this well */
15192 memory_below_frame
= 0; /* we don't remember what scrolls
15197 last_tool_bar_item
= -1;
15198 any_help_event_p
= 0;
15200 /* Try to use interrupt input; if we can't, then start polling. */
15201 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
15203 #ifdef USE_X_TOOLKIT
15204 XtToolkitInitialize ();
15206 Xt_app_con
= XtCreateApplicationContext ();
15208 /* Register a converter from strings to pixels, which uses
15209 Emacs' color allocation infrastructure. */
15210 XtAppSetTypeConverter (Xt_app_con
,
15211 XtRString
, XtRPixel
, cvt_string_to_pixel
,
15212 cvt_string_to_pixel_args
,
15213 XtNumber (cvt_string_to_pixel_args
),
15214 XtCacheByDisplay
, cvt_pixel_dtor
);
15216 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
15218 /* Install an asynchronous timer that processes Xt timeout events
15219 every 0.1s. This is necessary because some widget sets use
15220 timeouts internally, for example the LessTif menu bar, or the
15221 Xaw3d scroll bar. When Xt timouts aren't processed, these
15222 widgets don't behave normally. */
15224 EMACS_TIME interval
;
15225 EMACS_SET_SECS_USECS (interval
, 0, 100000);
15226 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
15230 #ifdef USE_TOOLKIT_SCROLL_BARS
15231 xaw3d_arrow_scroll
= False
;
15232 xaw3d_pick_top
= True
;
15235 /* Note that there is no real way portable across R3/R4 to get the
15236 original error handler. */
15237 XSetErrorHandler (x_error_handler
);
15238 XSetIOErrorHandler (x_io_error_quitter
);
15240 /* Disable Window Change signals; they are handled by X events. */
15242 signal (SIGWINCH
, SIG_DFL
);
15243 #endif /* SIGWINCH */
15245 signal (SIGPIPE
, x_connection_signal
);
15248 x_session_initialize ();
15256 staticpro (&x_error_message_string
);
15257 x_error_message_string
= Qnil
;
15259 staticpro (&x_display_name_list
);
15260 x_display_name_list
= Qnil
;
15262 staticpro (&last_mouse_scroll_bar
);
15263 last_mouse_scroll_bar
= Qnil
;
15265 staticpro (&Qvendor_specific_keysyms
);
15266 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
15268 staticpro (&Qutf_8
);
15269 Qutf_8
= intern ("utf-8");
15270 staticpro (&Qlatin_1
);
15271 Qlatin_1
= intern ("latin-1");
15273 staticpro (&last_mouse_press_frame
);
15274 last_mouse_press_frame
= Qnil
;
15277 staticpro (&help_echo
);
15278 help_echo_object
= Qnil
;
15279 staticpro (&help_echo_object
);
15280 help_echo_window
= Qnil
;
15281 staticpro (&help_echo_window
);
15282 previous_help_echo
= Qnil
;
15283 staticpro (&previous_help_echo
);
15284 help_echo_pos
= -1;
15286 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window
,
15287 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
15288 mouse_autoselect_window
= 0;
15290 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
15291 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
15292 For example, if a block cursor is over a tab, it will be drawn as
15293 wide as that tab on the display. */);
15294 x_stretch_cursor_p
= 0;
15296 DEFVAR_BOOL ("x-use-underline-position-properties",
15297 &x_use_underline_position_properties
,
15298 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15299 nil means ignore them. If you encounter fonts with bogus
15300 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15301 to 4.1, set this to nil. */);
15302 x_use_underline_position_properties
= 1;
15304 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
15305 doc
: /* What X toolkit scroll bars Emacs uses.
15306 A value of nil means Emacs doesn't use X toolkit scroll bars.
15307 Otherwise, value is a symbol describing the X toolkit. */);
15308 #ifdef USE_TOOLKIT_SCROLL_BARS
15310 Vx_toolkit_scroll_bars
= intern ("motif");
15311 #elif defined HAVE_XAW3D
15312 Vx_toolkit_scroll_bars
= intern ("xaw3d");
15314 Vx_toolkit_scroll_bars
= intern ("xaw");
15317 Vx_toolkit_scroll_bars
= Qnil
;
15320 staticpro (&last_mouse_motion_frame
);
15321 last_mouse_motion_frame
= Qnil
;
15323 Qmodifier_value
= intern ("modifier-value");
15324 Qalt
= intern ("alt");
15325 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
15326 Qhyper
= intern ("hyper");
15327 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
15328 Qmeta
= intern ("meta");
15329 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
15330 Qsuper
= intern ("super");
15331 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
15333 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
15334 doc
: /* Which keys Emacs uses for the alt modifier.
15335 This should be one of the symbols `alt', `hyper', `meta', `super'.
15336 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15337 is nil, which is the same as `alt'. */);
15338 Vx_alt_keysym
= Qnil
;
15340 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
15341 doc
: /* Which keys Emacs uses for the hyper modifier.
15342 This should be one of the symbols `alt', `hyper', `meta', `super'.
15343 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15344 default is nil, which is the same as `hyper'. */);
15345 Vx_hyper_keysym
= Qnil
;
15347 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
15348 doc
: /* Which keys Emacs uses for the meta modifier.
15349 This should be one of the symbols `alt', `hyper', `meta', `super'.
15350 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15351 default is nil, which is the same as `meta'. */);
15352 Vx_meta_keysym
= Qnil
;
15354 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
15355 doc
: /* Which keys Emacs uses for the super modifier.
15356 This should be one of the symbols `alt', `hyper', `meta', `super'.
15357 For example, `super' means use the Super_L and Super_R keysyms. The
15358 default is nil, which is the same as `super'. */);
15359 Vx_super_keysym
= Qnil
;
15363 #endif /* HAVE_X_WINDOWS */