1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
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"
88 #include "intervals.h"
93 #include <X11/Shell.h>
96 #ifdef HAVE_SYS_TIME_H
105 extern void free_frame_menubar
P_ ((struct frame
*));
106 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
114 /* Include toolkit specific headers for the scroll bar widget. */
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #include <Xm/ScrollBarP.h>
121 #else /* !USE_MOTIF i.e. use Xaw */
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
138 #endif /* USE_X_TOOLKIT */
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
153 #define min(a,b) ((a) < (b) ? (a) : (b))
156 #define max(a,b) ((a) > (b) ? (a) : (b))
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
164 /* Bitmaps for truncated lines. */
169 LEFT_TRUNCATION_BITMAP
,
170 RIGHT_TRUNCATION_BITMAP
,
171 OVERLAY_ARROW_BITMAP
,
172 CONTINUED_LINE_BITMAP
,
173 CONTINUATION_LINE_BITMAP
,
177 /* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
182 static unsigned char zv_bits
[] = {
183 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
185 /* An arrow like this: `<-'. */
188 #define left_height 8
189 static unsigned char left_bits
[] = {
190 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
192 /* Right truncation arrow bitmap `->'. */
194 #define right_width 8
195 #define right_height 8
196 static unsigned char right_bits
[] = {
197 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
199 /* Marker for continued lines. */
201 #define continued_width 8
202 #define continued_height 8
203 static unsigned char continued_bits
[] = {
204 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
206 /* Marker for continuation lines. */
208 #define continuation_width 8
209 #define continuation_height 8
210 static unsigned char continuation_bits
[] = {
211 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
213 /* Overlay arrow bitmap. */
219 static unsigned char ov_bits
[] = {
220 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
222 /* A triangular arrow. */
225 static unsigned char ov_bits
[] = {
226 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230 extern Lisp_Object Qhelp_echo
;
233 /* Non-zero means Emacs uses toolkit scroll bars. */
235 int x_toolkit_scroll_bars_p
;
237 /* If a string, XTread_socket generates an event to display that string.
238 (The display is done in read_char.) */
240 static Lisp_Object help_echo
;
241 static Lisp_Object help_echo_window
;
242 static Lisp_Object help_echo_object
;
243 static int help_echo_pos
;
245 /* Temporary variable for XTread_socket. */
247 static Lisp_Object previous_help_echo
;
249 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 static int any_help_event_p
;
254 /* Non-zero means draw block and hollow cursor as wide as the glyph
255 under it. For example, if a block cursor is over a tab, it will be
256 drawn as wide as that tab on the display. */
258 int x_stretch_cursor_p
;
260 /* This is a chain of structures for all the X displays currently in
263 struct x_display_info
*x_display_list
;
265 /* This is a list of cons cells, each of the form (NAME
266 . FONT-LIST-CACHE), one for each element of x_display_list and in
267 the same order. NAME is the name of the frame. FONT-LIST-CACHE
268 records previous values returned by x-list-fonts. */
270 Lisp_Object x_display_name_list
;
272 /* Frame being updated by update_frame. This is declared in term.c.
273 This is set by update_begin and looked at by all the XT functions.
274 It is zero while not inside an update. In that case, the XT
275 functions assume that `selected_frame' is the frame to apply to. */
277 extern struct frame
*updating_frame
;
279 extern int waiting_for_input
;
281 /* This is a frame waiting to be auto-raised, within XTread_socket. */
283 struct frame
*pending_autoraise_frame
;
286 /* The application context for Xt use. */
287 XtAppContext Xt_app_con
;
288 static String Xt_default_resources
[] = {0};
289 #endif /* USE_X_TOOLKIT */
291 /* Nominal cursor position -- where to draw output.
292 HPOS and VPOS are window relative glyph matrix coordinates.
293 X and Y are window relative pixel coordinates. */
295 struct cursor_pos output_cursor
;
297 /* Non-zero means user is interacting with a toolkit scroll bar. */
299 static int toolkit_scroll_bar_interaction
;
303 Formerly, we used PointerMotionHintMask (in standard_event_mask)
304 so that we would have to call XQueryPointer after each MotionNotify
305 event to ask for another such event. However, this made mouse tracking
306 slow, and there was a bug that made it eventually stop.
308 Simply asking for MotionNotify all the time seems to work better.
310 In order to avoid asking for motion events and then throwing most
311 of them away or busy-polling the server for mouse positions, we ask
312 the server for pointer motion hints. This means that we get only
313 one event per group of mouse movements. "Groups" are delimited by
314 other kinds of events (focus changes and button clicks, for
315 example), or by XQueryPointer calls; when one of these happens, we
316 get another MotionNotify event the next time the mouse moves. This
317 is at least as efficient as getting motion events when mouse
318 tracking is on, and I suspect only negligibly worse when tracking
321 /* Where the mouse was last time we reported a mouse event. */
323 FRAME_PTR last_mouse_frame
;
324 static XRectangle last_mouse_glyph
;
325 static Lisp_Object last_mouse_press_frame
;
327 /* The scroll bar in which the last X motion event occurred.
329 If the last X motion event occurred in a scroll bar, we set this so
330 XTmouse_position can know whether to report a scroll bar motion or
333 If the last X motion event didn't occur in a scroll bar, we set
334 this to Qnil, to tell XTmouse_position to return an ordinary motion
337 static Lisp_Object last_mouse_scroll_bar
;
339 /* This is a hack. We would really prefer that XTmouse_position would
340 return the time associated with the position it returns, but there
341 doesn't seem to be any way to wrest the time-stamp from the server
342 along with the position query. So, we just keep track of the time
343 of the last movement we received, and return that in hopes that
344 it's somewhat accurate. */
346 static Time last_mouse_movement_time
;
348 /* Incremented by XTread_socket whenever it really tries to read
352 static int volatile input_signal_count
;
354 static int input_signal_count
;
357 /* Used locally within XTread_socket. */
359 static int x_noop_count
;
361 /* Initial values of argv and argc. */
363 extern char **initial_argv
;
364 extern int initial_argc
;
366 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
368 /* Tells if a window manager is present or not. */
370 extern Lisp_Object Vx_no_window_manager
;
372 extern Lisp_Object Qface
, Qmouse_face
;
376 /* A mask of extra modifier bits to put into every keyboard char. */
378 extern int extra_keyboard_modifiers
;
380 static Lisp_Object Qvendor_specific_keysyms
;
382 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
383 extern Lisp_Object x_icon_type
P_ ((struct frame
*));
386 /* Enumeration for overriding/changing the face to use for drawing
387 glyphs in x_draw_glyphs. */
389 enum draw_glyphs_face
399 static const XColor
*x_color_cells
P_ ((struct frame
*, int *));
400 static void x_update_window_end
P_ ((struct window
*, int, int));
401 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
402 void x_delete_display
P_ ((struct x_display_info
*));
403 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
405 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
407 static void set_output_cursor
P_ ((struct cursor_pos
*));
408 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
409 int *, int *, int *));
410 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
411 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
412 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
413 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
414 static void show_mouse_face
P_ ((struct x_display_info
*,
415 enum draw_glyphs_face
));
416 static int x_io_error_quitter
P_ ((Display
*));
417 int x_catch_errors
P_ ((Display
*));
418 void x_uncatch_errors
P_ ((Display
*, int));
419 void x_lower_frame
P_ ((struct frame
*));
420 void x_scroll_bar_clear
P_ ((struct frame
*));
421 int x_had_errors_p
P_ ((Display
*));
422 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
423 void x_raise_frame
P_ ((struct frame
*));
424 void x_set_window_size
P_ ((struct frame
*, int, int, int));
425 void x_wm_set_window_state
P_ ((struct frame
*, int));
426 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
427 void x_initialize
P_ ((void));
428 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
429 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
430 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
432 enum draw_glyphs_face
));
433 static void x_update_end
P_ ((struct frame
*));
434 static void XTframe_up_to_date
P_ ((struct frame
*));
435 static void XTreassert_line_highlight
P_ ((int, int));
436 static void x_change_line_highlight
P_ ((int, int, int, int));
437 static void XTset_terminal_modes
P_ ((void));
438 static void XTreset_terminal_modes
P_ ((void));
439 static void XTcursor_to
P_ ((int, int, int, int));
440 static void x_write_glyphs
P_ ((struct glyph
*, int));
441 static void x_clear_end_of_line
P_ ((int));
442 static void x_clear_frame
P_ ((void));
443 static void x_clear_cursor
P_ ((struct window
*));
444 static void frame_highlight
P_ ((struct frame
*));
445 static void frame_unhighlight
P_ ((struct frame
*));
446 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
447 static void XTframe_rehighlight
P_ ((struct frame
*));
448 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
449 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
450 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
451 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
453 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
454 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
455 static void expose_window
P_ ((struct window
*, XRectangle
*));
456 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
457 XRectangle
*, enum glyph_row_area
));
458 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
460 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
461 static void x_update_window_cursor
P_ ((struct window
*, int));
462 static void x_erase_phys_cursor
P_ ((struct window
*));
463 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
464 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
467 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
469 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
470 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
471 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
472 static void x_flush
P_ ((struct frame
*f
));
473 static void x_update_begin
P_ ((struct frame
*));
474 static void x_update_window_begin
P_ ((struct window
*));
475 static void x_draw_vertical_border
P_ ((struct window
*));
476 static void x_after_update_window_line
P_ ((struct glyph_row
*));
477 static INLINE
void take_vertical_position_into_account
P_ ((struct it
*));
478 static void x_produce_stretch_glyph
P_ ((struct it
*));
481 /* Flush display of frame F, or of all frames if F is null. */
490 Lisp_Object rest
, frame
;
491 FOR_EACH_FRAME (rest
, frame
)
492 x_flush (XFRAME (frame
));
494 else if (FRAME_X_P (f
))
495 XFlush (FRAME_X_DISPLAY (f
));
500 /* Remove calls to XFlush by defining XFlush to an empty replacement.
501 Calls to XFlush should be unnecessary because the X output buffer
502 is flushed automatically as needed by calls to XPending,
503 XNextEvent, or XWindowEvent according to the XFlush man page.
504 XTread_socket calls XPending. Removing XFlush improves
507 #define XFlush(DISPLAY) (void) 0
510 /***********************************************************************
512 ***********************************************************************/
516 /* This is a function useful for recording debugging information about
517 the sequence of occurrences in this file. */
525 struct record event_record
[100];
527 int event_record_index
;
529 record_event (locus
, type
)
533 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
534 event_record_index
= 0;
536 event_record
[event_record_index
].locus
= locus
;
537 event_record
[event_record_index
].type
= type
;
538 event_record_index
++;
545 /* Return the struct x_display_info corresponding to DPY. */
547 struct x_display_info
*
548 x_display_info_for_display (dpy
)
551 struct x_display_info
*dpyinfo
;
553 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
554 if (dpyinfo
->display
== dpy
)
562 /***********************************************************************
563 Starting and ending an update
564 ***********************************************************************/
566 /* Start an update of frame F. This function is installed as a hook
567 for update_begin, i.e. it is called when update_begin is called.
568 This function is called prior to calls to x_update_window_begin for
569 each window being updated. Currently, there is nothing to do here
570 because all interesting stuff is done on a window basis. */
580 /* Start update of window W. Set the global variable updated_window
581 to the window being updated and set output_cursor to the cursor
585 x_update_window_begin (w
)
588 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
589 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
592 set_output_cursor (&w
->cursor
);
596 if (f
== display_info
->mouse_face_mouse_frame
)
598 /* Don't do highlighting for mouse motion during the update. */
599 display_info
->mouse_face_defer
= 1;
601 /* If F needs to be redrawn, simply forget about any prior mouse
603 if (FRAME_GARBAGED_P (f
))
604 display_info
->mouse_face_window
= Qnil
;
606 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
607 their mouse_face_p flag set, which means that they are always
608 unequal to rows in a desired matrix which never have that
609 flag set. So, rows containing mouse-face glyphs are never
610 scrolled, and we don't have to switch the mouse highlight off
611 here to prevent it from being scrolled. */
613 /* Can we tell that this update does not affect the window
614 where the mouse highlight is? If so, no need to turn off.
615 Likewise, don't do anything if the frame is garbaged;
616 in that case, the frame's current matrix that we would use
617 is all wrong, and we will redisplay that line anyway. */
618 if (!NILP (display_info
->mouse_face_window
)
619 && w
== XWINDOW (display_info
->mouse_face_window
))
623 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
624 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
627 if (i
< w
->desired_matrix
->nrows
)
628 clear_mouse_face (display_info
);
637 /* Draw a vertical window border to the right of window W if W doesn't
638 have vertical scroll bars. */
641 x_draw_vertical_border (w
)
644 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
646 /* Redraw borders between horizontally adjacent windows. Don't
647 do it for frames with vertical scroll bars because either the
648 right scroll bar of a window, or the left scroll bar of its
649 neighbor will suffice as a border. */
650 if (!WINDOW_RIGHTMOST_P (w
)
651 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
655 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
656 x1
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
);
659 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
660 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
665 /* End update of window W (which is equal to updated_window).
667 Draw vertical borders between horizontally adjacent windows, and
668 display W's cursor if CURSOR_ON_P is non-zero.
670 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
671 glyphs in mouse-face were overwritten. In that case we have to
672 make sure that the mouse-highlight is properly redrawn.
674 W may be a menu bar pseudo-window in case we don't have X toolkit
675 support. Such windows don't have a cursor, so don't display it
679 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
681 int cursor_on_p
, mouse_face_overwritten_p
;
683 if (!w
->pseudo_window_p
)
685 struct x_display_info
*dpyinfo
686 = FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
690 /* If a row with mouse-face was overwritten, arrange for
691 XTframe_up_to_date to redisplay the mouse highlight. */
692 if (mouse_face_overwritten_p
)
694 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
695 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
696 dpyinfo
->mouse_face_window
= Qnil
;
700 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
702 output_cursor
.x
, output_cursor
.y
);
704 x_draw_vertical_border (w
);
708 updated_window
= NULL
;
712 /* End update of frame F. This function is installed as a hook in
719 /* Mouse highlight may be displayed again. */
720 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
723 XFlush (FRAME_X_DISPLAY (f
));
728 /* This function is called from various places in xdisp.c whenever a
729 complete update has been performed. The global variable
730 updated_window is not available here. */
733 XTframe_up_to_date (f
)
738 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
740 if (dpyinfo
->mouse_face_deferred_gc
741 || f
== dpyinfo
->mouse_face_mouse_frame
)
744 if (dpyinfo
->mouse_face_mouse_frame
)
745 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
746 dpyinfo
->mouse_face_mouse_x
,
747 dpyinfo
->mouse_face_mouse_y
);
748 dpyinfo
->mouse_face_deferred_gc
= 0;
755 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
756 arrow bitmaps, or clear the areas where they would be displayed
757 before DESIRED_ROW is made current. The window being updated is
758 found in updated_window. This function It is called from
759 update_window_line only if it is known that there are differences
760 between bitmaps to be drawn between current row and DESIRED_ROW. */
763 x_after_update_window_line (desired_row
)
764 struct glyph_row
*desired_row
;
766 struct window
*w
= updated_window
;
770 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
773 x_draw_row_bitmaps (w
, desired_row
);
775 /* When a window has disappeared, make sure that no rest of
776 full-width rows stays visible in the internal border. */
777 if (windows_or_buffers_changed
)
779 struct frame
*f
= XFRAME (w
->frame
);
780 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
781 int height
= desired_row
->visible_height
;
782 int x
= (window_box_right (w
, -1)
783 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
));
784 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
786 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
787 x
, y
, width
, height
, False
);
795 /* Draw the bitmap WHICH in one of the areas to the left or right of
796 window W. ROW is the glyph row for which to display the bitmap; it
797 determines the vertical position at which the bitmap has to be
801 x_draw_bitmap (w
, row
, which
)
803 struct glyph_row
*row
;
804 enum bitmap_type which
;
806 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
807 Display
*display
= FRAME_X_DISPLAY (f
);
808 Window window
= FRAME_X_WINDOW (f
);
812 GC gc
= f
->output_data
.x
->normal_gc
;
814 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
816 /* Must clip because of partially visible lines. */
817 x_clip_to_row (w
, row
, gc
, 1);
821 case LEFT_TRUNCATION_BITMAP
:
825 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
827 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
830 case OVERLAY_ARROW_BITMAP
:
834 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
836 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
839 case RIGHT_TRUNCATION_BITMAP
:
843 x
= window_box_right (w
, -1);
844 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
847 case CONTINUED_LINE_BITMAP
:
850 bits
= continued_bits
;
851 x
= window_box_right (w
, -1);
852 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
855 case CONTINUATION_LINE_BITMAP
:
856 wd
= continuation_width
;
857 h
= continuation_height
;
858 bits
= continuation_bits
;
859 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
861 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
868 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
870 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
877 /* Convert to frame coordinates. Set dy to the offset in the row to
878 start drawing the bitmap. */
879 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
880 dy
= (row
->height
- h
) / 2;
882 /* Draw the bitmap. I believe these small pixmaps can be cached
884 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
885 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
887 face
->background
, depth
);
888 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
889 XFreePixmap (display
, pixmap
);
890 XSetClipMask (display
, gc
, None
);
894 /* Draw flags bitmaps for glyph row ROW on window W. Call this
895 function with input blocked. */
898 x_draw_row_bitmaps (w
, row
)
900 struct glyph_row
*row
;
902 struct frame
*f
= XFRAME (w
->frame
);
903 enum bitmap_type bitmap
;
905 int header_line_height
= -1;
907 xassert (interrupt_input_blocked
);
909 /* If row is completely invisible, because of vscrolling, we
910 don't have to draw anything. */
911 if (row
->visible_height
<= 0)
914 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
915 PREPARE_FACE_FOR_DISPLAY (f
, face
);
917 /* Decide which bitmap to draw at the left side. */
918 if (row
->overlay_arrow_p
)
919 bitmap
= OVERLAY_ARROW_BITMAP
;
920 else if (row
->truncated_on_left_p
)
921 bitmap
= LEFT_TRUNCATION_BITMAP
;
922 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
923 bitmap
= CONTINUATION_LINE_BITMAP
;
924 else if (row
->indicate_empty_line_p
)
925 bitmap
= ZV_LINE_BITMAP
;
929 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
931 if (bitmap
== NO_BITMAP
932 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
933 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
935 /* If W has a vertical border to its left, don't draw over it. */
936 int border
= ((XFASTINT (w
->left
) > 0
937 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
939 int left
= window_box_left (w
, -1);
941 if (header_line_height
< 0)
942 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
944 /* In case the same realized face is used for bitmap areas and
945 for something displayed in the text (e.g. face `region' on
946 mono-displays, the fill style may have been changed to
947 FillSolid in x_draw_glyph_string_background. */
949 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
951 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
953 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
956 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
958 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
960 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - border
,
961 row
->visible_height
);
963 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
966 /* Draw the left bitmap. */
967 if (bitmap
!= NO_BITMAP
)
968 x_draw_bitmap (w
, row
, bitmap
);
970 /* Decide which bitmap to draw at the right side. */
971 if (row
->truncated_on_right_p
)
972 bitmap
= RIGHT_TRUNCATION_BITMAP
;
973 else if (row
->continued_p
)
974 bitmap
= CONTINUED_LINE_BITMAP
;
978 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
980 if (bitmap
== NO_BITMAP
981 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
)
982 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
984 int right
= window_box_right (w
, -1);
986 if (header_line_height
< 0)
987 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
989 /* In case the same realized face is used for bitmap areas and
990 for something displayed in the text (e.g. face `region' on
991 mono-displays, the fill style may have been changed to
992 FillSolid in x_draw_glyph_string_background. */
994 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
996 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
997 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1000 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
1002 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
),
1003 row
->visible_height
);
1005 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1008 /* Draw the right bitmap. */
1009 if (bitmap
!= NO_BITMAP
)
1010 x_draw_bitmap (w
, row
, bitmap
);
1014 /***********************************************************************
1016 ***********************************************************************/
1018 /* External interface to control of standout mode. Not used for X
1019 frames. Aborts when called. */
1022 XTreassert_line_highlight (new, vpos
)
1029 /* Call this when about to modify line at position VPOS and change
1030 whether it is highlighted. Not used for X frames. Aborts when
1034 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
1035 int new_highlight
, vpos
, y
, first_unused_hpos
;
1041 /* This is called when starting Emacs and when restarting after
1042 suspend. When starting Emacs, no X window is mapped. And nothing
1043 must be done to Emacs's own window if it is suspended (though that
1047 XTset_terminal_modes ()
1051 /* This is called when exiting or suspending Emacs. Exiting will make
1052 the X-windows go away, and suspending requires no action. */
1055 XTreset_terminal_modes ()
1061 /***********************************************************************
1063 ***********************************************************************/
1065 /* Set the global variable output_cursor to CURSOR. All cursor
1066 positions are relative to updated_window. */
1069 set_output_cursor (cursor
)
1070 struct cursor_pos
*cursor
;
1072 output_cursor
.hpos
= cursor
->hpos
;
1073 output_cursor
.vpos
= cursor
->vpos
;
1074 output_cursor
.x
= cursor
->x
;
1075 output_cursor
.y
= cursor
->y
;
1079 /* Set a nominal cursor position.
1081 HPOS and VPOS are column/row positions in a window glyph matrix. X
1082 and Y are window text area relative pixel positions.
1084 If this is done during an update, updated_window will contain the
1085 window that is being updated and the position is the future output
1086 cursor position for that window. If updated_window is null, use
1087 selected_window and display the cursor at the given position. */
1090 XTcursor_to (vpos
, hpos
, y
, x
)
1091 int vpos
, hpos
, y
, x
;
1095 /* If updated_window is not set, work on selected_window. */
1099 w
= XWINDOW (selected_window
);
1101 /* Set the output cursor. */
1102 output_cursor
.hpos
= hpos
;
1103 output_cursor
.vpos
= vpos
;
1104 output_cursor
.x
= x
;
1105 output_cursor
.y
= y
;
1107 /* If not called as part of an update, really display the cursor.
1108 This will also set the cursor position of W. */
1109 if (updated_window
== NULL
)
1112 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1113 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1120 /***********************************************************************
1122 ***********************************************************************/
1124 /* Function prototypes of this page. */
1126 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1130 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1131 int, XChar2b
*, int));
1132 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1133 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1134 static void x_append_glyph
P_ ((struct it
*));
1135 static void x_append_composite_glyph
P_ ((struct it
*));
1136 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1138 static void x_produce_glyphs
P_ ((struct it
*));
1139 static void x_produce_image_glyph
P_ ((struct it
*it
));
1142 /* Return a pointer to per-char metric information in FONT of a
1143 character pointed by B which is a pointer to an XChar2b. */
1145 #define PER_CHAR_METRIC(font, b) \
1147 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1148 + (((font)->min_byte1 || (font)->max_byte1) \
1149 ? (((b)->byte1 - (font)->min_byte1) \
1150 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1152 : &((font)->max_bounds))
1155 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1156 is not contained in the font. */
1158 static INLINE XCharStruct
*
1159 x_per_char_metric (font
, char2b
)
1163 /* The result metric information. */
1164 XCharStruct
*pcm
= NULL
;
1166 xassert (font
&& char2b
);
1168 if (font
->per_char
!= NULL
)
1170 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1172 /* min_char_or_byte2 specifies the linear character index
1173 corresponding to the first element of the per_char array,
1174 max_char_or_byte2 is the index of the last character. A
1175 character with non-zero CHAR2B->byte1 is not in the font.
1176 A character with byte2 less than min_char_or_byte2 or
1177 greater max_char_or_byte2 is not in the font. */
1178 if (char2b
->byte1
== 0
1179 && char2b
->byte2
>= font
->min_char_or_byte2
1180 && char2b
->byte2
<= font
->max_char_or_byte2
)
1181 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1185 /* If either min_byte1 or max_byte1 are nonzero, both
1186 min_char_or_byte2 and max_char_or_byte2 are less than
1187 256, and the 2-byte character index values corresponding
1188 to the per_char array element N (counting from 0) are:
1190 byte1 = N/D + min_byte1
1191 byte2 = N\D + min_char_or_byte2
1195 D = max_char_or_byte2 - min_char_or_byte2 + 1
1196 / = integer division
1197 \ = integer modulus */
1198 if (char2b
->byte1
>= font
->min_byte1
1199 && char2b
->byte1
<= font
->max_byte1
1200 && char2b
->byte2
>= font
->min_char_or_byte2
1201 && char2b
->byte2
<= font
->max_char_or_byte2
)
1203 pcm
= (font
->per_char
1204 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1205 * (char2b
->byte1
- font
->min_byte1
))
1206 + (char2b
->byte2
- font
->min_char_or_byte2
));
1212 /* If the per_char pointer is null, all glyphs between the first
1213 and last character indexes inclusive have the same
1214 information, as given by both min_bounds and max_bounds. */
1215 if (char2b
->byte2
>= font
->min_char_or_byte2
1216 && char2b
->byte2
<= font
->max_char_or_byte2
)
1217 pcm
= &font
->max_bounds
;
1220 return ((pcm
== NULL
1221 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1226 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1227 the two-byte form of C. Encoding is returned in *CHAR2B. */
1230 x_encode_char (c
, char2b
, font_info
)
1233 struct font_info
*font_info
;
1235 int charset
= CHAR_CHARSET (c
);
1236 XFontStruct
*font
= font_info
->font
;
1238 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1239 This may be either a program in a special encoder language or a
1241 if (font_info
->font_encoder
)
1243 /* It's a program. */
1244 struct ccl_program
*ccl
= font_info
->font_encoder
;
1246 if (CHARSET_DIMENSION (charset
) == 1)
1248 ccl
->reg
[0] = charset
;
1249 ccl
->reg
[1] = char2b
->byte2
;
1253 ccl
->reg
[0] = charset
;
1254 ccl
->reg
[1] = char2b
->byte1
;
1255 ccl
->reg
[2] = char2b
->byte2
;
1258 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1260 /* We assume that MSBs are appropriately set/reset by CCL
1262 if (font
->max_byte1
== 0) /* 1-byte font */
1263 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1265 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1267 else if (font_info
->encoding
[charset
])
1269 /* Fixed encoding scheme. See fontset.h for the meaning of the
1270 encoding numbers. */
1271 int enc
= font_info
->encoding
[charset
];
1273 if ((enc
== 1 || enc
== 2)
1274 && CHARSET_DIMENSION (charset
) == 2)
1275 char2b
->byte1
|= 0x80;
1277 if (enc
== 1 || enc
== 3)
1278 char2b
->byte2
|= 0x80;
1283 /* Get face and two-byte form of character C in face FACE_ID on frame
1284 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1285 means we want to display multibyte text. Value is a pointer to a
1286 realized face that is ready for display. */
1288 static INLINE
struct face
*
1289 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1295 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1299 /* Unibyte case. We don't have to encode, but we have to make
1300 sure to use a face suitable for unibyte. */
1303 face_id
= FACE_FOR_CHAR (f
, face
, c
);
1304 face
= FACE_FROM_ID (f
, face_id
);
1306 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1308 /* Case of ASCII in a face known to fit ASCII. */
1314 int c1
, c2
, charset
;
1316 /* Split characters into bytes. If c2 is -1 afterwards, C is
1317 really a one-byte character so that byte1 is zero. */
1318 SPLIT_CHAR (c
, charset
, c1
, c2
);
1320 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1322 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1324 /* Maybe encode the character in *CHAR2B. */
1325 if (face
->font
!= NULL
)
1327 struct font_info
*font_info
1328 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1330 x_encode_char (c
, char2b
, font_info
);
1334 /* Make sure X resources of the face are allocated. */
1335 xassert (face
!= NULL
);
1336 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1342 /* Get face and two-byte form of character glyph GLYPH on frame F.
1343 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1344 a pointer to a realized face that is ready for display. */
1346 static INLINE
struct face
*
1347 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
1349 struct glyph
*glyph
;
1355 xassert (glyph
->type
== CHAR_GLYPH
);
1356 face
= FACE_FROM_ID (f
, glyph
->face_id
);
1361 if (!glyph
->multibyte_p
)
1363 /* Unibyte case. We don't have to encode, but we have to make
1364 sure to use a face suitable for unibyte. */
1366 char2b
->byte2
= glyph
->u
.ch
;
1368 else if (glyph
->u
.ch
< 128
1369 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
1371 /* Case of ASCII in a face known to fit ASCII. */
1373 char2b
->byte2
= glyph
->u
.ch
;
1377 int c1
, c2
, charset
;
1379 /* Split characters into bytes. If c2 is -1 afterwards, C is
1380 really a one-byte character so that byte1 is zero. */
1381 SPLIT_CHAR (glyph
->u
.ch
, charset
, c1
, c2
);
1383 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1385 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1387 /* Maybe encode the character in *CHAR2B. */
1388 if (charset
!= CHARSET_ASCII
)
1390 struct font_info
*font_info
1391 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1394 x_encode_char (glyph
->u
.ch
, char2b
, font_info
);
1397 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1402 /* Make sure X resources of the face are allocated. */
1403 xassert (face
!= NULL
);
1404 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1409 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1410 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1416 struct glyph
*glyph
;
1417 enum glyph_row_area area
= it
->area
;
1419 xassert (it
->glyph_row
);
1420 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1422 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1423 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1425 glyph
->charpos
= CHARPOS (it
->position
);
1426 glyph
->object
= it
->object
;
1427 glyph
->pixel_width
= it
->pixel_width
;
1428 glyph
->voffset
= it
->voffset
;
1429 glyph
->type
= CHAR_GLYPH
;
1430 glyph
->multibyte_p
= it
->multibyte_p
;
1431 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1432 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1433 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1434 || it
->phys_descent
> it
->descent
);
1435 glyph
->padding_p
= 0;
1436 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
1437 glyph
->face_id
= it
->face_id
;
1438 glyph
->u
.ch
= it
->char_to_display
;
1439 ++it
->glyph_row
->used
[area
];
1443 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1444 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1447 x_append_composite_glyph (it
)
1450 struct glyph
*glyph
;
1451 enum glyph_row_area area
= it
->area
;
1453 xassert (it
->glyph_row
);
1455 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1456 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1458 glyph
->charpos
= CHARPOS (it
->position
);
1459 glyph
->object
= it
->object
;
1460 glyph
->pixel_width
= it
->pixel_width
;
1461 glyph
->voffset
= it
->voffset
;
1462 glyph
->type
= COMPOSITE_GLYPH
;
1463 glyph
->multibyte_p
= it
->multibyte_p
;
1464 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1465 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1466 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1467 || it
->phys_descent
> it
->descent
);
1468 glyph
->padding_p
= 0;
1469 glyph
->glyph_not_available_p
= 0;
1470 glyph
->face_id
= it
->face_id
;
1471 glyph
->u
.cmp_id
= it
->cmp_id
;
1472 ++it
->glyph_row
->used
[area
];
1477 /* Change IT->ascent and IT->height according to the setting of
1481 take_vertical_position_into_account (it
)
1486 if (it
->voffset
< 0)
1487 /* Increase the ascent so that we can display the text higher
1489 it
->ascent
+= abs (it
->voffset
);
1491 /* Increase the descent so that we can display the text lower
1493 it
->descent
+= it
->voffset
;
1498 /* Produce glyphs/get display metrics for the image IT is loaded with.
1499 See the description of struct display_iterator in dispextern.h for
1500 an overview of struct display_iterator. */
1503 x_produce_image_glyph (it
)
1509 xassert (it
->what
== IT_IMAGE
);
1511 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1512 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1515 /* Make sure X resources of the face and image are loaded. */
1516 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1517 prepare_image_for_display (it
->f
, img
);
1519 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
1520 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1521 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1525 if (face
->box
!= FACE_NO_BOX
)
1527 it
->ascent
+= face
->box_line_width
;
1528 it
->descent
+= face
->box_line_width
;
1530 if (it
->start_of_box_run_p
)
1531 it
->pixel_width
+= face
->box_line_width
;
1532 if (it
->end_of_box_run_p
)
1533 it
->pixel_width
+= face
->box_line_width
;
1536 take_vertical_position_into_account (it
);
1540 struct glyph
*glyph
;
1541 enum glyph_row_area area
= it
->area
;
1543 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1544 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1546 glyph
->charpos
= CHARPOS (it
->position
);
1547 glyph
->object
= it
->object
;
1548 glyph
->pixel_width
= it
->pixel_width
;
1549 glyph
->voffset
= it
->voffset
;
1550 glyph
->type
= IMAGE_GLYPH
;
1551 glyph
->multibyte_p
= it
->multibyte_p
;
1552 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1553 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1554 glyph
->overlaps_vertically_p
= 0;
1555 glyph
->padding_p
= 0;
1556 glyph
->glyph_not_available_p
= 0;
1557 glyph
->face_id
= it
->face_id
;
1558 glyph
->u
.img_id
= img
->id
;
1559 ++it
->glyph_row
->used
[area
];
1565 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1566 of the glyph, WIDTH and HEIGHT are the width and height of the
1567 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1568 ascent of the glyph (0 <= ASCENT <= 1). */
1571 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1577 struct glyph
*glyph
;
1578 enum glyph_row_area area
= it
->area
;
1580 xassert (ascent
>= 0 && ascent
<= 1);
1582 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1583 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1585 glyph
->charpos
= CHARPOS (it
->position
);
1586 glyph
->object
= object
;
1587 glyph
->pixel_width
= width
;
1588 glyph
->voffset
= it
->voffset
;
1589 glyph
->type
= STRETCH_GLYPH
;
1590 glyph
->multibyte_p
= it
->multibyte_p
;
1591 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1592 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1593 glyph
->overlaps_vertically_p
= 0;
1594 glyph
->padding_p
= 0;
1595 glyph
->glyph_not_available_p
= 0;
1596 glyph
->face_id
= it
->face_id
;
1597 glyph
->u
.stretch
.ascent
= height
* ascent
;
1598 glyph
->u
.stretch
.height
= height
;
1599 ++it
->glyph_row
->used
[area
];
1604 /* Produce a stretch glyph for iterator IT. IT->object is the value
1605 of the glyph property displayed. The value must be a list
1606 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1609 1. `:width WIDTH' specifies that the space should be WIDTH *
1610 canonical char width wide. WIDTH may be an integer or floating
1613 2. `:relative-width FACTOR' specifies that the width of the stretch
1614 should be computed from the width of the first character having the
1615 `glyph' property, and should be FACTOR times that width.
1617 3. `:align-to HPOS' specifies that the space should be wide enough
1618 to reach HPOS, a value in canonical character units.
1620 Exactly one of the above pairs must be present.
1622 4. `:height HEIGHT' specifies that the height of the stretch produced
1623 should be HEIGHT, measured in canonical character units.
1625 5. `:relative-height FACTOR' specifies that the height of the the
1626 stretch should be FACTOR times the height of the characters having
1629 Either none or exactly one of 4 or 5 must be present.
1631 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1632 of the stretch should be used for the ascent of the stretch.
1633 ASCENT must be in the range 0 <= ASCENT <= 100. */
1636 ((INTEGERP (X) || FLOATP (X)) \
1642 x_produce_stretch_glyph (it
)
1645 /* (space :width WIDTH :height HEIGHT. */
1647 extern Lisp_Object Qspace
;
1649 extern Lisp_Object QCwidth
, QCheight
, QCascent
;
1650 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1651 extern Lisp_Object QCalign_to
;
1652 Lisp_Object prop
, plist
;
1653 double width
= 0, height
= 0, ascent
= 0;
1654 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1655 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1657 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1659 /* List should start with `space'. */
1660 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1661 plist
= XCDR (it
->object
);
1663 /* Compute the width of the stretch. */
1664 if (prop
= Fplist_get (plist
, QCwidth
),
1666 /* Absolute width `:width WIDTH' specified and valid. */
1667 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1668 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1671 /* Relative width `:relative-width FACTOR' specified and valid.
1672 Compute the width of the characters having the `glyph'
1675 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1678 if (it
->multibyte_p
)
1680 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1681 - IT_BYTEPOS (*it
));
1682 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1685 it2
.c
= *p
, it2
.len
= 1;
1687 it2
.glyph_row
= NULL
;
1688 it2
.what
= IT_CHARACTER
;
1689 x_produce_glyphs (&it2
);
1690 width
= NUMVAL (prop
) * it2
.pixel_width
;
1692 else if (prop
= Fplist_get (plist
, QCalign_to
),
1694 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1696 /* Nothing specified -> width defaults to canonical char width. */
1697 width
= CANON_X_UNIT (it
->f
);
1699 /* Compute height. */
1700 if (prop
= Fplist_get (plist
, QCheight
),
1702 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1703 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1705 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1707 height
= FONT_HEIGHT (font
);
1709 /* Compute percentage of height used for ascent. If
1710 `:ascent ASCENT' is present and valid, use that. Otherwise,
1711 derive the ascent from the font in use. */
1712 if (prop
= Fplist_get (plist
, QCascent
),
1713 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1714 ascent
= NUMVAL (prop
) / 100.0;
1716 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1725 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1726 if (!STRINGP (object
))
1727 object
= it
->w
->buffer
;
1728 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1731 it
->pixel_width
= width
;
1732 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1733 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1736 if (face
->box
!= FACE_NO_BOX
)
1738 it
->ascent
+= face
->box_line_width
;
1739 it
->descent
+= face
->box_line_width
;
1741 if (it
->start_of_box_run_p
)
1742 it
->pixel_width
+= face
->box_line_width
;
1743 if (it
->end_of_box_run_p
)
1744 it
->pixel_width
+= face
->box_line_width
;
1747 take_vertical_position_into_account (it
);
1750 /* Return proper value to be used as baseline offset of font that has
1751 ASCENT and DESCENT to draw characters by the font at the vertical
1752 center of the line of frame F.
1754 Here, out task is to find the value of BOFF in the following figure;
1756 -------------------------+-----------+-
1757 -+-+---------+-+ | |
1759 | | | | F_ASCENT F_HEIGHT
1762 | | |-|-+------+-----------|------- baseline
1764 | |---------|-+-+ | |
1766 -+-+---------+-+ F_DESCENT |
1767 -------------------------+-----------+-
1769 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1770 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1771 DESCENT = FONT->descent
1772 HEIGHT = FONT_HEIGHT (FONT)
1773 F_DESCENT = (F->output_data.x->font->descent
1774 - F->output_data.x->baseline_offset)
1775 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1778 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1780 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1781 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1782 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1784 /* Produce glyphs/get display metrics for the display element IT is
1785 loaded with. See the description of struct display_iterator in
1786 dispextern.h for an overview of struct display_iterator. */
1789 x_produce_glyphs (it
)
1792 it
->glyph_not_available_p
= 0;
1794 if (it
->what
== IT_CHARACTER
)
1798 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1800 int font_not_found_p
;
1801 struct font_info
*font_info
;
1802 int boff
; /* baseline offset */
1803 /* We may change it->multibyte_p upon unibyte<->multibyte
1804 conversion. So, save the current value now and restore it
1807 Note: It seems that we don't have to record multibyte_p in
1808 struct glyph because the character code itself tells if or
1809 not the character is multibyte. Thus, in the future, we must
1810 consider eliminating the field `multibyte_p' in the struct
1813 int saved_multibyte_p
= it
->multibyte_p
;
1815 /* Maybe translate single-byte characters to multibyte, or the
1817 it
->char_to_display
= it
->c
;
1818 if (!ASCII_BYTE_P (it
->c
))
1820 if (unibyte_display_via_language_environment
1821 && SINGLE_BYTE_CHAR_P (it
->c
)
1823 || !NILP (Vnonascii_translation_table
)))
1825 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1826 it
->multibyte_p
= 1;
1827 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1828 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1830 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
1831 && !it
->multibyte_p
)
1833 it
->char_to_display
= multibyte_char_to_unibyte (it
->c
, Qnil
);
1834 it
->multibyte_p
= 0;
1835 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1836 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1840 /* Get font to use. Encode IT->char_to_display. */
1841 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1842 it
->face_id
, &char2b
,
1846 /* When no suitable font found, use the default font. */
1847 font_not_found_p
= font
== NULL
;
1848 if (font_not_found_p
)
1850 font
= FRAME_FONT (it
->f
);
1851 boff
= it
->f
->output_data
.x
->baseline_offset
;
1856 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1857 boff
= font_info
->baseline_offset
;
1858 if (font_info
->vertical_centering
)
1859 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1862 if (it
->char_to_display
>= ' '
1863 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1865 /* Either unibyte or ASCII. */
1870 pcm
= x_per_char_metric (font
, &char2b
);
1871 it
->ascent
= font
->ascent
+ boff
;
1872 it
->descent
= font
->descent
- boff
;
1876 it
->phys_ascent
= pcm
->ascent
+ boff
;
1877 it
->phys_descent
= pcm
->descent
- boff
;
1878 it
->pixel_width
= pcm
->width
;
1882 it
->glyph_not_available_p
= 1;
1883 it
->phys_ascent
= font
->ascent
+ boff
;
1884 it
->phys_descent
= font
->descent
- boff
;
1885 it
->pixel_width
= FONT_WIDTH (font
);
1888 /* If this is a space inside a region of text with
1889 `space-width' property, change its width. */
1890 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1892 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1894 /* If face has a box, add the box thickness to the character
1895 height. If character has a box line to the left and/or
1896 right, add the box line width to the character's width. */
1897 if (face
->box
!= FACE_NO_BOX
)
1899 int thick
= face
->box_line_width
;
1901 it
->ascent
+= thick
;
1902 it
->descent
+= thick
;
1904 if (it
->start_of_box_run_p
)
1905 it
->pixel_width
+= thick
;
1906 if (it
->end_of_box_run_p
)
1907 it
->pixel_width
+= thick
;
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face
->overline_p
)
1915 take_vertical_position_into_account (it
);
1917 /* If we have to actually produce glyphs, do it. */
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1925 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1926 it
->ascent
+ it
->descent
, ascent
);
1929 x_append_glyph (it
);
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1934 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
1935 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1938 else if (it
->char_to_display
== '\n')
1940 /* A newline has no width but we need the height of the line. */
1941 it
->pixel_width
= 0;
1943 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1944 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1946 if (face
->box
!= FACE_NO_BOX
)
1948 int thick
= face
->box_line_width
;
1949 it
->ascent
+= thick
;
1950 it
->descent
+= thick
;
1953 else if (it
->char_to_display
== '\t')
1955 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1956 int x
= it
->current_x
+ it
->continuation_lines_width
;
1957 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x
- x
< CANON_X_UNIT (it
->f
))
1963 next_tab_x
+= tab_width
;
1965 it
->pixel_width
= next_tab_x
- x
;
1967 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1968 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1972 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1973 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1974 it
->ascent
+ it
->descent
, ascent
);
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
1981 width of the font. */
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character
1986 from the charset width; this is what old redisplay code
1988 pcm
= x_per_char_metric (font
, &char2b
);
1989 if (font_not_found_p
|| !pcm
)
1991 int charset
= CHAR_CHARSET (it
->char_to_display
);
1993 it
->glyph_not_available_p
= 1;
1994 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
1995 * CHARSET_WIDTH (charset
));
1996 it
->phys_ascent
= font
->ascent
+ boff
;
1997 it
->phys_descent
= font
->descent
- boff
;
2001 it
->pixel_width
= pcm
->width
;
2002 it
->phys_ascent
= pcm
->ascent
+ boff
;
2003 it
->phys_descent
= pcm
->descent
- boff
;
2005 && (pcm
->lbearing
< 0
2006 || pcm
->rbearing
> pcm
->width
))
2007 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
2010 it
->ascent
= font
->ascent
+ boff
;
2011 it
->descent
= font
->descent
- boff
;
2012 if (face
->box
!= FACE_NO_BOX
)
2014 int thick
= face
->box_line_width
;
2015 it
->ascent
+= thick
;
2016 it
->descent
+= thick
;
2018 if (it
->start_of_box_run_p
)
2019 it
->pixel_width
+= thick
;
2020 if (it
->end_of_box_run_p
)
2021 it
->pixel_width
+= thick
;
2024 /* If face has an overline, add the height of the overline
2025 (1 pixel) and a 1 pixel margin to the character height. */
2026 if (face
->overline_p
)
2029 take_vertical_position_into_account (it
);
2032 x_append_glyph (it
);
2034 it
->multibyte_p
= saved_multibyte_p
;
2036 else if (it
->what
== IT_COMPOSITION
)
2038 /* Note: A composition is represented as one glyph in the
2039 glyph matrix. There are no padding glyphs. */
2042 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2044 int font_not_found_p
;
2045 struct font_info
*font_info
;
2046 int boff
; /* baseline offset */
2047 struct composition
*cmp
= composition_table
[it
->cmp_id
];
2049 /* Maybe translate single-byte characters to multibyte. */
2050 it
->char_to_display
= it
->c
;
2051 if (unibyte_display_via_language_environment
2052 && SINGLE_BYTE_CHAR_P (it
->c
)
2055 && !NILP (Vnonascii_translation_table
))))
2057 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2060 /* Get face and font to use. Encode IT->char_to_display. */
2061 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2062 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2063 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2064 it
->face_id
, &char2b
, it
->multibyte_p
);
2067 /* When no suitable font found, use the default font. */
2068 font_not_found_p
= font
== NULL
;
2069 if (font_not_found_p
)
2071 font
= FRAME_FONT (it
->f
);
2072 boff
= it
->f
->output_data
.x
->baseline_offset
;
2077 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2078 boff
= font_info
->baseline_offset
;
2079 if (font_info
->vertical_centering
)
2080 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2083 /* There are no padding glyphs, so there is only one glyph to
2084 produce for the composition. Important is that pixel_width,
2085 ascent and descent are the values of what is drawn by
2086 draw_glyphs (i.e. the values of the overall glyphs composed). */
2089 /* If we have not yet calculated pixel size data of glyphs of
2090 the composition for the current face font, calculate them
2091 now. Theoretically, we have to check all fonts for the
2092 glyphs, but that requires much time and memory space. So,
2093 here we check only the font of the first glyph. This leads
2094 to incorrect display very rarely, and C-l (recenter) can
2095 correct the display anyway. */
2096 if (cmp
->font
!= (void *) font
)
2098 /* Ascent and descent of the font of the first character of
2099 this composition (adjusted by baseline offset). Ascent
2100 and descent of overall glyphs should not be less than
2101 them respectively. */
2102 int font_ascent
= font
->ascent
+ boff
;
2103 int font_descent
= font
->descent
- boff
;
2104 /* Bounding box of the overall glyphs. */
2105 int leftmost
, rightmost
, lowest
, highest
;
2106 int i
, width
, ascent
, descent
;
2108 cmp
->font
= (void *) font
;
2110 /* Initialize the bounding box. */
2111 pcm
= x_per_char_metric (font
, &char2b
);
2115 ascent
= pcm
->ascent
;
2116 descent
= pcm
->descent
;
2120 width
= FONT_WIDTH (font
);
2121 ascent
= font
->ascent
;
2122 descent
= font
->descent
;
2126 lowest
= - descent
+ boff
;
2127 highest
= ascent
+ boff
;
2131 && font_info
->default_ascent
2132 && CHAR_TABLE_P (Vuse_default_ascent
)
2133 && !NILP (Faref (Vuse_default_ascent
,
2134 make_number (it
->char_to_display
))))
2135 highest
= font_info
->default_ascent
+ boff
;
2137 /* Draw the first glyph at the normal position. It may be
2138 shifted to right later if some other glyphs are drawn at
2140 cmp
->offsets
[0] = 0;
2141 cmp
->offsets
[1] = boff
;
2143 /* Set cmp->offsets for the remaining glyphs. */
2144 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2146 int left
, right
, btm
, top
;
2147 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2148 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2150 face
= FACE_FROM_ID (it
->f
, face_id
);
2151 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2156 font
= FRAME_FONT (it
->f
);
2157 boff
= it
->f
->output_data
.x
->baseline_offset
;
2163 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2164 boff
= font_info
->baseline_offset
;
2165 if (font_info
->vertical_centering
)
2166 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2169 pcm
= x_per_char_metric (font
, &char2b
);
2173 ascent
= pcm
->ascent
;
2174 descent
= pcm
->descent
;
2178 width
= FONT_WIDTH (font
);
2179 ascent
= font
->ascent
;
2180 descent
= font
->descent
;
2183 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2185 /* Relative composition with or without
2187 left
= (leftmost
+ rightmost
- width
) / 2;
2188 btm
= - descent
+ boff
;
2189 if (font_info
&& font_info
->relative_compose
2190 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2191 || NILP (Faref (Vignore_relative_composition
,
2192 make_number (ch
)))))
2195 if (- descent
>= font_info
->relative_compose
)
2196 /* One extra pixel between two glyphs. */
2198 else if (ascent
<= 0)
2199 /* One extra pixel between two glyphs. */
2200 btm
= lowest
- 1 - ascent
- descent
;
2205 /* A composition rule is specified by an integer
2206 value that encodes global and new reference
2207 points (GREF and NREF). GREF and NREF are
2208 specified by numbers as below:
2216 ---3---4---5--- baseline
2218 6---7---8 -- descent
2220 int rule
= COMPOSITION_RULE (cmp
, i
);
2221 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2223 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2224 grefx
= gref
% 3, nrefx
= nref
% 3;
2225 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2228 + grefx
* (rightmost
- leftmost
) / 2
2229 - nrefx
* width
/ 2);
2230 btm
= ((grefy
== 0 ? highest
2232 : grefy
== 2 ? lowest
2233 : (highest
+ lowest
) / 2)
2234 - (nrefy
== 0 ? ascent
+ descent
2235 : nrefy
== 1 ? descent
- boff
2237 : (ascent
+ descent
) / 2));
2240 cmp
->offsets
[i
* 2] = left
;
2241 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2243 /* Update the bounding box of the overall glyphs. */
2244 right
= left
+ width
;
2245 top
= btm
+ descent
+ ascent
;
2246 if (left
< leftmost
)
2248 if (right
> rightmost
)
2256 /* If there are glyphs whose x-offsets are negative,
2257 shift all glyphs to the right and make all x-offsets
2261 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2262 cmp
->offsets
[i
* 2] -= leftmost
;
2263 rightmost
-= leftmost
;
2266 cmp
->pixel_width
= rightmost
;
2267 cmp
->ascent
= highest
;
2268 cmp
->descent
= - lowest
;
2269 if (cmp
->ascent
< font_ascent
)
2270 cmp
->ascent
= font_ascent
;
2271 if (cmp
->descent
< font_descent
)
2272 cmp
->descent
= font_descent
;
2275 it
->pixel_width
= cmp
->pixel_width
;
2276 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2277 it
->descent
= it
->phys_descent
= cmp
->descent
;
2279 if (face
->box
!= FACE_NO_BOX
)
2281 int thick
= face
->box_line_width
;
2282 it
->ascent
+= thick
;
2283 it
->descent
+= thick
;
2285 if (it
->start_of_box_run_p
)
2286 it
->pixel_width
+= thick
;
2287 if (it
->end_of_box_run_p
)
2288 it
->pixel_width
+= thick
;
2291 /* If face has an overline, add the height of the overline
2292 (1 pixel) and a 1 pixel margin to the character height. */
2293 if (face
->overline_p
)
2296 take_vertical_position_into_account (it
);
2299 x_append_composite_glyph (it
);
2301 else if (it
->what
== IT_IMAGE
)
2302 x_produce_image_glyph (it
);
2303 else if (it
->what
== IT_STRETCH
)
2304 x_produce_stretch_glyph (it
);
2306 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2307 because this isn't true for images with `:ascent 100'. */
2308 xassert (it
->ascent
>= 0 && it
->descent
>= 0);
2309 if (it
->area
== TEXT_AREA
)
2310 it
->current_x
+= it
->pixel_width
;
2312 it
->descent
+= it
->extra_line_spacing
;
2314 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2315 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2316 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2317 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2321 /* Estimate the pixel height of the mode or top line on frame F.
2322 FACE_ID specifies what line's height to estimate. */
2325 x_estimate_mode_line_height (f
, face_id
)
2327 enum face_id face_id
;
2329 int height
= FONT_HEIGHT (FRAME_FONT (f
));
2331 /* This function is called so early when Emacs starts that the face
2332 cache and mode line face are not yet initialized. */
2333 if (FRAME_FACE_CACHE (f
))
2335 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2339 height
= FONT_HEIGHT (face
->font
);
2340 height
+= 2 * face
->box_line_width
;
2348 /***********************************************************************
2350 ***********************************************************************/
2352 /* A sequence of glyphs to be drawn in the same face.
2354 This data structure is not really completely X specific, so it
2355 could possibly, at least partially, be useful for other systems. It
2356 is currently not part of the external redisplay interface because
2357 it's not clear what other systems will need. */
2361 /* X-origin of the string. */
2364 /* Y-origin and y-position of the base line of this string. */
2367 /* The width of the string, not including a face extension. */
2370 /* The width of the string, including a face extension. */
2371 int background_width
;
2373 /* The height of this string. This is the height of the line this
2374 string is drawn in, and can be different from the height of the
2375 font the string is drawn in. */
2378 /* Number of pixels this string overwrites in front of its x-origin.
2379 This number is zero if the string has an lbearing >= 0; it is
2380 -lbearing, if the string has an lbearing < 0. */
2383 /* Number of pixels this string overwrites past its right-most
2384 nominal x-position, i.e. x + width. Zero if the string's
2385 rbearing is <= its nominal width, rbearing - width otherwise. */
2388 /* The frame on which the glyph string is drawn. */
2391 /* The window on which the glyph string is drawn. */
2394 /* X display and window for convenience. */
2398 /* The glyph row for which this string was built. It determines the
2399 y-origin and height of the string. */
2400 struct glyph_row
*row
;
2402 /* The area within row. */
2403 enum glyph_row_area area
;
2405 /* Characters to be drawn, and number of characters. */
2409 /* A face-override for drawing cursors, mouse face and similar. */
2410 enum draw_glyphs_face hl
;
2412 /* Face in which this string is to be drawn. */
2415 /* Font in which this string is to be drawn. */
2418 /* Font info for this string. */
2419 struct font_info
*font_info
;
2421 /* Non-null means this string describes (part of) a composition.
2422 All characters from char2b are drawn composed. */
2423 struct composition
*cmp
;
2425 /* Index of this glyph string's first character in the glyph
2426 definition of CMP. If this is zero, this glyph string describes
2427 the first character of a composition. */
2430 /* 1 means this glyph strings face has to be drawn to the right end
2431 of the window's drawing area. */
2432 unsigned extends_to_end_of_line_p
: 1;
2434 /* 1 means the background of this string has been drawn. */
2435 unsigned background_filled_p
: 1;
2437 /* 1 means glyph string must be drawn with 16-bit functions. */
2438 unsigned two_byte_p
: 1;
2440 /* 1 means that the original font determined for drawing this glyph
2441 string could not be loaded. The member `font' has been set to
2442 the frame's default font in this case. */
2443 unsigned font_not_found_p
: 1;
2445 /* 1 means that the face in which this glyph string is drawn has a
2447 unsigned stippled_p
: 1;
2449 /* 1 means only the foreground of this glyph string must be drawn,
2450 and we should use the physical height of the line this glyph
2451 string appears in as clip rect. */
2452 unsigned for_overlaps_p
: 1;
2454 /* The GC to use for drawing this glyph string. */
2457 /* A pointer to the first glyph in the string. This glyph
2458 corresponds to char2b[0]. Needed to draw rectangles if
2459 font_not_found_p is 1. */
2460 struct glyph
*first_glyph
;
2462 /* Image, if any. */
2465 struct glyph_string
*next
, *prev
;
2472 x_dump_glyph_string (s
)
2473 struct glyph_string
*s
;
2475 fprintf (stderr
, "glyph string\n");
2476 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2477 s
->x
, s
->y
, s
->width
, s
->height
);
2478 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2479 fprintf (stderr
, " hl = %d\n", s
->hl
);
2480 fprintf (stderr
, " left overhang = %d, right = %d\n",
2481 s
->left_overhang
, s
->right_overhang
);
2482 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2483 fprintf (stderr
, " extends to end of line = %d\n",
2484 s
->extends_to_end_of_line_p
);
2485 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2486 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2489 #endif /* GLYPH_DEBUG */
2493 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2494 struct glyph_string
**,
2495 struct glyph_string
*,
2496 struct glyph_string
*));
2497 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2498 struct glyph_string
**,
2499 struct glyph_string
*,
2500 struct glyph_string
*));
2501 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2502 struct glyph_string
**,
2503 struct glyph_string
*));
2504 static int x_left_overwritten
P_ ((struct glyph_string
*));
2505 static int x_left_overwriting
P_ ((struct glyph_string
*));
2506 static int x_right_overwritten
P_ ((struct glyph_string
*));
2507 static int x_right_overwriting
P_ ((struct glyph_string
*));
2508 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2510 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2511 XChar2b
*, struct window
*,
2513 enum glyph_row_area
, int,
2514 enum draw_glyphs_face
));
2515 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2516 enum glyph_row_area
, int, int,
2517 enum draw_glyphs_face
, int *, int *, int));
2518 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2519 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2520 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2522 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2523 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2524 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2525 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2526 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2527 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2528 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2529 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2530 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2532 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2533 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2534 unsigned long *, double, int));
2535 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2536 double, int, unsigned long));
2537 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2538 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2539 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2540 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2541 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2542 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2543 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2545 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2546 int, int, int, int, XRectangle
*));
2547 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2548 int, int, int, XRectangle
*));
2549 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2550 enum glyph_row_area
));
2551 static int x_fill_stretch_glyph_string
P_ ((struct glyph_string
*,
2553 enum glyph_row_area
, int, int));
2556 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2560 /* Append the list of glyph strings with head H and tail T to the list
2561 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2564 x_append_glyph_string_lists (head
, tail
, h
, t
)
2565 struct glyph_string
**head
, **tail
;
2566 struct glyph_string
*h
, *t
;
2580 /* Prepend the list of glyph strings with head H and tail T to the
2581 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2585 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2586 struct glyph_string
**head
, **tail
;
2587 struct glyph_string
*h
, *t
;
2601 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2602 Set *HEAD and *TAIL to the resulting list. */
2605 x_append_glyph_string (head
, tail
, s
)
2606 struct glyph_string
**head
, **tail
;
2607 struct glyph_string
*s
;
2609 s
->next
= s
->prev
= NULL
;
2610 x_append_glyph_string_lists (head
, tail
, s
, s
);
2614 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2619 struct glyph_string
*s
;
2621 if (s
->font
== FRAME_FONT (s
->f
)
2622 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2623 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2625 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2628 /* Cursor on non-default face: must merge. */
2632 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2633 xgcv
.foreground
= s
->face
->background
;
2635 /* If the glyph would be invisible, try a different foreground. */
2636 if (xgcv
.foreground
== xgcv
.background
)
2637 xgcv
.foreground
= s
->face
->foreground
;
2638 if (xgcv
.foreground
== xgcv
.background
)
2639 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2640 if (xgcv
.foreground
== xgcv
.background
)
2641 xgcv
.foreground
= s
->face
->foreground
;
2643 /* Make sure the cursor is distinct from text in this face. */
2644 if (xgcv
.background
== s
->face
->background
2645 && xgcv
.foreground
== s
->face
->foreground
)
2647 xgcv
.background
= s
->face
->foreground
;
2648 xgcv
.foreground
= s
->face
->background
;
2651 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2652 xgcv
.font
= s
->font
->fid
;
2653 xgcv
.graphics_exposures
= False
;
2654 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2656 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2657 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2660 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2661 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2663 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2668 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2671 x_set_mouse_face_gc (s
)
2672 struct glyph_string
*s
;
2677 /* What face has to be used for the mouse face? */
2678 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2679 face
= FACE_FROM_ID (s
->f
, face_id
);
2680 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2681 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2683 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2684 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2685 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2687 /* If font in this face is same as S->font, use it. */
2688 if (s
->font
== s
->face
->font
)
2689 s
->gc
= s
->face
->gc
;
2692 /* Otherwise construct scratch_cursor_gc with values from FACE
2697 xgcv
.background
= s
->face
->background
;
2698 xgcv
.foreground
= s
->face
->foreground
;
2699 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2700 xgcv
.font
= s
->font
->fid
;
2701 xgcv
.graphics_exposures
= False
;
2702 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2704 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2705 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2708 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2709 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2711 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2714 xassert (s
->gc
!= 0);
2718 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2719 Faces to use in the mode line have already been computed when the
2720 matrix was built, so there isn't much to do, here. */
2723 x_set_mode_line_face_gc (s
)
2724 struct glyph_string
*s
;
2726 s
->gc
= s
->face
->gc
;
2730 /* Set S->gc of glyph string S for drawing that glyph string. Set
2731 S->stippled_p to a non-zero value if the face of S has a stipple
2735 x_set_glyph_string_gc (s
)
2736 struct glyph_string
*s
;
2738 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2740 if (s
->hl
== DRAW_NORMAL_TEXT
)
2742 s
->gc
= s
->face
->gc
;
2743 s
->stippled_p
= s
->face
->stipple
!= 0;
2745 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2747 x_set_mode_line_face_gc (s
);
2748 s
->stippled_p
= s
->face
->stipple
!= 0;
2750 else if (s
->hl
== DRAW_CURSOR
)
2752 x_set_cursor_gc (s
);
2755 else if (s
->hl
== DRAW_MOUSE_FACE
)
2757 x_set_mouse_face_gc (s
);
2758 s
->stippled_p
= s
->face
->stipple
!= 0;
2760 else if (s
->hl
== DRAW_IMAGE_RAISED
2761 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2763 s
->gc
= s
->face
->gc
;
2764 s
->stippled_p
= s
->face
->stipple
!= 0;
2768 s
->gc
= s
->face
->gc
;
2769 s
->stippled_p
= s
->face
->stipple
!= 0;
2772 /* GC must have been set. */
2773 xassert (s
->gc
!= 0);
2777 /* Return in *R the clipping rectangle for glyph string S. */
2780 x_get_glyph_string_clip_rect (s
, r
)
2781 struct glyph_string
*s
;
2784 if (s
->row
->full_width_p
)
2786 /* Draw full-width. X coordinates are relative to S->w->left. */
2787 int canon_x
= CANON_X_UNIT (s
->f
);
2789 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2790 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2792 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2794 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2795 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2799 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2801 /* Unless displaying a mode or menu bar line, which are always
2802 fully visible, clip to the visible part of the row. */
2803 if (s
->w
->pseudo_window_p
)
2804 r
->height
= s
->row
->visible_height
;
2806 r
->height
= s
->height
;
2810 /* This is a text line that may be partially visible. */
2811 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2812 r
->width
= window_box_width (s
->w
, s
->area
);
2813 r
->height
= s
->row
->visible_height
;
2816 /* Don't use S->y for clipping because it doesn't take partially
2817 visible lines into account. For example, it can be negative for
2818 partially visible lines at the top of a window. */
2819 if (!s
->row
->full_width_p
2820 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2821 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2823 r
->y
= max (0, s
->row
->y
);
2825 /* If drawing a tool-bar window, draw it over the internal border
2826 at the top of the window. */
2827 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2828 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2830 /* If S draws overlapping rows, it's sufficient to use the top and
2831 bottom of the window for clipping because this glyph string
2832 intentionally draws over other lines. */
2833 if (s
->for_overlaps_p
)
2835 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2836 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2839 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2843 /* Set clipping for output of glyph string S. S may be part of a mode
2844 line or menu if we don't have X toolkit support. */
2847 x_set_glyph_string_clipping (s
)
2848 struct glyph_string
*s
;
2851 x_get_glyph_string_clip_rect (s
, &r
);
2852 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2856 /* Compute left and right overhang of glyph string S. If S is a glyph
2857 string for a composition, assume overhangs don't exist. */
2860 x_compute_glyph_string_overhangs (s
)
2861 struct glyph_string
*s
;
2864 && s
->first_glyph
->type
== CHAR_GLYPH
)
2867 int direction
, font_ascent
, font_descent
;
2868 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2869 &font_ascent
, &font_descent
, &cs
);
2870 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2871 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2876 /* Compute overhangs and x-positions for glyph string S and its
2877 predecessors, or successors. X is the starting x-position for S.
2878 BACKWARD_P non-zero means process predecessors. */
2881 x_compute_overhangs_and_x (s
, x
, backward_p
)
2882 struct glyph_string
*s
;
2890 x_compute_glyph_string_overhangs (s
);
2900 x_compute_glyph_string_overhangs (s
);
2909 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2910 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2911 assumed to be zero. */
2914 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2915 struct glyph
*glyph
;
2921 if (glyph
->type
== CHAR_GLYPH
)
2925 struct font_info
*font_info
;
2929 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
2931 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2933 && (pcm
= x_per_char_metric (font
, &char2b
)))
2935 if (pcm
->rbearing
> pcm
->width
)
2936 *right
= pcm
->rbearing
- pcm
->width
;
2937 if (pcm
->lbearing
< 0)
2938 *left
= -pcm
->lbearing
;
2944 /* Return the index of the first glyph preceding glyph string S that
2945 is overwritten by S because of S's left overhang. Value is -1
2946 if no glyphs are overwritten. */
2949 x_left_overwritten (s
)
2950 struct glyph_string
*s
;
2954 if (s
->left_overhang
)
2957 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2958 int first
= s
->first_glyph
- glyphs
;
2960 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2961 x
-= glyphs
[i
].pixel_width
;
2972 /* Return the index of the first glyph preceding glyph string S that
2973 is overwriting S because of its right overhang. Value is -1 if no
2974 glyph in front of S overwrites S. */
2977 x_left_overwriting (s
)
2978 struct glyph_string
*s
;
2981 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2982 int first
= s
->first_glyph
- glyphs
;
2986 for (i
= first
- 1; i
>= 0; --i
)
2989 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2992 x
-= glyphs
[i
].pixel_width
;
2999 /* Return the index of the last glyph following glyph string S that is
3000 not overwritten by S because of S's right overhang. Value is -1 if
3001 no such glyph is found. */
3004 x_right_overwritten (s
)
3005 struct glyph_string
*s
;
3009 if (s
->right_overhang
)
3012 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3013 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3014 int end
= s
->row
->used
[s
->area
];
3016 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
3017 x
+= glyphs
[i
].pixel_width
;
3026 /* Return the index of the last glyph following glyph string S that
3027 overwrites S because of its left overhang. Value is negative
3028 if no such glyph is found. */
3031 x_right_overwriting (s
)
3032 struct glyph_string
*s
;
3035 int end
= s
->row
->used
[s
->area
];
3036 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
3037 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
3041 for (i
= first
; i
< end
; ++i
)
3044 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
3047 x
+= glyphs
[i
].pixel_width
;
3054 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3057 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
3058 struct glyph_string
*s
;
3062 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
3063 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3064 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3065 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3069 /* Draw the background of glyph_string S. If S->background_filled_p
3070 is non-zero don't draw it. FORCE_P non-zero means draw the
3071 background even if it wouldn't be drawn normally. This is used
3072 when a string preceding S draws into the background of S, or S
3073 contains the first component of a composition. */
3076 x_draw_glyph_string_background (s
, force_p
)
3077 struct glyph_string
*s
;
3080 /* Nothing to do if background has already been drawn or if it
3081 shouldn't be drawn in the first place. */
3082 if (!s
->background_filled_p
)
3086 /* Fill background with a stipple pattern. */
3087 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3088 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3089 s
->y
+ s
->face
->box_line_width
,
3090 s
->background_width
,
3091 s
->height
- 2 * s
->face
->box_line_width
);
3092 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3093 s
->background_filled_p
= 1;
3095 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
3096 || s
->font_not_found_p
3097 || s
->extends_to_end_of_line_p
3100 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
3101 s
->background_width
,
3102 s
->height
- 2 * s
->face
->box_line_width
);
3103 s
->background_filled_p
= 1;
3109 /* Draw the foreground of glyph string S. */
3112 x_draw_glyph_string_foreground (s
)
3113 struct glyph_string
*s
;
3117 /* If first glyph of S has a left box line, start drawing the text
3118 of S to the right of that box line. */
3119 if (s
->face
->box
!= FACE_NO_BOX
3120 && s
->first_glyph
->left_box_line_p
)
3121 x
= s
->x
+ s
->face
->box_line_width
;
3125 /* Draw characters of S as rectangles if S's font could not be
3127 if (s
->font_not_found_p
)
3129 for (i
= 0; i
< s
->nchars
; ++i
)
3131 struct glyph
*g
= s
->first_glyph
+ i
;
3132 XDrawRectangle (s
->display
, s
->window
,
3133 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3135 x
+= g
->pixel_width
;
3140 char *char1b
= (char *) s
->char2b
;
3141 int boff
= s
->font_info
->baseline_offset
;
3143 if (s
->font_info
->vertical_centering
)
3144 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3146 /* If we can use 8-bit functions, condense S->char2b. */
3148 for (i
= 0; i
< s
->nchars
; ++i
)
3149 char1b
[i
] = s
->char2b
[i
].byte2
;
3151 /* Draw text with XDrawString if background has already been
3152 filled. Otherwise, use XDrawImageString. (Note that
3153 XDrawImageString is usually faster than XDrawString.) Always
3154 use XDrawImageString when drawing the cursor so that there is
3155 no chance that characters under a box cursor are invisible. */
3156 if (s
->for_overlaps_p
3157 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3159 /* Draw characters with 16-bit or 8-bit functions. */
3161 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3162 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3164 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3165 s
->ybase
- boff
, char1b
, s
->nchars
);
3170 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3171 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3173 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3174 s
->ybase
- boff
, char1b
, s
->nchars
);
3179 /* Draw the foreground of composite glyph string S. */
3182 x_draw_composite_glyph_string_foreground (s
)
3183 struct glyph_string
*s
;
3187 /* If first glyph of S has a left box line, start drawing the text
3188 of S to the right of that box line. */
3189 if (s
->face
->box
!= FACE_NO_BOX
3190 && s
->first_glyph
->left_box_line_p
)
3191 x
= s
->x
+ s
->face
->box_line_width
;
3195 /* S is a glyph string for a composition. S->gidx is the index of
3196 the first character drawn for glyphs of this composition.
3197 S->gidx == 0 means we are drawing the very first character of
3198 this composition. */
3200 /* Draw a rectangle for the composition if the font for the very
3201 first character of the composition could not be loaded. */
3202 if (s
->font_not_found_p
)
3205 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3206 s
->width
- 1, s
->height
- 1);
3210 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3211 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3212 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3213 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3219 #ifdef USE_X_TOOLKIT
3221 static struct frame
*x_frame_of_widget
P_ ((Widget
));
3224 /* Return the frame on which widget WIDGET is used.. Abort if frame
3225 cannot be determined. */
3227 static struct frame
*
3228 x_frame_of_widget (widget
)
3231 struct x_display_info
*dpyinfo
;
3235 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3237 /* Find the top-level shell of the widget. Note that this function
3238 can be called when the widget is not yet realized, so XtWindow
3239 (widget) == 0. That's the reason we can't simply use
3240 x_any_window_to_frame. */
3241 while (!XtIsTopLevelShell (widget
))
3242 widget
= XtParent (widget
);
3244 /* Look for a frame with that top-level widget. Allocate the color
3245 on that frame to get the right gamma correction value. */
3246 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3247 if (GC_FRAMEP (XCAR (tail
))
3248 && (f
= XFRAME (XCAR (tail
)),
3249 (f
->output_data
.nothing
!= 1
3250 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3251 && f
->output_data
.x
->widget
== widget
)
3258 /* Allocate the color COLOR->pixel on the screen and display of
3259 widget WIDGET in colormap CMAP. If an exact match cannot be
3260 allocated, try the nearest color available. Value is non-zero
3261 if successful. This is called from lwlib. */
3264 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3269 struct frame
*f
= x_frame_of_widget (widget
);
3270 return x_alloc_nearest_color (f
, cmap
, color
);
3274 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3275 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3276 If this produces the same color as PIXEL, try a color where all RGB
3277 values have DELTA added. Return the allocated color in *PIXEL.
3278 DISPLAY is the X display, CMAP is the colormap to operate on.
3279 Value is non-zero if successful. */
3282 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
3286 unsigned long *pixel
;
3290 struct frame
*f
= x_frame_of_widget (widget
);
3291 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
3295 #endif /* USE_X_TOOLKIT */
3298 /* Value is an array of XColor structures for the contents of the
3299 color map of frame F. Set *NCELLS to the size of the array.
3300 Note that this probably shouldn't be called for large color maps,
3301 say a 24-bit TrueColor map. */
3303 static const XColor
*
3304 x_color_cells (f
, ncells
)
3308 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3310 if (dpyinfo
->color_cells
== NULL
)
3312 Display
*display
= FRAME_X_DISPLAY (f
);
3313 Screen
*screen
= FRAME_X_SCREEN (f
);
3316 dpyinfo
->ncolor_cells
3317 = XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3318 dpyinfo
->color_cells
3319 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
3320 * sizeof *dpyinfo
->color_cells
);
3322 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
3323 dpyinfo
->color_cells
[i
].pixel
= i
;
3325 XQueryColors (display
, FRAME_X_COLORMAP (f
),
3326 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
3329 *ncells
= dpyinfo
->ncolor_cells
;
3330 return dpyinfo
->color_cells
;
3334 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3335 colors in COLORS. Use cached information, if available. */
3338 x_query_colors (f
, colors
, ncolors
)
3343 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3345 if (dpyinfo
->color_cells
)
3348 for (i
= 0; i
< ncolors
; ++i
)
3350 unsigned long pixel
= colors
[i
].pixel
;
3351 xassert (pixel
< dpyinfo
->ncolor_cells
);
3352 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
3353 colors
[i
] = dpyinfo
->color_cells
[pixel
];
3357 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
3361 /* On frame F, translate pixel color to RGB values for the color in
3362 COLOR. Use cached information, if available. */
3365 x_query_color (f
, color
)
3369 x_query_colors (f
, color
, 1);
3373 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3374 CMAP. If an exact match can't be allocated, try the nearest color
3375 available. Value is non-zero if successful. Set *COLOR to the
3379 x_alloc_nearest_color (f
, cmap
, color
)
3384 Display
*display
= FRAME_X_DISPLAY (f
);
3385 Screen
*screen
= FRAME_X_SCREEN (f
);
3388 gamma_correct (f
, color
);
3389 rc
= XAllocColor (display
, cmap
, color
);
3392 /* If we got to this point, the colormap is full, so we're going
3393 to try to get the next closest color. The algorithm used is
3394 a least-squares matching, which is what X uses for closest
3395 color matching with StaticColor visuals. */
3397 unsigned long nearest_delta
= ~0;
3399 const XColor
*cells
= x_color_cells (f
, &ncells
);
3401 for (nearest
= i
= 0; i
< ncells
; ++i
)
3403 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3404 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3405 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3406 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3408 if (delta
< nearest_delta
)
3411 nearest_delta
= delta
;
3415 color
->red
= cells
[nearest
].red
;
3416 color
->green
= cells
[nearest
].green
;
3417 color
->blue
= cells
[nearest
].blue
;
3418 rc
= XAllocColor (display
, cmap
, color
);
3422 /* If allocation succeeded, and the allocated pixel color is not
3423 equal to a cached pixel color recorded earlier, there was a
3424 change in the colormap, so clear the color cache. */
3425 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3426 XColor
*cached_color
;
3428 if (dpyinfo
->color_cells
3429 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
3430 (cached_color
->red
!= color
->red
3431 || cached_color
->blue
!= color
->blue
3432 || cached_color
->green
!= color
->green
)))
3434 xfree (dpyinfo
->color_cells
);
3435 dpyinfo
->color_cells
= NULL
;
3436 dpyinfo
->ncolor_cells
= 0;
3440 #ifdef DEBUG_X_COLORS
3442 register_color (color
->pixel
);
3443 #endif /* DEBUG_X_COLORS */
3449 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3450 It's necessary to do this instead of just using PIXEL directly to
3451 get color reference counts right. */
3454 x_copy_color (f
, pixel
)
3456 unsigned long pixel
;
3460 color
.pixel
= pixel
;
3462 x_query_color (f
, &color
);
3463 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3465 #ifdef DEBUG_X_COLORS
3466 register_color (pixel
);
3472 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3473 It's necessary to do this instead of just using PIXEL directly to
3474 get color reference counts right. */
3477 x_copy_dpy_color (dpy
, cmap
, pixel
)
3480 unsigned long pixel
;
3484 color
.pixel
= pixel
;
3486 XQueryColor (dpy
, cmap
, &color
);
3487 XAllocColor (dpy
, cmap
, &color
);
3489 #ifdef DEBUG_X_COLORS
3490 register_color (pixel
);
3496 /* Brightness beyond which a color won't have its highlight brightness
3499 Nominally, highlight colors for `3d' faces are calculated by
3500 brightening an object's color by a constant scale factor, but this
3501 doesn't yield good results for dark colors, so for colors who's
3502 brightness is less than this value (on a scale of 0-65535) have an
3503 use an additional additive factor.
3505 The value here is set so that the default menu-bar/mode-line color
3506 (grey75) will not have its highlights changed at all. */
3507 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3510 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3511 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3512 If this produces the same color as PIXEL, try a color where all RGB
3513 values have DELTA added. Return the allocated color in *PIXEL.
3514 DISPLAY is the X display, CMAP is the colormap to operate on.
3515 Value is non-zero if successful. */
3518 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3522 unsigned long *pixel
;
3530 /* Get RGB color values. */
3531 color
.pixel
= *pixel
;
3532 x_query_color (f
, &color
);
3534 /* Change RGB values by specified FACTOR. Avoid overflow! */
3535 xassert (factor
>= 0);
3536 new.red
= min (0xffff, factor
* color
.red
);
3537 new.green
= min (0xffff, factor
* color
.green
);
3538 new.blue
= min (0xffff, factor
* color
.blue
);
3540 /* Calculate brightness of COLOR. */
3541 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
3543 /* We only boost colors that are darker than
3544 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3545 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
3546 /* Make an additive adjustment to NEW, because it's dark enough so
3547 that scaling by FACTOR alone isn't enough. */
3549 /* How far below the limit this color is (0 - 1, 1 being darker). */
3550 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
3551 /* The additive adjustment. */
3552 int min_delta
= delta
* dimness
* factor
/ 2;
3556 new.red
= max (0, new.red
- min_delta
);
3557 new.green
= max (0, new.green
- min_delta
);
3558 new.blue
= max (0, new.blue
- min_delta
);
3562 new.red
= min (0xffff, min_delta
+ new.red
);
3563 new.green
= min (0xffff, min_delta
+ new.green
);
3564 new.blue
= min (0xffff, min_delta
+ new.blue
);
3568 /* Try to allocate the color. */
3569 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3572 if (new.pixel
== *pixel
)
3574 /* If we end up with the same color as before, try adding
3575 delta to the RGB values. */
3576 x_free_colors (f
, &new.pixel
, 1);
3578 new.red
= min (0xffff, delta
+ color
.red
);
3579 new.green
= min (0xffff, delta
+ color
.green
);
3580 new.blue
= min (0xffff, delta
+ color
.blue
);
3581 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3592 /* Set up the foreground color for drawing relief lines of glyph
3593 string S. RELIEF is a pointer to a struct relief containing the GC
3594 with which lines will be drawn. Use a color that is FACTOR or
3595 DELTA lighter or darker than the relief's background which is found
3596 in S->f->output_data.x->relief_background. If such a color cannot
3597 be allocated, use DEFAULT_PIXEL, instead. */
3600 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3602 struct relief
*relief
;
3605 unsigned long default_pixel
;
3608 struct x_output
*di
= f
->output_data
.x
;
3609 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3610 unsigned long pixel
;
3611 unsigned long background
= di
->relief_background
;
3612 Colormap cmap
= FRAME_X_COLORMAP (f
);
3613 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3614 Display
*dpy
= FRAME_X_DISPLAY (f
);
3616 xgcv
.graphics_exposures
= False
;
3617 xgcv
.line_width
= 1;
3619 /* Free previously allocated color. The color cell will be reused
3620 when it has been freed as many times as it was allocated, so this
3621 doesn't affect faces using the same colors. */
3623 && relief
->allocated_p
)
3625 x_free_colors (f
, &relief
->pixel
, 1);
3626 relief
->allocated_p
= 0;
3629 /* Allocate new color. */
3630 xgcv
.foreground
= default_pixel
;
3632 if (dpyinfo
->n_planes
!= 1
3633 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3635 relief
->allocated_p
= 1;
3636 xgcv
.foreground
= relief
->pixel
= pixel
;
3639 if (relief
->gc
== 0)
3641 xgcv
.stipple
= dpyinfo
->gray
;
3643 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3646 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3650 /* Set up colors for the relief lines around glyph string S. */
3653 x_setup_relief_colors (s
)
3654 struct glyph_string
*s
;
3656 struct x_output
*di
= s
->f
->output_data
.x
;
3657 unsigned long color
;
3659 if (s
->face
->use_box_color_for_shadows_p
)
3660 color
= s
->face
->box_color
;
3665 /* Get the background color of the face. */
3666 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3667 color
= xgcv
.background
;
3670 if (di
->white_relief
.gc
== 0
3671 || color
!= di
->relief_background
)
3673 di
->relief_background
= color
;
3674 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3675 WHITE_PIX_DEFAULT (s
->f
));
3676 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3677 BLACK_PIX_DEFAULT (s
->f
));
3682 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3683 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3684 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3685 relief. LEFT_P non-zero means draw a relief on the left side of
3686 the rectangle. RIGHT_P non-zero means draw a relief on the right
3687 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3691 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3692 raised_p
, left_p
, right_p
, clip_rect
)
3694 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3695 XRectangle
*clip_rect
;
3701 gc
= f
->output_data
.x
->white_relief
.gc
;
3703 gc
= f
->output_data
.x
->black_relief
.gc
;
3704 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3707 for (i
= 0; i
< width
; ++i
)
3708 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3709 left_x
+ i
* left_p
, top_y
+ i
,
3710 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3714 for (i
= 0; i
< width
; ++i
)
3715 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3716 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3718 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3720 gc
= f
->output_data
.x
->black_relief
.gc
;
3722 gc
= f
->output_data
.x
->white_relief
.gc
;
3723 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3726 for (i
= 0; i
< width
; ++i
)
3727 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3728 left_x
+ i
* left_p
, bottom_y
- i
,
3729 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3733 for (i
= 0; i
< width
; ++i
)
3734 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3735 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3737 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3741 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3742 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3743 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3744 left side of the rectangle. RIGHT_P non-zero means draw a line
3745 on the right side of the rectangle. CLIP_RECT is the clipping
3746 rectangle to use when drawing. */
3749 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3750 left_p
, right_p
, clip_rect
)
3751 struct glyph_string
*s
;
3752 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3753 XRectangle
*clip_rect
;
3757 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3758 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3759 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3762 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3763 left_x
, top_y
, right_x
- left_x
+ 1, width
);
3767 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3768 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
3771 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3772 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
3776 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3777 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
3779 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3780 XSetClipMask (s
->display
, s
->gc
, None
);
3784 /* Draw a box around glyph string S. */
3787 x_draw_glyph_string_box (s
)
3788 struct glyph_string
*s
;
3790 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3791 int left_p
, right_p
;
3792 struct glyph
*last_glyph
;
3793 XRectangle clip_rect
;
3795 last_x
= window_box_right (s
->w
, s
->area
);
3796 if (s
->row
->full_width_p
3797 && !s
->w
->pseudo_window_p
)
3799 last_x
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s
->f
);
3800 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3801 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3804 /* The glyph that may have a right box line. */
3805 last_glyph
= (s
->cmp
|| s
->img
3807 : s
->first_glyph
+ s
->nchars
- 1);
3809 width
= s
->face
->box_line_width
;
3810 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3812 right_x
= ((s
->row
->full_width_p
3814 : min (last_x
, s
->x
+ s
->background_width
) - 1));
3816 bottom_y
= top_y
+ s
->height
- 1;
3818 left_p
= (s
->first_glyph
->left_box_line_p
3819 || (s
->hl
== DRAW_MOUSE_FACE
3821 || s
->prev
->hl
!= s
->hl
)));
3822 right_p
= (last_glyph
->right_box_line_p
3823 || (s
->hl
== DRAW_MOUSE_FACE
3825 || s
->next
->hl
!= s
->hl
)));
3827 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3829 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3830 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3831 left_p
, right_p
, &clip_rect
);
3834 x_setup_relief_colors (s
);
3835 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3836 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3841 /* Draw foreground of image glyph string S. */
3844 x_draw_image_foreground (s
)
3845 struct glyph_string
*s
;
3848 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
3850 /* If first glyph of S has a left box line, start drawing it to the
3851 right of that line. */
3852 if (s
->face
->box
!= FACE_NO_BOX
3853 && s
->first_glyph
->left_box_line_p
)
3854 x
= s
->x
+ s
->face
->box_line_width
;
3858 /* If there is a margin around the image, adjust x- and y-position
3862 x
+= s
->img
->margin
;
3863 y
+= s
->img
->margin
;
3870 /* We can't set both a clip mask and use XSetClipRectangles
3871 because the latter also sets a clip mask. We also can't
3872 trust on the shape extension to be available
3873 (XShapeCombineRegion). So, compute the rectangle to draw
3875 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3878 XRectangle clip_rect
, image_rect
, r
;
3880 xgcv
.clip_mask
= s
->img
->mask
;
3881 xgcv
.clip_x_origin
= x
;
3882 xgcv
.clip_y_origin
= y
;
3883 xgcv
.function
= GXcopy
;
3884 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3886 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3889 image_rect
.width
= s
->img
->width
;
3890 image_rect
.height
= s
->img
->height
;
3891 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3892 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3893 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3897 unsigned long mask
= GCClipXOrigin
| GCClipYOrigin
| GCFunction
;
3899 XRectangle clip_rect
, image_rect
, r
;
3901 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3904 image_rect
.width
= s
->img
->width
;
3905 image_rect
.height
= s
->img
->height
;
3906 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3907 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3908 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3910 /* When the image has a mask, we can expect that at
3911 least part of a mouse highlight or a block cursor will
3912 be visible. If the image doesn't have a mask, make
3913 a block cursor visible by drawing a rectangle around
3914 the image. I believe it's looking better if we do
3915 nothing here for mouse-face. */
3916 if (s
->hl
== DRAW_CURSOR
)
3917 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3918 s
->img
->width
- 1, s
->img
->height
- 1);
3922 /* Draw a rectangle if image could not be loaded. */
3923 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3924 s
->img
->width
- 1, s
->img
->height
- 1);
3928 /* Draw a relief around the image glyph string S. */
3931 x_draw_image_relief (s
)
3932 struct glyph_string
*s
;
3934 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3937 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
3939 /* If first glyph of S has a left box line, start drawing it to the
3940 right of that line. */
3941 if (s
->face
->box
!= FACE_NO_BOX
3942 && s
->first_glyph
->left_box_line_p
)
3943 x
= s
->x
+ s
->face
->box_line_width
;
3947 /* If there is a margin around the image, adjust x- and y-position
3951 x
+= s
->img
->margin
;
3952 y
+= s
->img
->margin
;
3955 if (s
->hl
== DRAW_IMAGE_SUNKEN
3956 || s
->hl
== DRAW_IMAGE_RAISED
)
3958 thick
= tool_bar_button_relief
> 0 ? tool_bar_button_relief
: 3;
3959 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3963 thick
= abs (s
->img
->relief
);
3964 raised_p
= s
->img
->relief
> 0;
3969 x1
= x
+ s
->img
->width
+ thick
- 1;
3970 y1
= y
+ s
->img
->height
+ thick
- 1;
3972 x_setup_relief_colors (s
);
3973 x_get_glyph_string_clip_rect (s
, &r
);
3974 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3978 /* Draw the foreground of image glyph string S to PIXMAP. */
3981 x_draw_image_foreground_1 (s
, pixmap
)
3982 struct glyph_string
*s
;
3986 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
3988 /* If first glyph of S has a left box line, start drawing it to the
3989 right of that line. */
3990 if (s
->face
->box
!= FACE_NO_BOX
3991 && s
->first_glyph
->left_box_line_p
)
3992 x
= s
->face
->box_line_width
;
3996 /* If there is a margin around the image, adjust x- and y-position
4000 x
+= s
->img
->margin
;
4001 y
+= s
->img
->margin
;
4008 /* We can't set both a clip mask and use XSetClipRectangles
4009 because the latter also sets a clip mask. We also can't
4010 trust on the shape extension to be available
4011 (XShapeCombineRegion). So, compute the rectangle to draw
4013 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
4017 xgcv
.clip_mask
= s
->img
->mask
;
4018 xgcv
.clip_x_origin
= x
;
4019 xgcv
.clip_y_origin
= y
;
4020 xgcv
.function
= GXcopy
;
4021 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
4023 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4024 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4025 XSetClipMask (s
->display
, s
->gc
, None
);
4029 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
4030 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
4032 /* When the image has a mask, we can expect that at
4033 least part of a mouse highlight or a block cursor will
4034 be visible. If the image doesn't have a mask, make
4035 a block cursor visible by drawing a rectangle around
4036 the image. I believe it's looking better if we do
4037 nothing here for mouse-face. */
4038 if (s
->hl
== DRAW_CURSOR
)
4039 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
4040 s
->img
->width
- 1, s
->img
->height
- 1);
4044 /* Draw a rectangle if image could not be loaded. */
4045 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
4046 s
->img
->width
- 1, s
->img
->height
- 1);
4050 /* Draw part of the background of glyph string S. X, Y, W, and H
4051 give the rectangle to draw. */
4054 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
4055 struct glyph_string
*s
;
4060 /* Fill background with a stipple pattern. */
4061 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4062 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
4063 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4066 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
4070 /* Draw image glyph string S.
4073 s->x +-------------------------
4076 | +-------------------------
4079 | | +-------------------
4085 x_draw_image_glyph_string (s
)
4086 struct glyph_string
*s
;
4089 int box_line_width
= s
->face
->box_line_width
;
4090 int margin
= s
->img
->margin
;
4092 Pixmap pixmap
= None
;
4094 height
= s
->height
- 2 * box_line_width
;
4096 /* Fill background with face under the image. Do it only if row is
4097 taller than image or if image has a clip mask to reduce
4099 s
->stippled_p
= s
->face
->stipple
!= 0;
4100 if (height
> s
->img
->height
4103 || s
->img
->pixmap
== 0
4104 || s
->width
!= s
->background_width
)
4106 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
4107 x
= s
->x
+ box_line_width
;
4111 y
= s
->y
+ box_line_width
;
4115 /* Create a pixmap as large as the glyph string. Fill it
4116 with the background color. Copy the image to it, using
4117 its mask. Copy the temporary pixmap to the display. */
4118 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
4119 int depth
= DefaultDepthOfScreen (screen
);
4121 /* Create a pixmap as large as the glyph string. */
4122 pixmap
= XCreatePixmap (s
->display
, s
->window
,
4123 s
->background_width
,
4126 /* Don't clip in the following because we're working on the
4128 XSetClipMask (s
->display
, s
->gc
, None
);
4130 /* Fill the pixmap with the background color/stipple. */
4133 /* Fill background with a stipple pattern. */
4134 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
4135 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4136 0, 0, s
->background_width
, s
->height
);
4137 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
4142 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
4144 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
4145 XFillRectangle (s
->display
, pixmap
, s
->gc
,
4146 0, 0, s
->background_width
, s
->height
);
4147 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4151 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
4153 s
->background_filled_p
= 1;
4156 /* Draw the foreground. */
4159 x_draw_image_foreground_1 (s
, pixmap
);
4160 x_set_glyph_string_clipping (s
);
4161 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
4162 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
4163 XFreePixmap (s
->display
, pixmap
);
4166 x_draw_image_foreground (s
);
4168 /* If we must draw a relief around the image, do it. */
4170 || s
->hl
== DRAW_IMAGE_RAISED
4171 || s
->hl
== DRAW_IMAGE_SUNKEN
)
4172 x_draw_image_relief (s
);
4176 /* Draw stretch glyph string S. */
4179 x_draw_stretch_glyph_string (s
)
4180 struct glyph_string
*s
;
4182 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4183 s
->stippled_p
= s
->face
->stipple
!= 0;
4185 if (s
->hl
== DRAW_CURSOR
4186 && !x_stretch_cursor_p
)
4188 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4189 as wide as the stretch glyph. */
4190 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
4193 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
4195 /* Clear rest using the GC of the original non-cursor face. */
4196 if (width
< s
->background_width
)
4198 GC gc
= s
->face
->gc
;
4199 int x
= s
->x
+ width
, y
= s
->y
;
4200 int w
= s
->background_width
- width
, h
= s
->height
;
4203 x_get_glyph_string_clip_rect (s
, &r
);
4204 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
4206 if (s
->face
->stipple
)
4208 /* Fill background with a stipple pattern. */
4209 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
4210 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4211 XSetFillStyle (s
->display
, gc
, FillSolid
);
4216 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
4217 XSetForeground (s
->display
, gc
, xgcv
.background
);
4218 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
4219 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
4224 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
4227 s
->background_filled_p
= 1;
4231 /* Draw glyph string S. */
4234 x_draw_glyph_string (s
)
4235 struct glyph_string
*s
;
4237 /* If S draws into the background of its successor, draw the
4238 background of the successor first so that S can draw into it.
4239 This makes S->next use XDrawString instead of XDrawImageString. */
4240 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
4242 xassert (s
->next
->img
== NULL
);
4243 x_set_glyph_string_gc (s
->next
);
4244 x_set_glyph_string_clipping (s
->next
);
4245 x_draw_glyph_string_background (s
->next
, 1);
4248 /* Set up S->gc, set clipping and draw S. */
4249 x_set_glyph_string_gc (s
);
4250 x_set_glyph_string_clipping (s
);
4252 switch (s
->first_glyph
->type
)
4255 x_draw_image_glyph_string (s
);
4259 x_draw_stretch_glyph_string (s
);
4263 if (s
->for_overlaps_p
)
4264 s
->background_filled_p
= 1;
4266 x_draw_glyph_string_background (s
, 0);
4267 x_draw_glyph_string_foreground (s
);
4270 case COMPOSITE_GLYPH
:
4271 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4272 s
->background_filled_p
= 1;
4274 x_draw_glyph_string_background (s
, 1);
4275 x_draw_composite_glyph_string_foreground (s
);
4282 if (!s
->for_overlaps_p
)
4284 /* Draw underline. */
4285 if (s
->face
->underline_p
)
4287 unsigned long tem
, h
;
4290 /* Get the underline thickness. Default is 1 pixel. */
4291 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4294 /* Get the underline position. This is the recommended
4295 vertical offset in pixels from the baseline to the top of
4296 the underline. This is a signed value according to the
4297 specs, and its default is
4299 ROUND ((maximum descent) / 2), with
4300 ROUND(x) = floor (x + 0.5) */
4302 if (XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
4303 y
= s
->ybase
+ (long) tem
;
4304 else if (s
->face
->font
)
4305 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
4309 if (s
->face
->underline_defaulted_p
)
4310 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4311 s
->x
, y
, s
->width
, h
);
4315 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4316 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4317 XFillRectangle (s
->display
, s
->window
, s
->gc
,
4318 s
->x
, y
, s
->width
, h
);
4319 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4323 /* Draw overline. */
4324 if (s
->face
->overline_p
)
4326 unsigned long dy
= 0, h
= 1;
4328 if (s
->face
->overline_color_defaulted_p
)
4329 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4334 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4335 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4336 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4338 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4342 /* Draw strike-through. */
4343 if (s
->face
->strike_through_p
)
4345 unsigned long h
= 1;
4346 unsigned long dy
= (s
->height
- h
) / 2;
4348 if (s
->face
->strike_through_color_defaulted_p
)
4349 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4354 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4355 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4356 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4358 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4363 if (s
->face
->box
!= FACE_NO_BOX
)
4364 x_draw_glyph_string_box (s
);
4367 /* Reset clipping. */
4368 XSetClipMask (s
->display
, s
->gc
, None
);
4372 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4373 struct face
**, int));
4376 /* Fill glyph string S with composition components specified by S->cmp.
4378 FACES is an array of faces for all components of this composition.
4379 S->gidx is the index of the first component for S.
4380 OVERLAPS_P non-zero means S should draw the foreground only, and
4381 use its physical height for clipping.
4383 Value is the index of a component not in S. */
4386 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4387 struct glyph_string
*s
;
4388 struct face
**faces
;
4395 s
->for_overlaps_p
= overlaps_p
;
4397 s
->face
= faces
[s
->gidx
];
4398 s
->font
= s
->face
->font
;
4399 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4401 /* For all glyphs of this composition, starting at the offset
4402 S->gidx, until we reach the end of the definition or encounter a
4403 glyph that requires the different face, add it to S. */
4405 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4408 /* All glyph strings for the same composition has the same width,
4409 i.e. the width set for the first component of the composition. */
4411 s
->width
= s
->first_glyph
->pixel_width
;
4413 /* If the specified font could not be loaded, use the frame's
4414 default font, but record the fact that we couldn't load it in
4415 the glyph string so that we can draw rectangles for the
4416 characters of the glyph string. */
4417 if (s
->font
== NULL
)
4419 s
->font_not_found_p
= 1;
4420 s
->font
= FRAME_FONT (s
->f
);
4423 /* Adjust base line for subscript/superscript text. */
4424 s
->ybase
+= s
->first_glyph
->voffset
;
4426 xassert (s
->face
&& s
->face
->gc
);
4428 /* This glyph string must always be drawn with 16-bit functions. */
4431 return s
->gidx
+ s
->nchars
;
4435 /* Fill glyph string S from a sequence of character glyphs.
4437 FACE_ID is the face id of the string. START is the index of the
4438 first glyph to consider, END is the index of the last + 1.
4439 OVERLAPS_P non-zero means S should draw the foreground only, and
4440 use its physical height for clipping.
4442 Value is the index of the first glyph not in S. */
4445 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4446 struct glyph_string
*s
;
4448 int start
, end
, overlaps_p
;
4450 struct glyph
*glyph
, *last
;
4452 int glyph_not_available_p
;
4454 xassert (s
->f
== XFRAME (s
->w
->frame
));
4455 xassert (s
->nchars
== 0);
4456 xassert (start
>= 0 && end
> start
);
4458 s
->for_overlaps_p
= overlaps_p
,
4459 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4460 last
= s
->row
->glyphs
[s
->area
] + end
;
4461 voffset
= glyph
->voffset
;
4463 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4466 && glyph
->type
== CHAR_GLYPH
4467 && glyph
->voffset
== voffset
4468 /* Same face id implies same font, nowadays. */
4469 && glyph
->face_id
== face_id
4470 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
4474 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4475 s
->char2b
+ s
->nchars
,
4477 s
->two_byte_p
= two_byte_p
;
4479 xassert (s
->nchars
<= end
- start
);
4480 s
->width
+= glyph
->pixel_width
;
4484 s
->font
= s
->face
->font
;
4485 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4487 /* If the specified font could not be loaded, use the frame's font,
4488 but record the fact that we couldn't load it in
4489 S->font_not_found_p so that we can draw rectangles for the
4490 characters of the glyph string. */
4491 if (s
->font
== NULL
|| glyph_not_available_p
)
4493 s
->font_not_found_p
= 1;
4494 s
->font
= FRAME_FONT (s
->f
);
4497 /* Adjust base line for subscript/superscript text. */
4498 s
->ybase
+= voffset
;
4500 xassert (s
->face
&& s
->face
->gc
);
4501 return glyph
- s
->row
->glyphs
[s
->area
];
4505 /* Fill glyph string S from image glyph S->first_glyph. */
4508 x_fill_image_glyph_string (s
)
4509 struct glyph_string
*s
;
4511 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4512 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
4514 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
4515 s
->font
= s
->face
->font
;
4516 s
->width
= s
->first_glyph
->pixel_width
;
4518 /* Adjust base line for subscript/superscript text. */
4519 s
->ybase
+= s
->first_glyph
->voffset
;
4523 /* Fill glyph string S from a sequence of stretch glyphs.
4525 ROW is the glyph row in which the glyphs are found, AREA is the
4526 area within the row. START is the index of the first glyph to
4527 consider, END is the index of the last + 1.
4529 Value is the index of the first glyph not in S. */
4532 x_fill_stretch_glyph_string (s
, row
, area
, start
, end
)
4533 struct glyph_string
*s
;
4534 struct glyph_row
*row
;
4535 enum glyph_row_area area
;
4538 struct glyph
*glyph
, *last
;
4539 int voffset
, face_id
;
4541 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4543 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4544 last
= s
->row
->glyphs
[s
->area
] + end
;
4545 face_id
= glyph
->face_id
;
4546 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
4547 s
->font
= s
->face
->font
;
4548 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4549 s
->width
= glyph
->pixel_width
;
4550 voffset
= glyph
->voffset
;
4554 && glyph
->type
== STRETCH_GLYPH
4555 && glyph
->voffset
== voffset
4556 && glyph
->face_id
== face_id
);
4558 s
->width
+= glyph
->pixel_width
;
4560 /* Adjust base line for subscript/superscript text. */
4561 s
->ybase
+= voffset
;
4563 xassert (s
->face
&& s
->face
->gc
);
4564 return glyph
- s
->row
->glyphs
[s
->area
];
4568 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4569 of XChar2b structures for S; it can't be allocated in
4570 x_init_glyph_string because it must be allocated via `alloca'. W
4571 is the window on which S is drawn. ROW and AREA are the glyph row
4572 and area within the row from which S is constructed. START is the
4573 index of the first glyph structure covered by S. HL is a
4574 face-override for drawing S. */
4577 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4578 struct glyph_string
*s
;
4581 struct glyph_row
*row
;
4582 enum glyph_row_area area
;
4584 enum draw_glyphs_face hl
;
4586 bzero (s
, sizeof *s
);
4588 s
->f
= XFRAME (w
->frame
);
4589 s
->display
= FRAME_X_DISPLAY (s
->f
);
4590 s
->window
= FRAME_X_WINDOW (s
->f
);
4595 s
->first_glyph
= row
->glyphs
[area
] + start
;
4596 s
->height
= row
->height
;
4597 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4599 /* Display the internal border below the tool-bar window. */
4600 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4601 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4603 s
->ybase
= s
->y
+ row
->ascent
;
4607 /* Set background width of glyph string S. START is the index of the
4608 first glyph following S. LAST_X is the right-most x-position + 1
4609 in the drawing area. */
4612 x_set_glyph_string_background_width (s
, start
, last_x
)
4613 struct glyph_string
*s
;
4617 /* If the face of this glyph string has to be drawn to the end of
4618 the drawing area, set S->extends_to_end_of_line_p. */
4619 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4621 if (start
== s
->row
->used
[s
->area
]
4622 && s
->hl
== DRAW_NORMAL_TEXT
4623 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4624 || s
->face
->background
!= default_face
->background
4625 || s
->face
->stipple
!= default_face
->stipple
))
4626 s
->extends_to_end_of_line_p
= 1;
4628 /* If S extends its face to the end of the line, set its
4629 background_width to the distance to the right edge of the drawing
4631 if (s
->extends_to_end_of_line_p
)
4632 s
->background_width
= last_x
- s
->x
+ 1;
4634 s
->background_width
= s
->width
;
4638 /* Add a glyph string for a stretch glyph to the list of strings
4639 between HEAD and TAIL. START is the index of the stretch glyph in
4640 row area AREA of glyph row ROW. END is the index of the last glyph
4641 in that glyph row area. X is the current output position assigned
4642 to the new glyph string constructed. HL overrides that face of the
4643 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4644 is the right-most x-position of the drawing area. */
4646 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4647 and below -- keep them on one line. */
4648 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4651 s = (struct glyph_string *) alloca (sizeof *s); \
4652 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4653 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4654 x_append_glyph_string (&HEAD, &TAIL, s); \
4660 /* Add a glyph string for an image glyph to the list of strings
4661 between HEAD and TAIL. START is the index of the image glyph in
4662 row area AREA of glyph row ROW. END is the index of the last glyph
4663 in that glyph row area. X is the current output position assigned
4664 to the new glyph string constructed. HL overrides that face of the
4665 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4666 is the right-most x-position of the drawing area. */
4668 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4671 s = (struct glyph_string *) alloca (sizeof *s); \
4672 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4673 x_fill_image_glyph_string (s); \
4674 x_append_glyph_string (&HEAD, &TAIL, s); \
4681 /* Add a glyph string for a sequence of character glyphs to the list
4682 of strings between HEAD and TAIL. START is the index of the first
4683 glyph in row area AREA of glyph row ROW that is part of the new
4684 glyph string. END is the index of the last glyph in that glyph row
4685 area. X is the current output position assigned to the new glyph
4686 string constructed. HL overrides that face of the glyph; e.g. it
4687 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4688 right-most x-position of the drawing area. */
4690 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4696 c = (ROW)->glyphs[AREA][START].u.ch; \
4697 face_id = (ROW)->glyphs[AREA][START].face_id; \
4699 s = (struct glyph_string *) alloca (sizeof *s); \
4700 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4701 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4702 x_append_glyph_string (&HEAD, &TAIL, s); \
4704 START = x_fill_glyph_string (s, face_id, START, END, \
4710 /* Add a glyph string for a composite sequence to the list of strings
4711 between HEAD and TAIL. START is the index of the first glyph in
4712 row area AREA of glyph row ROW that is part of the new glyph
4713 string. END is the index of the last glyph in that glyph row area.
4714 X is the current output position assigned to the new glyph string
4715 constructed. HL overrides that face of the glyph; e.g. it is
4716 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4717 x-position of the drawing area. */
4719 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4721 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4722 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4723 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4724 struct composition *cmp = composition_table[cmp_id]; \
4725 int glyph_len = cmp->glyph_len; \
4727 struct face **faces; \
4728 struct glyph_string *first_s = NULL; \
4731 base_face = base_face->ascii_face; \
4732 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4733 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4734 /* At first, fill in `char2b' and `faces'. */ \
4735 for (n = 0; n < glyph_len; n++) \
4737 int c = COMPOSITION_GLYPH (cmp, n); \
4738 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4739 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4740 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4741 this_face_id, char2b + n, 1); \
4744 /* Make glyph_strings for each glyph sequence that is drawable by \
4745 the same face, and append them to HEAD/TAIL. */ \
4746 for (n = 0; n < cmp->glyph_len;) \
4748 s = (struct glyph_string *) alloca (sizeof *s); \
4749 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4750 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4758 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4766 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4767 of AREA of glyph row ROW on window W between indices START and END.
4768 HL overrides the face for drawing glyph strings, e.g. it is
4769 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4770 x-positions of the drawing area.
4772 This is an ugly monster macro construct because we must use alloca
4773 to allocate glyph strings (because x_draw_glyphs can be called
4776 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4779 HEAD = TAIL = NULL; \
4780 while (START < END) \
4782 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4783 switch (first_glyph->type) \
4786 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4787 TAIL, HL, X, LAST_X, \
4791 case COMPOSITE_GLYPH: \
4792 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4793 HEAD, TAIL, HL, X, LAST_X,\
4797 case STRETCH_GLYPH: \
4798 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4799 HEAD, TAIL, HL, X, LAST_X); \
4803 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4804 TAIL, HL, X, LAST_X); \
4811 x_set_glyph_string_background_width (s, START, LAST_X); \
4818 /* Draw glyphs between START and END in AREA of ROW on window W,
4819 starting at x-position X. X is relative to AREA in W. HL is a
4820 face-override with the following meaning:
4822 DRAW_NORMAL_TEXT draw normally
4823 DRAW_CURSOR draw in cursor face
4824 DRAW_MOUSE_FACE draw in mouse face.
4825 DRAW_INVERSE_VIDEO draw in mode line face
4826 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4827 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4829 If REAL_START is non-null, return in *REAL_START the real starting
4830 position for display. This can be different from START in case
4831 overlapping glyphs must be displayed. If REAL_END is non-null,
4832 return in *REAL_END the real end position for display. This can be
4833 different from END in case overlapping glyphs must be displayed.
4835 If OVERLAPS_P is non-zero, draw only the foreground of characters
4836 and clip to the physical height of ROW.
4838 Value is the x-position reached, relative to AREA of W. */
4841 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
,
4845 struct glyph_row
*row
;
4846 enum glyph_row_area area
;
4848 enum draw_glyphs_face hl
;
4849 int *real_start
, *real_end
;
4852 struct glyph_string
*head
, *tail
;
4853 struct glyph_string
*s
;
4854 int last_x
, area_width
;
4858 /* Let's rather be paranoid than getting a SEGV. */
4859 end
= min (end
, row
->used
[area
]);
4860 start
= max (0, start
);
4861 start
= min (end
, start
);
4863 *real_start
= start
;
4867 /* Translate X to frame coordinates. Set last_x to the right
4868 end of the drawing area. */
4869 if (row
->full_width_p
)
4871 /* X is relative to the left edge of W, without scroll bars
4873 struct frame
*f
= XFRAME (w
->frame
);
4874 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4875 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4878 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4879 last_x
= window_left_x
+ area_width
;
4881 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4883 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4884 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4890 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4891 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
4895 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4896 area_width
= window_box_width (w
, area
);
4897 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4900 /* Build a doubly-linked list of glyph_string structures between
4901 head and tail from what we have to draw. Note that the macro
4902 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4903 the reason we use a separate variable `i'. */
4905 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
4908 x_reached
= tail
->x
+ tail
->background_width
;
4912 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4913 the row, redraw some glyphs in front or following the glyph
4914 strings built above. */
4915 if (head
&& !overlaps_p
&& row
->contains_overlapping_glyphs_p
)
4918 struct glyph_string
*h
, *t
;
4920 /* Compute overhangs for all glyph strings. */
4921 for (s
= head
; s
; s
= s
->next
)
4922 x_compute_glyph_string_overhangs (s
);
4924 /* Prepend glyph strings for glyphs in front of the first glyph
4925 string that are overwritten because of the first glyph
4926 string's left overhang. The background of all strings
4927 prepended must be drawn because the first glyph string
4929 i
= x_left_overwritten (head
);
4933 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4934 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4938 *real_start
= start
;
4939 x_compute_overhangs_and_x (t
, head
->x
, 1);
4940 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4943 /* Prepend glyph strings for glyphs in front of the first glyph
4944 string that overwrite that glyph string because of their
4945 right overhang. For these strings, only the foreground must
4946 be drawn, because it draws over the glyph string at `head'.
4947 The background must not be drawn because this would overwrite
4948 right overhangs of preceding glyphs for which no glyph
4950 i
= x_left_overwriting (head
);
4953 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4954 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4956 for (s
= h
; s
; s
= s
->next
)
4957 s
->background_filled_p
= 1;
4960 x_compute_overhangs_and_x (t
, head
->x
, 1);
4961 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4964 /* Append glyphs strings for glyphs following the last glyph
4965 string tail that are overwritten by tail. The background of
4966 these strings has to be drawn because tail's foreground draws
4968 i
= x_right_overwritten (tail
);
4971 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4972 DRAW_NORMAL_TEXT
, x
, last_x
,
4974 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4975 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4980 /* Append glyph strings for glyphs following the last glyph
4981 string tail that overwrite tail. The foreground of such
4982 glyphs has to be drawn because it writes into the background
4983 of tail. The background must not be drawn because it could
4984 paint over the foreground of following glyphs. */
4985 i
= x_right_overwriting (tail
);
4988 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4989 DRAW_NORMAL_TEXT
, x
, last_x
,
4991 for (s
= h
; s
; s
= s
->next
)
4992 s
->background_filled_p
= 1;
4993 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4994 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
5000 /* Draw all strings. */
5001 for (s
= head
; s
; s
= s
->next
)
5002 x_draw_glyph_string (s
);
5004 /* Value is the x-position up to which drawn, relative to AREA of W.
5005 This doesn't include parts drawn because of overhangs. */
5006 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
5007 if (!row
->full_width_p
)
5009 if (area
> LEFT_MARGIN_AREA
)
5010 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
5011 if (area
> TEXT_AREA
)
5012 x_reached
-= window_box_width (w
, TEXT_AREA
);
5019 /* Fix the display of area AREA of overlapping row ROW in window W. */
5022 x_fix_overlapping_area (w
, row
, area
)
5024 struct glyph_row
*row
;
5025 enum glyph_row_area area
;
5031 if (area
== LEFT_MARGIN_AREA
)
5033 else if (area
== TEXT_AREA
)
5034 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5036 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5037 + window_box_width (w
, TEXT_AREA
));
5039 for (i
= 0; i
< row
->used
[area
];)
5041 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
5043 int start
= i
, start_x
= x
;
5047 x
+= row
->glyphs
[area
][i
].pixel_width
;
5050 while (i
< row
->used
[area
]
5051 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
5053 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
5055 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
5060 x
+= row
->glyphs
[area
][i
].pixel_width
;
5069 /* Output LEN glyphs starting at START at the nominal cursor position.
5070 Advance the nominal cursor over the text. The global variable
5071 updated_window contains the window being updated, updated_row is
5072 the glyph row being updated, and updated_area is the area of that
5073 row being updated. */
5076 x_write_glyphs (start
, len
)
5077 struct glyph
*start
;
5080 int x
, hpos
, real_start
, real_end
;
5082 xassert (updated_window
&& updated_row
);
5087 hpos
= start
- updated_row
->glyphs
[updated_area
];
5088 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
5089 updated_row
, updated_area
,
5091 (updated_row
->inverse_p
5092 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
5093 &real_start
, &real_end
, 0);
5095 /* If we drew over the cursor, note that it is not visible any more. */
5096 note_overwritten_text_cursor (updated_window
, real_start
,
5097 real_end
- real_start
);
5101 /* Advance the output cursor. */
5102 output_cursor
.hpos
+= len
;
5103 output_cursor
.x
= x
;
5107 /* Insert LEN glyphs from START at the nominal cursor position. */
5110 x_insert_glyphs (start
, len
)
5111 struct glyph
*start
;
5116 int line_height
, shift_by_width
, shifted_region_width
;
5117 struct glyph_row
*row
;
5118 struct glyph
*glyph
;
5119 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
5121 xassert (updated_window
&& updated_row
);
5124 f
= XFRAME (WINDOW_FRAME (w
));
5126 /* Get the height of the line we are in. */
5128 line_height
= row
->height
;
5130 /* Get the width of the glyphs to insert. */
5132 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
5133 shift_by_width
+= glyph
->pixel_width
;
5135 /* Get the width of the region to shift right. */
5136 shifted_region_width
= (window_box_width (w
, updated_area
)
5141 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
5142 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
5143 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5144 f
->output_data
.x
->normal_gc
,
5146 shifted_region_width
, line_height
,
5147 frame_x
+ shift_by_width
, frame_y
);
5149 /* Write the glyphs. */
5150 hpos
= start
- row
->glyphs
[updated_area
];
5151 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
5152 DRAW_NORMAL_TEXT
, &real_start
, &real_end
, 0);
5153 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
5155 /* Advance the output cursor. */
5156 output_cursor
.hpos
+= len
;
5157 output_cursor
.x
+= shift_by_width
;
5162 /* Delete N glyphs at the nominal cursor position. Not implemented
5173 /* Erase the current text line from the nominal cursor position
5174 (inclusive) to pixel column TO_X (exclusive). The idea is that
5175 everything from TO_X onward is already erased.
5177 TO_X is a pixel position relative to updated_area of
5178 updated_window. TO_X == -1 means clear to the end of this area. */
5181 x_clear_end_of_line (to_x
)
5185 struct window
*w
= updated_window
;
5186 int max_x
, min_y
, max_y
;
5187 int from_x
, from_y
, to_y
;
5189 xassert (updated_window
&& updated_row
);
5190 f
= XFRAME (w
->frame
);
5192 if (updated_row
->full_width_p
)
5194 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
5195 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5196 && !w
->pseudo_window_p
)
5197 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
5200 max_x
= window_box_width (w
, updated_area
);
5201 max_y
= window_text_bottom_y (w
);
5203 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5204 of window. For TO_X > 0, truncate to end of drawing area. */
5210 to_x
= min (to_x
, max_x
);
5212 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
5214 /* Notice if the cursor will be cleared by this operation. */
5215 if (!updated_row
->full_width_p
)
5216 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
5218 from_x
= output_cursor
.x
;
5220 /* Translate to frame coordinates. */
5221 if (updated_row
->full_width_p
)
5223 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
5224 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
5228 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
5229 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
5232 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
5233 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
5234 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
5236 /* Prevent inadvertently clearing to end of the X window. */
5237 if (to_x
> from_x
&& to_y
> from_y
)
5240 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5241 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
5248 /* Clear entire frame. If updating_frame is non-null, clear that
5249 frame. Otherwise clear the selected frame. */
5259 f
= SELECTED_FRAME ();
5261 /* Clearing the frame will erase any cursor, so mark them all as no
5263 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5264 output_cursor
.hpos
= output_cursor
.vpos
= 0;
5265 output_cursor
.x
= -1;
5267 /* We don't set the output cursor here because there will always
5268 follow an explicit cursor_to. */
5270 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5272 /* We have to clear the scroll bars, too. If we have changed
5273 colors or something like that, then they should be notified. */
5274 x_scroll_bar_clear (f
);
5276 XFlush (FRAME_X_DISPLAY (f
));
5282 /* Invert the middle quarter of the frame for .15 sec. */
5284 /* We use the select system call to do the waiting, so we have to make
5285 sure it's available. If it isn't, we just won't do visual bells. */
5287 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5290 /* Subtract the `struct timeval' values X and Y, storing the result in
5291 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5294 timeval_subtract (result
, x
, y
)
5295 struct timeval
*result
, x
, y
;
5297 /* Perform the carry for the later subtraction by updating y. This
5298 is safer because on some systems the tv_sec member is unsigned. */
5299 if (x
.tv_usec
< y
.tv_usec
)
5301 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
5302 y
.tv_usec
-= 1000000 * nsec
;
5306 if (x
.tv_usec
- y
.tv_usec
> 1000000)
5308 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
5309 y
.tv_usec
+= 1000000 * nsec
;
5313 /* Compute the time remaining to wait. tv_usec is certainly
5315 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5316 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5318 /* Return indication of whether the result should be considered
5320 return x
.tv_sec
< y
.tv_sec
;
5332 /* Create a GC that will use the GXxor function to flip foreground
5333 pixels into background pixels. */
5337 values
.function
= GXxor
;
5338 values
.foreground
= (f
->output_data
.x
->foreground_pixel
5339 ^ f
->output_data
.x
->background_pixel
);
5341 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5342 GCFunction
| GCForeground
, &values
);
5346 /* Get the height not including a menu bar widget. */
5347 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
5348 /* Height of each line to flash. */
5349 int flash_height
= FRAME_LINE_HEIGHT (f
);
5350 /* These will be the left and right margins of the rectangles. */
5351 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
5352 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
5356 /* Don't flash the area between a scroll bar and the frame
5357 edge it is next to. */
5358 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
5360 case vertical_scroll_bar_left
:
5361 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5364 case vertical_scroll_bar_right
:
5365 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5372 width
= flash_right
- flash_left
;
5374 /* If window is tall, flash top and bottom line. */
5375 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5377 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5379 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5380 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5381 width
, flash_height
);
5382 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5384 (height
- flash_height
5385 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5386 width
, flash_height
);
5389 /* If it is short, flash it all. */
5390 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5391 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5392 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5397 struct timeval wakeup
;
5399 EMACS_GET_TIME (wakeup
);
5401 /* Compute time to wait until, propagating carry from usecs. */
5402 wakeup
.tv_usec
+= 150000;
5403 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5404 wakeup
.tv_usec
%= 1000000;
5406 /* Keep waiting until past the time wakeup. */
5409 struct timeval timeout
;
5411 EMACS_GET_TIME (timeout
);
5413 /* In effect, timeout = wakeup - timeout.
5414 Break if result would be negative. */
5415 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5418 /* Try to wait that long--but we might wake up sooner. */
5419 select (0, NULL
, NULL
, NULL
, &timeout
);
5423 /* If window is tall, flash top and bottom line. */
5424 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5426 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5428 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5429 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5430 width
, flash_height
);
5431 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5433 (height
- flash_height
5434 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5435 width
, flash_height
);
5438 /* If it is short, flash it all. */
5439 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5440 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5441 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5443 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5451 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5454 /* Make audible bell. */
5459 struct frame
*f
= SELECTED_FRAME ();
5461 if (FRAME_X_DISPLAY (f
))
5463 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5470 XBell (FRAME_X_DISPLAY (f
), 0);
5471 XFlush (FRAME_X_DISPLAY (f
));
5478 /* Specify how many text lines, from the top of the window,
5479 should be affected by insert-lines and delete-lines operations.
5480 This, and those operations, are used only within an update
5481 that is bounded by calls to x_update_begin and x_update_end. */
5484 XTset_terminal_window (n
)
5487 /* This function intentionally left blank. */
5492 /***********************************************************************
5494 ***********************************************************************/
5496 /* Perform an insert-lines or delete-lines operation, inserting N
5497 lines or deleting -N lines at vertical position VPOS. */
5500 x_ins_del_lines (vpos
, n
)
5507 /* Scroll part of the display as described by RUN. */
5510 x_scroll_run (w
, run
)
5514 struct frame
*f
= XFRAME (w
->frame
);
5515 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5517 /* Get frame-relative bounding box of the text display area of W,
5518 without mode lines. Include in this box the flags areas to the
5519 left and right of W. */
5520 window_box (w
, -1, &x
, &y
, &width
, &height
);
5521 width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
5522 x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
5524 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5525 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5526 bottom_y
= y
+ height
;
5530 /* Scrolling up. Make sure we don't copy part of the mode
5531 line at the bottom. */
5532 if (from_y
+ run
->height
> bottom_y
)
5533 height
= bottom_y
- from_y
;
5535 height
= run
->height
;
5539 /* Scolling down. Make sure we don't copy over the mode line.
5541 if (to_y
+ run
->height
> bottom_y
)
5542 height
= bottom_y
- to_y
;
5544 height
= run
->height
;
5549 /* Cursor off. Will be switched on again in x_update_window_end. */
5553 XCopyArea (FRAME_X_DISPLAY (f
),
5554 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5555 f
->output_data
.x
->normal_gc
,
5565 /***********************************************************************
5567 ***********************************************************************/
5569 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5570 corner of the exposed rectangle. W and H are width and height of
5571 the exposed area. All are pixel values. W or H zero means redraw
5572 the entire frame. */
5575 expose_frame (f
, x
, y
, w
, h
)
5581 TRACE ((stderr
, "expose_frame "));
5583 /* No need to redraw if frame will be redrawn soon. */
5584 if (FRAME_GARBAGED_P (f
))
5586 TRACE ((stderr
, " garbaged\n"));
5590 /* If basic faces haven't been realized yet, there is no point in
5591 trying to redraw anything. This can happen when we get an expose
5592 event while Emacs is starting, e.g. by moving another window. */
5593 if (FRAME_FACE_CACHE (f
) == NULL
5594 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5596 TRACE ((stderr
, " no faces\n"));
5600 if (w
== 0 || h
== 0)
5603 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5604 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5614 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5615 expose_window_tree (XWINDOW (f
->root_window
), &r
);
5617 if (WINDOWP (f
->tool_bar_window
))
5619 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5620 XRectangle window_rect
;
5621 XRectangle intersection_rect
;
5622 int window_x
, window_y
, window_width
, window_height
;
5625 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5626 window_rect
.x
= window_x
;
5627 window_rect
.y
= window_y
;
5628 window_rect
.width
= window_width
;
5629 window_rect
.height
= window_height
;
5631 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5632 expose_window (w
, &intersection_rect
);
5635 #ifndef USE_X_TOOLKIT
5636 if (WINDOWP (f
->menu_bar_window
))
5638 struct window
*w
= XWINDOW (f
->menu_bar_window
);
5639 XRectangle window_rect
;
5640 XRectangle intersection_rect
;
5641 int window_x
, window_y
, window_width
, window_height
;
5644 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5645 window_rect
.x
= window_x
;
5646 window_rect
.y
= window_y
;
5647 window_rect
.width
= window_width
;
5648 window_rect
.height
= window_height
;
5650 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5651 expose_window (w
, &intersection_rect
);
5653 #endif /* not USE_X_TOOLKIT */
5657 /* Redraw (parts) of all windows in the window tree rooted at W that
5658 intersect R. R contains frame pixel coordinates. */
5661 expose_window_tree (w
, r
)
5667 if (!NILP (w
->hchild
))
5668 expose_window_tree (XWINDOW (w
->hchild
), r
);
5669 else if (!NILP (w
->vchild
))
5670 expose_window_tree (XWINDOW (w
->vchild
), r
);
5673 XRectangle window_rect
;
5674 XRectangle intersection_rect
;
5675 struct frame
*f
= XFRAME (w
->frame
);
5676 int window_x
, window_y
, window_width
, window_height
;
5678 /* Frame-relative pixel rectangle of W. */
5679 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5683 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
5684 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5685 window_rect
.y
= window_y
;
5688 + FRAME_X_FLAGS_AREA_WIDTH (f
)
5689 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5691 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5693 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5694 expose_window (w
, &intersection_rect
);
5697 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5702 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5703 which intersects rectangle R. R is in window-relative coordinates. */
5706 expose_area (w
, row
, r
, area
)
5708 struct glyph_row
*row
;
5710 enum glyph_row_area area
;
5713 struct glyph
*first
= row
->glyphs
[area
];
5714 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5718 /* Set x to the window-relative start position for drawing glyphs of
5719 AREA. The first glyph of the text area can be partially visible.
5720 The first glyphs of other areas cannot. */
5721 if (area
== LEFT_MARGIN_AREA
)
5723 else if (area
== TEXT_AREA
)
5724 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5726 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5727 + window_box_width (w
, TEXT_AREA
));
5729 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5730 /* If row extends face to end of line write the whole line. */
5731 x_draw_glyphs (w
, x
, row
, area
,
5733 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5737 /* Find the first glyph that must be redrawn. */
5739 && x
+ first
->pixel_width
< r
->x
)
5741 x
+= first
->pixel_width
;
5745 /* Find the last one. */
5749 && x
< r
->x
+ r
->width
)
5751 x
+= last
->pixel_width
;
5757 x_draw_glyphs (w
, first_x
, row
, area
,
5758 first
- row
->glyphs
[area
],
5759 last
- row
->glyphs
[area
],
5760 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5766 /* Redraw the parts of the glyph row ROW on window W intersecting
5767 rectangle R. R is in window-relative coordinates. */
5770 expose_line (w
, row
, r
)
5772 struct glyph_row
*row
;
5775 xassert (row
->enabled_p
);
5777 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5778 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5779 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5783 if (row
->used
[LEFT_MARGIN_AREA
])
5784 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5785 if (row
->used
[TEXT_AREA
])
5786 expose_area (w
, row
, r
, TEXT_AREA
);
5787 if (row
->used
[RIGHT_MARGIN_AREA
])
5788 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5789 x_draw_row_bitmaps (w
, row
);
5794 /* Return non-zero if W's cursor intersects rectangle R. */
5797 x_phys_cursor_in_rect_p (w
, r
)
5801 XRectangle cr
, result
;
5802 struct glyph
*cursor_glyph
;
5804 cursor_glyph
= get_phys_cursor_glyph (w
);
5807 cr
.x
= w
->phys_cursor
.x
;
5808 cr
.y
= w
->phys_cursor
.y
;
5809 cr
.width
= cursor_glyph
->pixel_width
;
5810 cr
.height
= w
->phys_cursor_height
;
5811 return x_intersect_rectangles (&cr
, r
, &result
);
5818 /* Redraw a rectangle of window W. R is a rectangle in window
5819 relative coordinates. Call this function with input blocked. */
5822 expose_window (w
, r
)
5826 struct glyph_row
*row
;
5828 int yb
= window_text_bottom_y (w
);
5829 int cursor_cleared_p
;
5831 /* If window is not yet fully initialized, do nothing. This can
5832 happen when toolkit scroll bars are used and a window is split.
5833 Reconfiguring the scroll bar will generate an expose for a newly
5835 if (w
->current_matrix
== NULL
)
5838 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5839 r
->x
, r
->y
, r
->width
, r
->height
));
5841 /* Convert to window coordinates. */
5842 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5843 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5845 /* Turn off the cursor. */
5846 if (!w
->pseudo_window_p
5847 && x_phys_cursor_in_rect_p (w
, r
))
5850 cursor_cleared_p
= 1;
5853 cursor_cleared_p
= 0;
5855 /* Find the first row intersecting the rectangle R. */
5856 row
= w
->current_matrix
->rows
;
5858 while (row
->enabled_p
5860 && y
+ row
->height
< r
->y
)
5866 /* Display the text in the rectangle, one text line at a time. */
5867 while (row
->enabled_p
5869 && y
< r
->y
+ r
->height
)
5871 expose_line (w
, row
, r
);
5876 /* Display the mode line if there is one. */
5877 if (WINDOW_WANTS_MODELINE_P (w
)
5878 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5880 && row
->y
< r
->y
+ r
->height
)
5881 expose_line (w
, row
, r
);
5883 if (!w
->pseudo_window_p
)
5885 /* Draw border between windows. */
5886 x_draw_vertical_border (w
);
5888 /* Turn the cursor on again. */
5889 if (cursor_cleared_p
)
5890 x_update_window_cursor (w
, 1);
5895 /* Determine the intersection of two rectangles R1 and R2. Return
5896 the intersection in *RESULT. Value is non-zero if RESULT is not
5900 x_intersect_rectangles (r1
, r2
, result
)
5901 XRectangle
*r1
, *r2
, *result
;
5903 XRectangle
*left
, *right
;
5904 XRectangle
*upper
, *lower
;
5905 int intersection_p
= 0;
5907 /* Rearrange so that R1 is the left-most rectangle. */
5909 left
= r1
, right
= r2
;
5911 left
= r2
, right
= r1
;
5913 /* X0 of the intersection is right.x0, if this is inside R1,
5914 otherwise there is no intersection. */
5915 if (right
->x
<= left
->x
+ left
->width
)
5917 result
->x
= right
->x
;
5919 /* The right end of the intersection is the minimum of the
5920 the right ends of left and right. */
5921 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5924 /* Same game for Y. */
5926 upper
= r1
, lower
= r2
;
5928 upper
= r2
, lower
= r1
;
5930 /* The upper end of the intersection is lower.y0, if this is inside
5931 of upper. Otherwise, there is no intersection. */
5932 if (lower
->y
<= upper
->y
+ upper
->height
)
5934 result
->y
= lower
->y
;
5936 /* The lower end of the intersection is the minimum of the lower
5937 ends of upper and lower. */
5938 result
->height
= (min (lower
->y
+ lower
->height
,
5939 upper
->y
+ upper
->height
)
5945 return intersection_p
;
5956 /* We used to only do this if Vx_no_window_manager was non-nil, but
5957 the ICCCM (section 4.1.6) says that the window's border pixmap
5958 and border pixel are window attributes which are "private to the
5959 client", so we can always change it to whatever we want. */
5961 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5962 f
->output_data
.x
->border_pixel
);
5964 x_update_cursor (f
, 1);
5968 frame_unhighlight (f
)
5971 /* We used to only do this if Vx_no_window_manager was non-nil, but
5972 the ICCCM (section 4.1.6) says that the window's border pixmap
5973 and border pixel are window attributes which are "private to the
5974 client", so we can always change it to whatever we want. */
5976 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5977 f
->output_data
.x
->border_tile
);
5979 x_update_cursor (f
, 1);
5982 /* The focus has changed. Update the frames as necessary to reflect
5983 the new situation. Note that we can't change the selected frame
5984 here, because the Lisp code we are interrupting might become confused.
5985 Each event gets marked with the frame in which it occurred, so the
5986 Lisp code can tell when the switch took place by examining the events. */
5989 x_new_focus_frame (dpyinfo
, frame
)
5990 struct x_display_info
*dpyinfo
;
5991 struct frame
*frame
;
5993 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5995 if (frame
!= dpyinfo
->x_focus_frame
)
5997 /* Set this before calling other routines, so that they see
5998 the correct value of x_focus_frame. */
5999 dpyinfo
->x_focus_frame
= frame
;
6001 if (old_focus
&& old_focus
->auto_lower
)
6002 x_lower_frame (old_focus
);
6005 selected_frame
= frame
;
6006 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
6008 Fselect_window (selected_frame
->selected_window
);
6009 choose_minibuf_frame ();
6012 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
6013 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
6015 pending_autoraise_frame
= 0;
6018 x_frame_rehighlight (dpyinfo
);
6021 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6024 x_mouse_leave (dpyinfo
)
6025 struct x_display_info
*dpyinfo
;
6027 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
6030 /* The focus has changed, or we have redirected a frame's focus to
6031 another frame (this happens when a frame uses a surrogate
6032 mini-buffer frame). Shift the highlight as appropriate.
6034 The FRAME argument doesn't necessarily have anything to do with which
6035 frame is being highlighted or un-highlighted; we only use it to find
6036 the appropriate X display info. */
6039 XTframe_rehighlight (frame
)
6040 struct frame
*frame
;
6042 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
6046 x_frame_rehighlight (dpyinfo
)
6047 struct x_display_info
*dpyinfo
;
6049 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
6051 if (dpyinfo
->x_focus_frame
)
6053 dpyinfo
->x_highlight_frame
6054 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
6055 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
6056 : dpyinfo
->x_focus_frame
);
6057 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
6059 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
6060 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
6064 dpyinfo
->x_highlight_frame
= 0;
6066 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
6069 frame_unhighlight (old_highlight
);
6070 if (dpyinfo
->x_highlight_frame
)
6071 frame_highlight (dpyinfo
->x_highlight_frame
);
6077 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6079 /* Initialize mode_switch_bit and modifier_meaning. */
6081 x_find_modifier_meanings (dpyinfo
)
6082 struct x_display_info
*dpyinfo
;
6084 int min_code
, max_code
;
6087 XModifierKeymap
*mods
;
6089 dpyinfo
->meta_mod_mask
= 0;
6090 dpyinfo
->shift_lock_mask
= 0;
6091 dpyinfo
->alt_mod_mask
= 0;
6092 dpyinfo
->super_mod_mask
= 0;
6093 dpyinfo
->hyper_mod_mask
= 0;
6096 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
6098 min_code
= dpyinfo
->display
->min_keycode
;
6099 max_code
= dpyinfo
->display
->max_keycode
;
6102 syms
= XGetKeyboardMapping (dpyinfo
->display
,
6103 min_code
, max_code
- min_code
+ 1,
6105 mods
= XGetModifierMapping (dpyinfo
->display
);
6107 /* Scan the modifier table to see which modifier bits the Meta and
6108 Alt keysyms are on. */
6110 int row
, col
; /* The row and column in the modifier table. */
6112 for (row
= 3; row
< 8; row
++)
6113 for (col
= 0; col
< mods
->max_keypermod
; col
++)
6116 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
6118 /* Zeroes are used for filler. Skip them. */
6122 /* Are any of this keycode's keysyms a meta key? */
6126 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
6128 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
6134 dpyinfo
->meta_mod_mask
|= (1 << row
);
6139 dpyinfo
->alt_mod_mask
|= (1 << row
);
6144 dpyinfo
->hyper_mod_mask
|= (1 << row
);
6149 dpyinfo
->super_mod_mask
|= (1 << row
);
6153 /* Ignore this if it's not on the lock modifier. */
6154 if ((1 << row
) == LockMask
)
6155 dpyinfo
->shift_lock_mask
= LockMask
;
6163 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6164 if (! dpyinfo
->meta_mod_mask
)
6166 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
6167 dpyinfo
->alt_mod_mask
= 0;
6170 /* If some keys are both alt and meta,
6171 make them just meta, not alt. */
6172 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
6174 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
6177 XFree ((char *) syms
);
6178 XFreeModifiermap (mods
);
6181 /* Convert between the modifier bits X uses and the modifier bits
6185 x_x_to_emacs_modifiers (dpyinfo
, state
)
6186 struct x_display_info
*dpyinfo
;
6189 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
6190 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
6191 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
6192 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
6193 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
6194 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
6198 x_emacs_to_x_modifiers (dpyinfo
, state
)
6199 struct x_display_info
*dpyinfo
;
6202 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
6203 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
6204 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
6205 | ((state
& shift_modifier
) ? ShiftMask
: 0)
6206 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
6207 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
6210 /* Convert a keysym to its name. */
6213 x_get_keysym_name (keysym
)
6219 value
= XKeysymToString (keysym
);
6227 /* Mouse clicks and mouse movement. Rah. */
6229 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6230 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6231 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6232 not force the value into range. */
6235 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
6237 register int pix_x
, pix_y
;
6238 register int *x
, *y
;
6242 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6243 even for negative values. */
6245 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
6247 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
6249 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
6250 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
6254 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
6255 bounds
->height
= f
->output_data
.x
->line_height
;
6256 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
6257 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
6264 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
6265 pix_x
= FRAME_WINDOW_WIDTH (f
);
6269 else if (pix_y
> f
->height
)
6278 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6279 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6280 can't tell the positions because W's display is not up to date,
6284 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
6287 int *frame_x
, *frame_y
;
6291 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
6292 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
6294 if (display_completed
)
6296 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6297 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
6298 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
6304 *frame_x
+= glyph
->pixel_width
;
6312 *frame_y
= *frame_x
= 0;
6316 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6317 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6322 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6324 If the event is a button press, then note that we have grabbed
6328 construct_mouse_click (result
, event
, f
)
6329 struct input_event
*result
;
6330 XButtonEvent
*event
;
6333 /* Make the event type no_event; we'll change that when we decide
6335 result
->kind
= mouse_click
;
6336 result
->code
= event
->button
- Button1
;
6337 result
->timestamp
= event
->time
;
6338 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6340 | (event
->type
== ButtonRelease
6344 XSETINT (result
->x
, event
->x
);
6345 XSETINT (result
->y
, event
->y
);
6346 XSETFRAME (result
->frame_or_window
, f
);
6352 /* Function to report a mouse movement to the mainstream Emacs code.
6353 The input handler calls this.
6355 We have received a mouse movement event, which is given in *event.
6356 If the mouse is over a different glyph than it was last time, tell
6357 the mainstream emacs code by setting mouse_moved. If not, ask for
6358 another motion event, so we can check again the next time it moves. */
6360 static XMotionEvent last_mouse_motion_event
;
6361 static Lisp_Object last_mouse_motion_frame
;
6364 note_mouse_movement (frame
, event
)
6366 XMotionEvent
*event
;
6368 last_mouse_movement_time
= event
->time
;
6369 last_mouse_motion_event
= *event
;
6370 XSETFRAME (last_mouse_motion_frame
, frame
);
6372 if (event
->window
!= FRAME_X_WINDOW (frame
))
6374 frame
->mouse_moved
= 1;
6375 last_mouse_scroll_bar
= Qnil
;
6376 note_mouse_highlight (frame
, -1, -1);
6379 /* Has the mouse moved off the glyph it was on at the last sighting? */
6380 else if (event
->x
< last_mouse_glyph
.x
6381 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6382 || event
->y
< last_mouse_glyph
.y
6383 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6385 frame
->mouse_moved
= 1;
6386 last_mouse_scroll_bar
= Qnil
;
6387 note_mouse_highlight (frame
, event
->x
, event
->y
);
6391 /* This is used for debugging, to turn off note_mouse_highlight. */
6393 int disable_mouse_highlight
;
6397 /************************************************************************
6399 ************************************************************************/
6401 /* Find the glyph under window-relative coordinates X/Y in window W.
6402 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6403 strings. Return in *HPOS and *VPOS the row and column number of
6404 the glyph found. Return in *AREA the glyph area containing X.
6405 Value is a pointer to the glyph found or null if X/Y is not on
6406 text, or we can't tell because W's current matrix is not up to
6409 static struct glyph
*
6410 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
6413 int *hpos
, *vpos
, *area
;
6415 struct glyph
*glyph
, *end
;
6416 struct glyph_row
*row
= NULL
;
6417 int x0
, i
, left_area_width
;
6419 /* Find row containing Y. Give up if some row is not enabled. */
6420 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6422 row
= MATRIX_ROW (w
->current_matrix
, i
);
6423 if (!row
->enabled_p
)
6425 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6432 /* Give up if Y is not in the window. */
6433 if (i
== w
->current_matrix
->nrows
)
6436 /* Get the glyph area containing X. */
6437 if (w
->pseudo_window_p
)
6444 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6445 if (x
< left_area_width
)
6447 *area
= LEFT_MARGIN_AREA
;
6450 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6453 x0
= row
->x
+ left_area_width
;
6457 *area
= RIGHT_MARGIN_AREA
;
6458 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6462 /* Find glyph containing X. */
6463 glyph
= row
->glyphs
[*area
];
6464 end
= glyph
+ row
->used
[*area
];
6467 if (x
< x0
+ glyph
->pixel_width
)
6469 if (w
->pseudo_window_p
)
6471 else if (BUFFERP (glyph
->object
))
6475 x0
+= glyph
->pixel_width
;
6482 *hpos
= glyph
- row
->glyphs
[*area
];
6487 /* Convert frame-relative x/y to coordinates relative to window W.
6488 Takes pseudo-windows into account. */
6491 frame_to_window_pixel_xy (w
, x
, y
)
6495 if (w
->pseudo_window_p
)
6497 /* A pseudo-window is always full-width, and starts at the
6498 left edge of the frame, plus a frame border. */
6499 struct frame
*f
= XFRAME (w
->frame
);
6500 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6501 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6505 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6506 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6511 /* Take proper action when mouse has moved to the mode or header line of
6512 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6513 mode line. X is relative to the start of the text display area of
6514 W, so the width of bitmap areas and scroll bars must be subtracted
6515 to get a position relative to the start of the mode line. */
6518 note_mode_line_highlight (w
, x
, mode_line_p
)
6522 struct frame
*f
= XFRAME (w
->frame
);
6523 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6524 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6525 struct glyph_row
*row
;
6528 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6530 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6534 struct glyph
*glyph
, *end
;
6535 Lisp_Object help
, map
;
6538 /* Find the glyph under X. */
6539 glyph
= row
->glyphs
[TEXT_AREA
];
6540 end
= glyph
+ row
->used
[TEXT_AREA
];
6541 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6542 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
));
6545 && x
>= x0
+ glyph
->pixel_width
)
6547 x0
+= glyph
->pixel_width
;
6552 && STRINGP (glyph
->object
)
6553 && XSTRING (glyph
->object
)->intervals
6554 && glyph
->charpos
>= 0
6555 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6557 /* If we're on a string with `help-echo' text property,
6558 arrange for the help to be displayed. This is done by
6559 setting the global variable help_echo to the help string. */
6560 help
= Fget_text_property (make_number (glyph
->charpos
),
6561 Qhelp_echo
, glyph
->object
);
6565 XSETWINDOW (help_echo_window
, w
);
6566 help_echo_object
= glyph
->object
;
6567 help_echo_pos
= glyph
->charpos
;
6570 /* Change the mouse pointer according to what is under X/Y. */
6571 map
= Fget_text_property (make_number (glyph
->charpos
),
6572 Qlocal_map
, glyph
->object
);
6574 cursor
= f
->output_data
.x
->nontext_cursor
;
6577 map
= Fget_text_property (make_number (glyph
->charpos
),
6578 Qkeymap
, glyph
->object
);
6580 cursor
= f
->output_data
.x
->nontext_cursor
;
6585 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6589 /* Take proper action when the mouse has moved to position X, Y on
6590 frame F as regards highlighting characters that have mouse-face
6591 properties. Also de-highlighting chars where the mouse was before.
6592 X and Y can be negative or out of range. */
6595 note_mouse_highlight (f
, x
, y
)
6599 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6604 /* When a menu is active, don't highlight because this looks odd. */
6605 #ifdef USE_X_TOOLKIT
6606 if (popup_activated ())
6610 if (disable_mouse_highlight
6611 || !f
->glyphs_initialized_p
)
6614 dpyinfo
->mouse_face_mouse_x
= x
;
6615 dpyinfo
->mouse_face_mouse_y
= y
;
6616 dpyinfo
->mouse_face_mouse_frame
= f
;
6618 if (dpyinfo
->mouse_face_defer
)
6623 dpyinfo
->mouse_face_deferred_gc
= 1;
6627 /* Which window is that in? */
6628 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6630 /* If we were displaying active text in another window, clear that. */
6631 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6632 clear_mouse_face (dpyinfo
);
6634 /* Not on a window -> return. */
6635 if (!WINDOWP (window
))
6638 /* Convert to window-relative pixel coordinates. */
6639 w
= XWINDOW (window
);
6640 frame_to_window_pixel_xy (w
, &x
, &y
);
6642 /* Handle tool-bar window differently since it doesn't display a
6644 if (EQ (window
, f
->tool_bar_window
))
6646 note_tool_bar_highlight (f
, x
, y
);
6650 if (portion
== 1 || portion
== 3)
6652 /* Mouse is on the mode or top line. */
6653 note_mode_line_highlight (w
, x
, portion
== 1);
6656 else if (portion
== 2)
6657 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6658 f
->output_data
.x
->horizontal_drag_cursor
);
6660 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6661 f
->output_data
.x
->text_cursor
);
6663 /* Are we in a window whose display is up to date?
6664 And verify the buffer's text has not changed. */
6665 if (/* Within text portion of the window. */
6667 && EQ (w
->window_end_valid
, w
->buffer
)
6668 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
6669 && (XFASTINT (w
->last_overlay_modified
)
6670 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
6672 int hpos
, vpos
, pos
, i
, area
;
6673 struct glyph
*glyph
;
6675 /* Find the glyph under X/Y. */
6676 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
6678 /* Clear mouse face if X/Y not over text. */
6680 || area
!= TEXT_AREA
6681 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6683 clear_mouse_face (dpyinfo
);
6687 pos
= glyph
->charpos
;
6688 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6690 /* Check for mouse-face and help-echo. */
6692 Lisp_Object mouse_face
, overlay
, position
;
6693 Lisp_Object
*overlay_vec
;
6695 struct buffer
*obuf
;
6698 /* If we get an out-of-range value, return now; avoid an error. */
6699 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6702 /* Make the window's buffer temporarily current for
6703 overlays_at and compute_char_face. */
6704 obuf
= current_buffer
;
6705 current_buffer
= XBUFFER (w
->buffer
);
6711 /* Is this char mouse-active or does it have help-echo? */
6712 XSETINT (position
, pos
);
6714 /* Put all the overlays we want in a vector in overlay_vec.
6715 Store the length in len. If there are more than 10, make
6716 enough space for all, and try again. */
6718 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6719 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
6720 if (noverlays
> len
)
6723 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6724 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
6727 /* Sort overlays into increasing priority order. */
6728 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6730 /* Check mouse-face highlighting. */
6731 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6732 && vpos
>= dpyinfo
->mouse_face_beg_row
6733 && vpos
<= dpyinfo
->mouse_face_end_row
6734 && (vpos
> dpyinfo
->mouse_face_beg_row
6735 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6736 && (vpos
< dpyinfo
->mouse_face_end_row
6737 || hpos
< dpyinfo
->mouse_face_end_col
6738 || dpyinfo
->mouse_face_past_end
)))
6740 /* Clear the display of the old active region, if any. */
6741 clear_mouse_face (dpyinfo
);
6743 /* Find the highest priority overlay that has a mouse-face prop. */
6745 for (i
= noverlays
- 1; i
>= 0; --i
)
6747 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6748 if (!NILP (mouse_face
))
6750 overlay
= overlay_vec
[i
];
6755 /* If no overlay applies, get a text property. */
6757 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6759 /* Handle the overlay case. */
6760 if (! NILP (overlay
))
6762 /* Find the range of text around this char that
6763 should be active. */
6764 Lisp_Object before
, after
;
6767 before
= Foverlay_start (overlay
);
6768 after
= Foverlay_end (overlay
);
6769 /* Record this as the current active region. */
6770 fast_find_position (w
, XFASTINT (before
),
6771 &dpyinfo
->mouse_face_beg_col
,
6772 &dpyinfo
->mouse_face_beg_row
,
6773 &dpyinfo
->mouse_face_beg_x
,
6774 &dpyinfo
->mouse_face_beg_y
);
6775 dpyinfo
->mouse_face_past_end
6776 = !fast_find_position (w
, XFASTINT (after
),
6777 &dpyinfo
->mouse_face_end_col
,
6778 &dpyinfo
->mouse_face_end_row
,
6779 &dpyinfo
->mouse_face_end_x
,
6780 &dpyinfo
->mouse_face_end_y
);
6781 dpyinfo
->mouse_face_window
= window
;
6782 dpyinfo
->mouse_face_face_id
6783 = face_at_buffer_position (w
, pos
, 0, 0,
6784 &ignore
, pos
+ 1, 1);
6786 /* Display it as active. */
6787 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6789 /* Handle the text property case. */
6790 else if (! NILP (mouse_face
))
6792 /* Find the range of text around this char that
6793 should be active. */
6794 Lisp_Object before
, after
, beginning
, end
;
6797 beginning
= Fmarker_position (w
->start
);
6798 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6799 - XFASTINT (w
->window_end_pos
)));
6801 = Fprevious_single_property_change (make_number (pos
+ 1),
6803 w
->buffer
, beginning
);
6805 = Fnext_single_property_change (position
, Qmouse_face
,
6807 /* Record this as the current active region. */
6808 fast_find_position (w
, XFASTINT (before
),
6809 &dpyinfo
->mouse_face_beg_col
,
6810 &dpyinfo
->mouse_face_beg_row
,
6811 &dpyinfo
->mouse_face_beg_x
,
6812 &dpyinfo
->mouse_face_beg_y
);
6813 dpyinfo
->mouse_face_past_end
6814 = !fast_find_position (w
, XFASTINT (after
),
6815 &dpyinfo
->mouse_face_end_col
,
6816 &dpyinfo
->mouse_face_end_row
,
6817 &dpyinfo
->mouse_face_end_x
,
6818 &dpyinfo
->mouse_face_end_y
);
6819 dpyinfo
->mouse_face_window
= window
;
6820 dpyinfo
->mouse_face_face_id
6821 = face_at_buffer_position (w
, pos
, 0, 0,
6822 &ignore
, pos
+ 1, 1);
6824 /* Display it as active. */
6825 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6829 /* Look for a `help-echo' property. */
6831 Lisp_Object help
, overlay
;
6833 /* Check overlays first. */
6834 help
= overlay
= Qnil
;
6835 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
6837 overlay
= overlay_vec
[i
];
6838 help
= Foverlay_get (overlay
, Qhelp_echo
);
6844 help_echo_window
= window
;
6845 help_echo_object
= overlay
;
6846 help_echo_pos
= pos
;
6850 /* Try text properties. */
6851 if ((STRINGP (glyph
->object
)
6852 && glyph
->charpos
>= 0
6853 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6854 || (BUFFERP (glyph
->object
)
6855 && glyph
->charpos
>= BEGV
6856 && glyph
->charpos
< ZV
))
6857 help
= Fget_text_property (make_number (glyph
->charpos
),
6858 Qhelp_echo
, glyph
->object
);
6863 help_echo_window
= window
;
6864 help_echo_object
= glyph
->object
;
6865 help_echo_pos
= glyph
->charpos
;
6872 current_buffer
= obuf
;
6878 redo_mouse_highlight ()
6880 if (!NILP (last_mouse_motion_frame
)
6881 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6882 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6883 last_mouse_motion_event
.x
,
6884 last_mouse_motion_event
.y
);
6889 /***********************************************************************
6891 ***********************************************************************/
6893 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
6894 struct glyph
**, int *, int *, int *));
6896 /* Tool-bar item index of the item on which a mouse button was pressed
6899 static int last_tool_bar_item
;
6902 /* Get information about the tool-bar item at position X/Y on frame F.
6903 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6904 the current matrix of the tool-bar window of F, or NULL if not
6905 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6906 item in F->tool_bar_items. Value is
6908 -1 if X/Y is not on a tool-bar item
6909 0 if X/Y is on the same item that was highlighted before.
6913 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6916 struct glyph
**glyph
;
6917 int *hpos
, *vpos
, *prop_idx
;
6919 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6920 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6923 /* Find the glyph under X/Y. */
6924 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6928 /* Get the start of this tool-bar item's properties in
6929 f->tool_bar_items. */
6930 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
6933 /* Is mouse on the highlighted item? */
6934 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
6935 && *vpos
>= dpyinfo
->mouse_face_beg_row
6936 && *vpos
<= dpyinfo
->mouse_face_end_row
6937 && (*vpos
> dpyinfo
->mouse_face_beg_row
6938 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6939 && (*vpos
< dpyinfo
->mouse_face_end_row
6940 || *hpos
< dpyinfo
->mouse_face_end_col
6941 || dpyinfo
->mouse_face_past_end
))
6948 /* Handle mouse button event on the tool-bar of frame F, at
6949 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6953 x_handle_tool_bar_click (f
, button_event
)
6955 XButtonEvent
*button_event
;
6957 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6958 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6959 int hpos
, vpos
, prop_idx
;
6960 struct glyph
*glyph
;
6961 Lisp_Object enabled_p
;
6962 int x
= button_event
->x
;
6963 int y
= button_event
->y
;
6965 /* If not on the highlighted tool-bar item, return. */
6966 frame_to_window_pixel_xy (w
, &x
, &y
);
6967 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6970 /* If item is disabled, do nothing. */
6971 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
6972 if (NILP (enabled_p
))
6975 if (button_event
->type
== ButtonPress
)
6977 /* Show item in pressed state. */
6978 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6979 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6980 last_tool_bar_item
= prop_idx
;
6984 Lisp_Object key
, frame
;
6985 struct input_event event
;
6987 /* Show item in released state. */
6988 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6989 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6991 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
6993 XSETFRAME (frame
, f
);
6994 event
.kind
= TOOL_BAR_EVENT
;
6995 event
.frame_or_window
= frame
;
6997 kbd_buffer_store_event (&event
);
6999 event
.kind
= TOOL_BAR_EVENT
;
7000 event
.frame_or_window
= frame
;
7002 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
7003 button_event
->state
);
7004 kbd_buffer_store_event (&event
);
7005 last_tool_bar_item
= -1;
7010 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7011 tool-bar window-relative coordinates X/Y. Called from
7012 note_mouse_highlight. */
7015 note_tool_bar_highlight (f
, x
, y
)
7019 Lisp_Object window
= f
->tool_bar_window
;
7020 struct window
*w
= XWINDOW (window
);
7021 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7023 struct glyph
*glyph
;
7024 struct glyph_row
*row
;
7026 Lisp_Object enabled_p
;
7028 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
7029 int mouse_down_p
, rc
;
7031 /* Function note_mouse_highlight is called with negative x(y
7032 values when mouse moves outside of the frame. */
7033 if (x
<= 0 || y
<= 0)
7035 clear_mouse_face (dpyinfo
);
7039 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
7042 /* Not on tool-bar item. */
7043 clear_mouse_face (dpyinfo
);
7047 /* On same tool-bar item as before. */
7050 clear_mouse_face (dpyinfo
);
7052 /* Mouse is down, but on different tool-bar item? */
7053 mouse_down_p
= (dpyinfo
->grabbed
7054 && f
== last_mouse_frame
7055 && FRAME_LIVE_P (f
));
7057 && last_tool_bar_item
!= prop_idx
)
7060 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
7061 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
7063 /* If tool-bar item is not enabled, don't highlight it. */
7064 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
7065 if (!NILP (enabled_p
))
7067 /* Compute the x-position of the glyph. In front and past the
7068 image is a space. We include this is the highlighted area. */
7069 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
7070 for (i
= x
= 0; i
< hpos
; ++i
)
7071 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
7073 /* Record this as the current active region. */
7074 dpyinfo
->mouse_face_beg_col
= hpos
;
7075 dpyinfo
->mouse_face_beg_row
= vpos
;
7076 dpyinfo
->mouse_face_beg_x
= x
;
7077 dpyinfo
->mouse_face_beg_y
= row
->y
;
7078 dpyinfo
->mouse_face_past_end
= 0;
7080 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
7081 dpyinfo
->mouse_face_end_row
= vpos
;
7082 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
7083 dpyinfo
->mouse_face_end_y
= row
->y
;
7084 dpyinfo
->mouse_face_window
= window
;
7085 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
7087 /* Display it as active. */
7088 show_mouse_face (dpyinfo
, draw
);
7089 dpyinfo
->mouse_face_image_state
= draw
;
7094 /* Set help_echo to a help string.to display for this tool-bar item.
7095 XTread_socket does the rest. */
7096 help_echo_object
= help_echo_window
= Qnil
;
7098 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
7099 if (NILP (help_echo
))
7100 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
7105 /* Find the glyph matrix position of buffer position POS in window W.
7106 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7107 current glyphs must be up to date. If POS is above window start
7108 return (0, 0, 0, 0). If POS is after end of W, return end of
7112 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
7115 int *hpos
, *vpos
, *x
, *y
;
7119 int maybe_next_line_p
= 0;
7120 int line_start_position
;
7121 int yb
= window_text_bottom_y (w
);
7122 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
7123 struct glyph_row
*best_row
= row
;
7124 int row_vpos
= 0, best_row_vpos
= 0;
7129 if (row
->used
[TEXT_AREA
])
7130 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
7132 line_start_position
= 0;
7134 if (line_start_position
> pos
)
7136 /* If the position sought is the end of the buffer,
7137 don't include the blank lines at the bottom of the window. */
7138 else if (line_start_position
== pos
7139 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
7141 maybe_next_line_p
= 1;
7144 else if (line_start_position
> 0)
7147 best_row_vpos
= row_vpos
;
7150 if (row
->y
+ row
->height
>= yb
)
7157 /* Find the right column within BEST_ROW. */
7159 current_x
= best_row
->x
;
7160 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
7162 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
7165 charpos
= glyph
->charpos
;
7169 *vpos
= best_row_vpos
;
7174 else if (charpos
> pos
)
7176 else if (charpos
> 0)
7179 current_x
+= glyph
->pixel_width
;
7182 /* If we're looking for the end of the buffer,
7183 and we didn't find it in the line we scanned,
7184 use the start of the following line. */
7185 if (maybe_next_line_p
)
7190 current_x
= best_row
->x
;
7193 *vpos
= best_row_vpos
;
7194 *hpos
= lastcol
+ 1;
7201 /* Display the active region described by mouse_face_*
7202 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7205 show_mouse_face (dpyinfo
, draw
)
7206 struct x_display_info
*dpyinfo
;
7207 enum draw_glyphs_face draw
;
7209 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
7210 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7212 int cursor_off_p
= 0;
7213 struct cursor_pos saved_cursor
;
7215 saved_cursor
= output_cursor
;
7217 /* If window is in the process of being destroyed, don't bother
7219 if (w
->current_matrix
== NULL
)
7222 /* Recognize when we are called to operate on rows that don't exist
7223 anymore. This can happen when a window is split. */
7224 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
7227 set_output_cursor (&w
->phys_cursor
);
7229 /* Note that mouse_face_beg_row etc. are window relative. */
7230 for (i
= dpyinfo
->mouse_face_beg_row
;
7231 i
<= dpyinfo
->mouse_face_end_row
;
7234 int start_hpos
, end_hpos
, start_x
;
7235 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
7237 /* Don't do anything if row doesn't have valid contents. */
7238 if (!row
->enabled_p
)
7241 /* For all but the first row, the highlight starts at column 0. */
7242 if (i
== dpyinfo
->mouse_face_beg_row
)
7244 start_hpos
= dpyinfo
->mouse_face_beg_col
;
7245 start_x
= dpyinfo
->mouse_face_beg_x
;
7253 if (i
== dpyinfo
->mouse_face_end_row
)
7254 end_hpos
= dpyinfo
->mouse_face_end_col
;
7256 end_hpos
= row
->used
[TEXT_AREA
];
7258 /* If the cursor's in the text we are about to rewrite, turn the
7260 if (!w
->pseudo_window_p
7261 && i
== output_cursor
.vpos
7262 && output_cursor
.hpos
>= start_hpos
- 1
7263 && output_cursor
.hpos
<= end_hpos
)
7265 x_update_window_cursor (w
, 0);
7269 if (end_hpos
> start_hpos
)
7271 row
->mouse_face_p
= draw
== DRAW_MOUSE_FACE
;
7272 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
7273 start_hpos
, end_hpos
, draw
, NULL
, NULL
, 0);
7277 /* If we turned the cursor off, turn it back on. */
7279 x_display_cursor (w
, 1,
7280 output_cursor
.hpos
, output_cursor
.vpos
,
7281 output_cursor
.x
, output_cursor
.y
);
7283 output_cursor
= saved_cursor
;
7287 /* Change the mouse cursor. */
7288 if (draw
== DRAW_NORMAL_TEXT
)
7289 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7290 f
->output_data
.x
->text_cursor
);
7291 else if (draw
== DRAW_MOUSE_FACE
)
7292 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7293 f
->output_data
.x
->cross_cursor
);
7295 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7296 f
->output_data
.x
->nontext_cursor
);
7299 /* Clear out the mouse-highlighted active region.
7300 Redraw it un-highlighted first. */
7303 clear_mouse_face (dpyinfo
)
7304 struct x_display_info
*dpyinfo
;
7309 if (! NILP (dpyinfo
->mouse_face_window
))
7310 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
7312 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7313 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7314 dpyinfo
->mouse_face_window
= Qnil
;
7318 /* Clear any mouse-face on window W. This function is part of the
7319 redisplay interface, and is called from try_window_id and similar
7320 functions to ensure the mouse-highlight is off. */
7323 x_clear_mouse_face (w
)
7326 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
7330 XSETWINDOW (window
, w
);
7331 if (EQ (window
, dpyinfo
->mouse_face_window
))
7332 clear_mouse_face (dpyinfo
);
7337 /* Just discard the mouse face information for frame F, if any.
7338 This is used when the size of F is changed. */
7341 cancel_mouse_face (f
)
7345 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7347 window
= dpyinfo
->mouse_face_window
;
7348 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
7350 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7351 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7352 dpyinfo
->mouse_face_window
= Qnil
;
7356 static struct scroll_bar
*x_window_to_scroll_bar ();
7357 static void x_scroll_bar_report_motion ();
7359 /* Return the current position of the mouse.
7360 *fp should be a frame which indicates which display to ask about.
7362 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7363 and *part to the frame, window, and scroll bar part that the mouse
7364 is over. Set *x and *y to the portion and whole of the mouse's
7365 position on the scroll bar.
7367 If the mouse movement started elsewhere, set *fp to the frame the
7368 mouse is on, *bar_window to nil, and *x and *y to the character cell
7371 Set *time to the server time-stamp for the time at which the mouse
7372 was at this position.
7374 Don't store anything if we don't have a valid set of values to report.
7376 This clears the mouse_moved flag, so we can wait for the next mouse
7380 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
7383 Lisp_Object
*bar_window
;
7384 enum scroll_bar_part
*part
;
7386 unsigned long *time
;
7392 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
7393 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
7399 Window dummy_window
;
7402 Lisp_Object frame
, tail
;
7404 /* Clear the mouse-moved flag for every frame on this display. */
7405 FOR_EACH_FRAME (tail
, frame
)
7406 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
7407 XFRAME (frame
)->mouse_moved
= 0;
7409 last_mouse_scroll_bar
= Qnil
;
7411 /* Figure out which root window we're on. */
7412 XQueryPointer (FRAME_X_DISPLAY (*fp
),
7413 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
7415 /* The root window which contains the pointer. */
7418 /* Trash which we can't trust if the pointer is on
7419 a different screen. */
7422 /* The position on that root window. */
7425 /* More trash we can't trust. */
7428 /* Modifier keys and pointer buttons, about which
7430 (unsigned int *) &dummy
);
7432 /* Now we have a position on the root; find the innermost window
7433 containing the pointer. */
7437 int parent_x
= 0, parent_y
= 0;
7442 /* XTranslateCoordinates can get errors if the window
7443 structure is changing at the same time this function
7444 is running. So at least we must not crash from them. */
7446 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
7448 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
7449 && FRAME_LIVE_P (last_mouse_frame
))
7451 /* If mouse was grabbed on a frame, give coords for that frame
7452 even if the mouse is now outside it. */
7453 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7455 /* From-window, to-window. */
7456 root
, FRAME_X_WINDOW (last_mouse_frame
),
7458 /* From-position, to-position. */
7459 root_x
, root_y
, &win_x
, &win_y
,
7463 f1
= last_mouse_frame
;
7469 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7471 /* From-window, to-window. */
7474 /* From-position, to-position. */
7475 root_x
, root_y
, &win_x
, &win_y
,
7480 if (child
== None
|| child
== win
)
7488 /* Now we know that:
7489 win is the innermost window containing the pointer
7490 (XTC says it has no child containing the pointer),
7491 win_x and win_y are the pointer's position in it
7492 (XTC did this the last time through), and
7493 parent_x and parent_y are the pointer's position in win's parent.
7494 (They are what win_x and win_y were when win was child.
7495 If win is the root window, it has no parent, and
7496 parent_{x,y} are invalid, but that's okay, because we'll
7497 never use them in that case.) */
7499 /* Is win one of our frames? */
7500 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
7502 #ifdef USE_X_TOOLKIT
7503 /* If we end up with the menu bar window, say it's not
7506 && f1
->output_data
.x
->menubar_widget
7507 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
7509 #endif /* USE_X_TOOLKIT */
7512 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
7515 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
7517 /* If not, is it one of our scroll bars? */
7520 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
7524 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7530 if (f1
== 0 && insist
> 0)
7531 f1
= SELECTED_FRAME ();
7535 /* Ok, we found a frame. Store all the values.
7536 last_mouse_glyph is a rectangle used to reduce the
7537 generation of mouse events. To not miss any motion
7538 events, we must divide the frame into rectangles of the
7539 size of the smallest character that could be displayed
7540 on it, i.e. into the same rectangles that matrices on
7541 the frame are divided into. */
7543 #if OLD_REDISPLAY_CODE
7544 int ignore1
, ignore2
;
7545 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
7547 FRAME_X_DISPLAY_INFO (f1
)->grabbed
7551 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
7552 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
7556 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7557 round down even for negative values. */
7563 last_mouse_glyph
.width
= width
;
7564 last_mouse_glyph
.height
= height
;
7565 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
7566 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
7573 XSETINT (*x
, win_x
);
7574 XSETINT (*y
, win_y
);
7575 *time
= last_mouse_movement_time
;
7584 #ifdef USE_X_TOOLKIT
7586 /* Atimer callback function for TIMER. Called every 0.1s to process
7587 Xt timeouts, if needed. We must avoid calling XtAppPending as
7588 much as possible because that function does an implicit XFlush
7589 that slows us down. */
7592 x_process_timeouts (timer
)
7593 struct atimer
*timer
;
7595 if (toolkit_scroll_bar_interaction
|| popup_activated_flag
)
7598 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
7599 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
7604 #endif /* USE_X_TOOLKIT */
7607 /* Scroll bar support. */
7609 /* Given an X window ID, find the struct scroll_bar which manages it.
7610 This can be called in GC, so we have to make sure to strip off mark
7613 static struct scroll_bar
*
7614 x_window_to_scroll_bar (window_id
)
7619 for (tail
= Vframe_list
;
7620 XGCTYPE (tail
) == Lisp_Cons
;
7623 Lisp_Object frame
, bar
, condemned
;
7625 frame
= XCAR (tail
);
7626 /* All elements of Vframe_list should be frames. */
7627 if (! GC_FRAMEP (frame
))
7630 /* Scan this frame's scroll bar list for a scroll bar with the
7632 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
7633 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
7634 /* This trick allows us to search both the ordinary and
7635 condemned scroll bar lists with one loop. */
7636 ! GC_NILP (bar
) || (bar
= condemned
,
7639 bar
= XSCROLL_BAR (bar
)->next
)
7640 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
7641 return XSCROLL_BAR (bar
);
7649 /************************************************************************
7651 ************************************************************************/
7653 #if USE_TOOLKIT_SCROLL_BARS
7655 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
7656 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
7657 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
7658 struct scroll_bar
*));
7659 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
7663 /* Id of action hook installed for scroll bars. */
7665 static XtActionHookId action_hook_id
;
7667 /* Lisp window being scrolled. Set when starting to interact with
7668 a toolkit scroll bar, reset to nil when ending the interaction. */
7670 static Lisp_Object window_being_scrolled
;
7672 /* Last scroll bar part sent in xm_scroll_callback. */
7674 static int last_scroll_bar_part
;
7676 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7677 that movements of 1/20 of the screen size are mapped to up/down. */
7679 static Boolean xaw3d_arrow_scroll
;
7681 /* Whether the drag scrolling maintains the mouse at the top of the
7682 thumb. If not, resizing the thumb needs to be done more carefully
7683 to avoid jerkyness. */
7685 static Boolean xaw3d_pick_top
;
7688 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7689 bars are used.. The hook is responsible for detecting when
7690 the user ends an interaction with the scroll bar, and generates
7691 a `end-scroll' scroll_bar_click' event if so. */
7694 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
7697 XtPointer client_data
;
7701 Cardinal
*num_params
;
7707 scroll_bar_p
= XmIsScrollBar (widget
);
7708 end_action
= "Release";
7709 #else /* !USE_MOTIF i.e. use Xaw */
7710 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
7711 end_action
= "EndScroll";
7712 #endif /* USE_MOTIF */
7715 && strcmp (action_name
, end_action
) == 0
7716 && WINDOWP (window_being_scrolled
))
7720 x_send_scroll_bar_event (window_being_scrolled
,
7721 scroll_bar_end_scroll
, 0, 0);
7722 w
= XWINDOW (window_being_scrolled
);
7723 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
7724 window_being_scrolled
= Qnil
;
7725 last_scroll_bar_part
= -1;
7727 /* Xt timeouts no longer needed. */
7728 toolkit_scroll_bar_interaction
= 0;
7732 /* A vector of windows used for communication between
7733 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
7735 static struct window
**scroll_bar_windows
;
7736 static int scroll_bar_windows_size
;
7739 /* Send a client message with message type Xatom_Scrollbar for a
7740 scroll action to the frame of WINDOW. PART is a value identifying
7741 the part of the scroll bar that was clicked on. PORTION is the
7742 amount to scroll of a whole of WHOLE. */
7745 x_send_scroll_bar_event (window
, part
, portion
, whole
)
7747 int part
, portion
, whole
;
7750 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
7751 struct window
*w
= XWINDOW (window
);
7752 struct frame
*f
= XFRAME (w
->frame
);
7757 /* Construct a ClientMessage event to send to the frame. */
7758 ev
->type
= ClientMessage
;
7759 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
7760 ev
->display
= FRAME_X_DISPLAY (f
);
7761 ev
->window
= FRAME_X_WINDOW (f
);
7764 /* We can only transfer 32 bits in the XClientMessageEvent, which is
7765 not enough to store a pointer or Lisp_Object on a 64 bit system.
7766 So, store the window in scroll_bar_windows and pass the index
7767 into that array in the event. */
7768 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
7769 if (scroll_bar_windows
[i
] == NULL
)
7772 if (i
== scroll_bar_windows_size
)
7774 int new_size
= max (10, 2 * scroll_bar_windows_size
);
7775 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
7776 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
7778 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
7780 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
7781 scroll_bar_windows_size
= new_size
;
7784 scroll_bar_windows
[i
] = w
;
7785 ev
->data
.l
[0] = (long) i
;
7786 ev
->data
.l
[1] = (long) part
;
7787 ev
->data
.l
[2] = (long) 0;
7788 ev
->data
.l
[3] = (long) portion
;
7789 ev
->data
.l
[4] = (long) whole
;
7791 /* Make Xt timeouts work while the scroll bar is active. */
7792 toolkit_scroll_bar_interaction
= 1;
7794 /* Setting the event mask to zero means that the message will
7795 be sent to the client that created the window, and if that
7796 window no longer exists, no event will be sent. */
7797 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7802 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7806 x_scroll_bar_to_input_event (event
, ievent
)
7808 struct input_event
*ievent
;
7810 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7815 w
= scroll_bar_windows
[ev
->data
.l
[0]];
7816 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
7818 XSETWINDOW (window
, w
);
7819 f
= XFRAME (w
->frame
);
7821 ievent
->kind
= scroll_bar_click
;
7822 ievent
->frame_or_window
= window
;
7824 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7825 ievent
->part
= ev
->data
.l
[1];
7826 ievent
->code
= ev
->data
.l
[2];
7827 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7828 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7829 ievent
->modifiers
= 0;
7835 /* Minimum and maximum values used for Motif scroll bars. */
7838 #define XM_SB_MAX 10000000
7839 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7842 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7843 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7844 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7847 xm_scroll_callback (widget
, client_data
, call_data
)
7849 XtPointer client_data
, call_data
;
7851 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7852 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7854 int part
= -1, whole
= 0, portion
= 0;
7858 case XmCR_DECREMENT
:
7859 bar
->dragging
= Qnil
;
7860 part
= scroll_bar_up_arrow
;
7863 case XmCR_INCREMENT
:
7864 bar
->dragging
= Qnil
;
7865 part
= scroll_bar_down_arrow
;
7868 case XmCR_PAGE_DECREMENT
:
7869 bar
->dragging
= Qnil
;
7870 part
= scroll_bar_above_handle
;
7873 case XmCR_PAGE_INCREMENT
:
7874 bar
->dragging
= Qnil
;
7875 part
= scroll_bar_below_handle
;
7879 bar
->dragging
= Qnil
;
7880 part
= scroll_bar_to_top
;
7883 case XmCR_TO_BOTTOM
:
7884 bar
->dragging
= Qnil
;
7885 part
= scroll_bar_to_bottom
;
7891 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7892 && XINT (bar
->dragging
) <= cs
->value
);
7894 /* Get the slider size. */
7896 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7899 /* At the max position of the scroll bar, do a line-wise
7900 movement. Without doing anything, the LessTif scroll bar
7901 calls us with the same cs->value again and again. If we
7902 want to make sure that we can reach the end of the buffer,
7903 we have to do something.
7905 Implementation note: setting bar->dragging always to
7906 cs->value gives a smoother movement at the max position.
7907 Setting it to nil when doing line-wise movement gives
7908 a better slider behavior. */
7910 if (cs
->value
+ slider_size
== XM_SB_MAX
7912 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7914 part
= scroll_bar_down_arrow
;
7915 bar
->dragging
= Qnil
;
7919 whole
= XM_SB_RANGE
;
7920 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7921 part
= scroll_bar_handle
;
7922 bar
->dragging
= make_number (cs
->value
);
7927 case XmCR_VALUE_CHANGED
:
7933 window_being_scrolled
= bar
->window
;
7934 last_scroll_bar_part
= part
;
7935 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7940 #else /* !USE_MOTIF, i.e. Xaw. */
7943 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7944 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7945 scroll bar struct. CALL_DATA is a pointer to a float saying where
7949 xaw_jump_callback (widget
, client_data
, call_data
)
7951 XtPointer client_data
, call_data
;
7953 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7954 float top
= *(float *) call_data
;
7956 int whole
, portion
, height
;
7959 /* Get the size of the thumb, a value between 0 and 1. */
7961 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
7965 portion
= shown
< 1 ? top
* whole
: 0;
7967 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
7968 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7969 the bottom, so we force the scrolling whenever we see that we're
7970 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7971 we try to ensure that we always stay two pixels away from the
7973 part
= scroll_bar_down_arrow
;
7975 part
= scroll_bar_handle
;
7977 window_being_scrolled
= bar
->window
;
7978 bar
->dragging
= make_number (portion
);
7979 last_scroll_bar_part
= part
;
7980 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7984 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7985 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7986 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7987 the scroll bar. CALL_DATA is an integer specifying the action that
7988 has taken place. It's magnitude is in the range 0..height of the
7989 scroll bar. Negative values mean scroll towards buffer start.
7990 Values < height of scroll bar mean line-wise movement. */
7993 xaw_scroll_callback (widget
, client_data
, call_data
)
7995 XtPointer client_data
, call_data
;
7997 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7998 int position
= (int) call_data
;
8002 /* Get the height of the scroll bar. */
8004 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
8007 if (abs (position
) >= height
)
8008 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
8010 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8011 it maps line-movement to call_data = max(5, height/20). */
8012 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
8013 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
8015 part
= scroll_bar_move_ratio
;
8017 window_being_scrolled
= bar
->window
;
8018 bar
->dragging
= Qnil
;
8019 last_scroll_bar_part
= part
;
8020 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
8024 #endif /* not USE_MOTIF */
8027 /* Create the widget for scroll bar BAR on frame F. Record the widget
8028 and X window of the scroll bar in BAR. */
8031 x_create_toolkit_scroll_bar (f
, bar
)
8033 struct scroll_bar
*bar
;
8039 char *scroll_bar_name
= "verticalScrollBar";
8040 unsigned long pixel
;
8045 /* LessTif 0.85, problems:
8047 1. When the mouse if over the scroll bar, the scroll bar will
8048 get keyboard events. I didn't find a way to turn this off.
8050 2. Do we have to explicitly set the cursor to get an arrow
8051 cursor (see below)? */
8053 /* Set resources. Create the widget. */
8054 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8055 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
8056 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
8057 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
8058 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
8059 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
8060 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
8062 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8065 XtSetArg (av
[ac
], XmNforeground
, pixel
);
8069 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8072 XtSetArg (av
[ac
], XmNbackground
, pixel
);
8076 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
8077 scroll_bar_name
, av
, ac
);
8079 /* Add one callback for everything that can happen. */
8080 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
8082 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
8084 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
8086 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
8088 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
8090 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
8092 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
8095 /* Realize the widget. Only after that is the X window created. */
8096 XtRealizeWidget (widget
);
8098 /* Set the cursor to an arrow. I didn't find a resource to do that.
8099 And I'm wondering why it hasn't an arrow cursor by default. */
8100 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
8101 f
->output_data
.x
->nontext_cursor
);
8103 #else /* !USE_MOTIF i.e. use Xaw */
8105 /* Set resources. Create the widget. The background of the
8106 Xaw3d scroll bar widget is a little bit light for my taste.
8107 We don't alter it here to let users change it according
8108 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8109 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
8110 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
8111 /* For smoother scrolling with Xaw3d -sm */
8112 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8113 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8115 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
8118 XtSetArg (av
[ac
], XtNforeground
, pixel
);
8122 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8125 XtSetArg (av
[ac
], XtNbackground
, pixel
);
8129 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
8130 f
->output_data
.x
->edit_widget
, av
, ac
);
8134 char *val
= initial
;
8135 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
8136 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
8138 { /* ARROW_SCROLL */
8139 xaw3d_arrow_scroll
= True
;
8140 /* Isn't that just a personal preference ? -sm */
8141 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
8145 /* Define callbacks. */
8146 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
8147 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
8150 /* Realize the widget. Only after that is the X window created. */
8151 XtRealizeWidget (widget
);
8153 #endif /* !USE_MOTIF */
8155 /* Install an action hook that let's us detect when the user
8156 finishes interacting with a scroll bar. */
8157 if (action_hook_id
== 0)
8158 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
8160 /* Remember X window and widget in the scroll bar vector. */
8161 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
8162 xwindow
= XtWindow (widget
);
8163 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
8169 /* Set the thumb size and position of scroll bar BAR. We are currently
8170 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8173 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
8174 struct scroll_bar
*bar
;
8175 int portion
, position
, whole
;
8177 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8178 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
8185 top
= (float) position
/ whole
;
8186 shown
= (float) portion
/ whole
;
8194 Boolean arrow1_selected
, arrow2_selected
;
8195 unsigned char flags
;
8196 XmScrollBarWidget sb
;
8198 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8199 is the scroll bar's maximum and MIN is the scroll bar's minimum
8201 size
= shown
* XM_SB_RANGE
;
8202 size
= min (size
, XM_SB_RANGE
);
8203 size
= max (size
, 1);
8205 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8206 value
= top
* XM_SB_RANGE
;
8207 value
= min (value
, XM_SB_MAX
- size
);
8208 value
= max (value
, XM_SB_MIN
);
8210 /* LessTif: Calling XmScrollBarSetValues after an increment or
8211 decrement turns off auto-repeat LessTif-internally. This can
8212 be seen in ScrollBar.c which resets Arrow1Selected and
8213 Arrow2Selected. It also sets internal flags so that LessTif
8214 believes the mouse is in the slider. We either have to change
8215 our code, or work around that by accessing private data. */
8217 sb
= (XmScrollBarWidget
) widget
;
8218 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
8219 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
8220 flags
= sb
->scrollBar
.flags
;
8222 if (NILP (bar
->dragging
))
8223 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
8224 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
8225 /* This has the negative side effect that the slider value is
8226 not what it would be if we scrolled here using line-wise or
8227 page-wise movement. */
8228 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
8231 /* If currently dragging, only update the slider size.
8232 This reduces flicker effects. */
8233 int old_value
, old_size
, increment
, page_increment
;
8235 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
8236 &increment
, &page_increment
);
8237 XmScrollBarSetValues (widget
, old_value
,
8238 min (size
, XM_SB_RANGE
- old_value
),
8242 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
8243 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
8244 sb
->scrollBar
.flags
= flags
;
8246 #else /* !USE_MOTIF i.e. use Xaw */
8248 float old_top
, old_shown
;
8250 XtVaGetValues (widget
,
8251 XtNtopOfThumb
, &old_top
,
8252 XtNshown
, &old_shown
,
8256 /* Massage the top+shown values. */
8257 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
8258 top
= max (0, min (1, top
));
8261 /* Keep two pixels available for moving the thumb down. */
8262 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
8264 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8265 check that your system's configuration file contains a define
8266 for `NARROWPROTO'. See s/freebsd.h for an example. */
8267 if (top
!= old_top
|| shown
!= old_shown
)
8269 if (NILP (bar
->dragging
))
8270 XawScrollbarSetThumb (widget
, top
, shown
);
8274 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
8275 int scroll_mode
= 0;
8277 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8278 if (xaw3d_arrow_scroll
)
8280 /* Xaw3d stupidly ignores resize requests while dragging
8281 so we have to make it believe it's not in dragging mode. */
8282 scroll_mode
= sb
->scrollbar
.scroll_mode
;
8283 if (scroll_mode
== 2)
8284 sb
->scrollbar
.scroll_mode
= 0;
8287 /* Try to make the scrolling a tad smoother. */
8288 if (!xaw3d_pick_top
)
8289 shown
= min (shown
, old_shown
);
8291 XawScrollbarSetThumb (widget
, top
, shown
);
8294 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
8295 sb
->scrollbar
.scroll_mode
= scroll_mode
;
8300 #endif /* !USE_MOTIF */
8305 #endif /* USE_TOOLKIT_SCROLL_BARS */
8309 /************************************************************************
8310 Scroll bars, general
8311 ************************************************************************/
8313 /* Create a scroll bar and return the scroll bar vector for it. W is
8314 the Emacs window on which to create the scroll bar. TOP, LEFT,
8315 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8318 static struct scroll_bar
*
8319 x_scroll_bar_create (w
, top
, left
, width
, height
)
8321 int top
, left
, width
, height
;
8323 struct frame
*f
= XFRAME (w
->frame
);
8324 struct scroll_bar
*bar
8325 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
8329 #if USE_TOOLKIT_SCROLL_BARS
8330 x_create_toolkit_scroll_bar (f
, bar
);
8331 #else /* not USE_TOOLKIT_SCROLL_BARS */
8333 XSetWindowAttributes a
;
8337 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
8338 if (a
.background_pixel
== -1)
8339 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
8341 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
8342 | ButtonMotionMask
| PointerMotionHintMask
8344 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
8346 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
8348 /* Clear the area of W that will serve as a scroll bar. This is
8349 for the case that a window has been split horizontally. In
8350 this case, no clear_frame is generated to reduce flickering. */
8351 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8353 window_box_height (w
), False
);
8355 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8356 /* Position and size of scroll bar. */
8357 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8359 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8361 /* Border width, depth, class, and visual. */
8368 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
8370 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8372 XSETWINDOW (bar
->window
, w
);
8373 XSETINT (bar
->top
, top
);
8374 XSETINT (bar
->left
, left
);
8375 XSETINT (bar
->width
, width
);
8376 XSETINT (bar
->height
, height
);
8377 XSETINT (bar
->start
, 0);
8378 XSETINT (bar
->end
, 0);
8379 bar
->dragging
= Qnil
;
8381 /* Add bar to its frame's list of scroll bars. */
8382 bar
->next
= FRAME_SCROLL_BARS (f
);
8384 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8385 if (!NILP (bar
->next
))
8386 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8388 /* Map the window/widget. */
8389 #if USE_TOOLKIT_SCROLL_BARS
8391 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
8392 XtConfigureWidget (scroll_bar
,
8393 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8395 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8397 XtMapWidget (scroll_bar
);
8399 #else /* not USE_TOOLKIT_SCROLL_BARS */
8400 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8401 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8408 /* Draw BAR's handle in the proper position.
8410 If the handle is already drawn from START to END, don't bother
8411 redrawing it, unless REBUILD is non-zero; in that case, always
8412 redraw it. (REBUILD is handy for drawing the handle after expose
8415 Normally, we want to constrain the start and end of the handle to
8416 fit inside its rectangle, but if the user is dragging the scroll
8417 bar handle, we want to let them drag it down all the way, so that
8418 the bar's top is as far down as it goes; otherwise, there's no way
8419 to move to the very end of the buffer. */
8421 #ifndef USE_TOOLKIT_SCROLL_BARS
8424 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
8425 struct scroll_bar
*bar
;
8429 int dragging
= ! NILP (bar
->dragging
);
8430 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8431 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8432 GC gc
= f
->output_data
.x
->normal_gc
;
8434 /* If the display is already accurate, do nothing. */
8436 && start
== XINT (bar
->start
)
8437 && end
== XINT (bar
->end
))
8443 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
8444 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8445 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8447 /* Make sure the values are reasonable, and try to preserve
8448 the distance between start and end. */
8450 int length
= end
- start
;
8454 else if (start
> top_range
)
8456 end
= start
+ length
;
8460 else if (end
> top_range
&& ! dragging
)
8464 /* Store the adjusted setting in the scroll bar. */
8465 XSETINT (bar
->start
, start
);
8466 XSETINT (bar
->end
, end
);
8468 /* Clip the end position, just for display. */
8469 if (end
> top_range
)
8472 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8473 below top positions, to make sure the handle is always at least
8474 that many pixels tall. */
8475 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8477 /* Draw the empty space above the handle. Note that we can't clear
8478 zero-height areas; that means "clear to end of window." */
8480 XClearArea (FRAME_X_DISPLAY (f
), w
,
8482 /* x, y, width, height, and exposures. */
8483 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8484 VERTICAL_SCROLL_BAR_TOP_BORDER
,
8485 inside_width
, start
,
8488 /* Change to proper foreground color if one is specified. */
8489 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8490 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8491 f
->output_data
.x
->scroll_bar_foreground_pixel
);
8493 /* Draw the handle itself. */
8494 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8496 /* x, y, width, height */
8497 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8498 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
8499 inside_width
, end
- start
);
8501 /* Restore the foreground color of the GC if we changed it above. */
8502 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8503 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8504 f
->output_data
.x
->foreground_pixel
);
8506 /* Draw the empty space below the handle. Note that we can't
8507 clear zero-height areas; that means "clear to end of window." */
8508 if (end
< inside_height
)
8509 XClearArea (FRAME_X_DISPLAY (f
), w
,
8511 /* x, y, width, height, and exposures. */
8512 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8513 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
8514 inside_width
, inside_height
- end
,
8522 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8524 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8528 x_scroll_bar_remove (bar
)
8529 struct scroll_bar
*bar
;
8531 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8534 #if USE_TOOLKIT_SCROLL_BARS
8535 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
8537 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8540 /* Disassociate this scroll bar from its window. */
8541 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8547 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8548 that we are displaying PORTION characters out of a total of WHOLE
8549 characters, starting at POSITION. If WINDOW has no scroll bar,
8553 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8555 int portion
, whole
, position
;
8557 struct frame
*f
= XFRAME (w
->frame
);
8558 struct scroll_bar
*bar
;
8559 int top
, height
, left
, sb_left
, width
, sb_width
;
8560 int window_x
, window_y
, window_width
, window_height
;
8562 /* Get window dimensions. */
8563 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8565 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8566 height
= window_height
;
8568 /* Compute the left edge of the scroll bar area. */
8569 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8570 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8572 left
= XFASTINT (w
->left
);
8573 left
*= CANON_X_UNIT (f
);
8574 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8576 /* Compute the width of the scroll bar which might be less than
8577 the width of the area reserved for the scroll bar. */
8578 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8579 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8583 /* Compute the left edge of the scroll bar. */
8584 #ifdef USE_TOOLKIT_SCROLL_BARS
8585 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8586 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8588 sb_left
= left
+ (width
- sb_width
) / 2;
8590 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8591 sb_left
= left
+ width
- sb_width
;
8596 /* Does the scroll bar exist yet? */
8597 if (NILP (w
->vertical_scroll_bar
))
8600 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8601 left
, top
, width
, height
, False
);
8603 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
8607 /* It may just need to be moved and resized. */
8608 unsigned int mask
= 0;
8610 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8614 if (sb_left
!= XINT (bar
->left
))
8616 if (top
!= XINT (bar
->top
))
8618 if (sb_width
!= XINT (bar
->width
))
8620 if (height
!= XINT (bar
->height
))
8623 #ifdef USE_TOOLKIT_SCROLL_BARS
8625 /* Since toolkit scroll bars are smaller than the space reserved
8626 for them on the frame, we have to clear "under" them. */
8627 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8628 left
, top
, width
, height
, False
);
8630 /* Move/size the scroll bar widget. */
8632 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
8633 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8635 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8638 #else /* not USE_TOOLKIT_SCROLL_BARS */
8640 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
8642 /* Clear areas not covered by the scroll bar. This makes sure a
8643 previous mode line display is cleared after C-x 2 C-x 1, for
8644 example. Non-toolkit scroll bars are as wide as the area
8645 reserved for scroll bars - trim at both sides. */
8646 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8647 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8649 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8650 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8651 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8655 /* Move/size the scroll bar window. */
8660 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8662 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
8664 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
8668 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8670 /* Remember new settings. */
8671 XSETINT (bar
->left
, sb_left
);
8672 XSETINT (bar
->top
, top
);
8673 XSETINT (bar
->width
, sb_width
);
8674 XSETINT (bar
->height
, height
);
8679 #if USE_TOOLKIT_SCROLL_BARS
8680 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
8681 #else /* not USE_TOOLKIT_SCROLL_BARS */
8682 /* Set the scroll bar's current state, unless we're currently being
8684 if (NILP (bar
->dragging
))
8686 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8689 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8692 int start
= ((double) position
* top_range
) / whole
;
8693 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8694 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8697 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8699 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8703 /* The following three hooks are used when we're doing a thorough
8704 redisplay of the frame. We don't explicitly know which scroll bars
8705 are going to be deleted, because keeping track of when windows go
8706 away is a real pain - "Can you say set-window-configuration, boys
8707 and girls?" Instead, we just assert at the beginning of redisplay
8708 that *all* scroll bars are to be removed, and then save a scroll bar
8709 from the fiery pit when we actually redisplay its window. */
8711 /* Arrange for all scroll bars on FRAME to be removed at the next call
8712 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8713 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8716 XTcondemn_scroll_bars (frame
)
8719 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8720 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8723 bar
= FRAME_SCROLL_BARS (frame
);
8724 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8725 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8726 XSCROLL_BAR (bar
)->prev
= Qnil
;
8727 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8728 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8729 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8734 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8735 Note that WINDOW isn't necessarily condemned at all. */
8738 XTredeem_scroll_bar (window
)
8739 struct window
*window
;
8741 struct scroll_bar
*bar
;
8744 /* We can't redeem this window's scroll bar if it doesn't have one. */
8745 if (NILP (window
->vertical_scroll_bar
))
8748 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8750 /* Unlink it from the condemned list. */
8751 f
= XFRAME (WINDOW_FRAME (window
));
8752 if (NILP (bar
->prev
))
8754 /* If the prev pointer is nil, it must be the first in one of
8756 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8757 /* It's not condemned. Everything's fine. */
8759 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8760 window
->vertical_scroll_bar
))
8761 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8763 /* If its prev pointer is nil, it must be at the front of
8764 one or the other! */
8768 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8770 if (! NILP (bar
->next
))
8771 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8773 bar
->next
= FRAME_SCROLL_BARS (f
);
8775 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8776 if (! NILP (bar
->next
))
8777 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8780 /* Remove all scroll bars on FRAME that haven't been saved since the
8781 last call to `*condemn_scroll_bars_hook'. */
8784 XTjudge_scroll_bars (f
)
8787 Lisp_Object bar
, next
;
8789 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8791 /* Clear out the condemned list now so we won't try to process any
8792 more events on the hapless scroll bars. */
8793 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8795 for (; ! NILP (bar
); bar
= next
)
8797 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8799 x_scroll_bar_remove (b
);
8802 b
->next
= b
->prev
= Qnil
;
8805 /* Now there should be no references to the condemned scroll bars,
8806 and they should get garbage-collected. */
8810 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8811 is a no-op when using toolkit scroll bars.
8813 This may be called from a signal handler, so we have to ignore GC
8817 x_scroll_bar_expose (bar
, event
)
8818 struct scroll_bar
*bar
;
8821 #ifndef USE_TOOLKIT_SCROLL_BARS
8823 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8824 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8825 GC gc
= f
->output_data
.x
->normal_gc
;
8826 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8830 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8832 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8833 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8835 /* x, y, width, height */
8837 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8838 XINT (bar
->height
) - 1);
8842 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8845 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8846 is set to something other than no_event, it is enqueued.
8848 This may be called from a signal handler, so we have to ignore GC
8851 #ifndef USE_TOOLKIT_SCROLL_BARS
8854 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8855 struct scroll_bar
*bar
;
8857 struct input_event
*emacs_event
;
8859 if (! GC_WINDOWP (bar
->window
))
8862 emacs_event
->kind
= scroll_bar_click
;
8863 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8864 emacs_event
->modifiers
8865 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8866 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8867 event
->xbutton
.state
)
8868 | (event
->type
== ButtonRelease
8871 emacs_event
->frame_or_window
= bar
->window
;
8872 emacs_event
->arg
= Qnil
;
8873 emacs_event
->timestamp
= event
->xbutton
.time
;
8876 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8878 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8881 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8882 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8885 if (y
> top_range
) y
= top_range
;
8887 if (y
< XINT (bar
->start
))
8888 emacs_event
->part
= scroll_bar_above_handle
;
8889 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8890 emacs_event
->part
= scroll_bar_handle
;
8892 emacs_event
->part
= scroll_bar_below_handle
;
8894 /* Just because the user has clicked on the handle doesn't mean
8895 they want to drag it. Lisp code needs to be able to decide
8896 whether or not we're dragging. */
8898 /* If the user has just clicked on the handle, record where they're
8900 if (event
->type
== ButtonPress
8901 && emacs_event
->part
== scroll_bar_handle
)
8902 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8905 /* If the user has released the handle, set it to its final position. */
8906 if (event
->type
== ButtonRelease
8907 && ! NILP (bar
->dragging
))
8909 int new_start
= y
- XINT (bar
->dragging
);
8910 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8912 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8913 bar
->dragging
= Qnil
;
8916 /* Same deal here as the other #if 0. */
8918 /* Clicks on the handle are always reported as occurring at the top of
8920 if (emacs_event
->part
== scroll_bar_handle
)
8921 emacs_event
->x
= bar
->start
;
8923 XSETINT (emacs_event
->x
, y
);
8925 XSETINT (emacs_event
->x
, y
);
8928 XSETINT (emacs_event
->y
, top_range
);
8932 /* Handle some mouse motion while someone is dragging the scroll bar.
8934 This may be called from a signal handler, so we have to ignore GC
8938 x_scroll_bar_note_movement (bar
, event
)
8939 struct scroll_bar
*bar
;
8942 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8944 last_mouse_movement_time
= event
->xmotion
.time
;
8947 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8949 /* If we're dragging the bar, display it. */
8950 if (! GC_NILP (bar
->dragging
))
8952 /* Where should the handle be now? */
8953 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8955 if (new_start
!= XINT (bar
->start
))
8957 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8959 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8964 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8966 /* Return information to the user about the current position of the mouse
8967 on the scroll bar. */
8970 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8972 Lisp_Object
*bar_window
;
8973 enum scroll_bar_part
*part
;
8975 unsigned long *time
;
8977 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8978 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8979 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8981 Window dummy_window
;
8983 unsigned int dummy_mask
;
8987 /* Get the mouse's position relative to the scroll bar window, and
8989 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8991 /* Root, child, root x and root y. */
8992 &dummy_window
, &dummy_window
,
8993 &dummy_coord
, &dummy_coord
,
8995 /* Position relative to scroll bar. */
8998 /* Mouse buttons and modifier keys. */
9005 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
9008 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
9010 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
9012 if (! NILP (bar
->dragging
))
9013 win_y
-= XINT (bar
->dragging
);
9017 if (win_y
> top_range
)
9021 *bar_window
= bar
->window
;
9023 if (! NILP (bar
->dragging
))
9024 *part
= scroll_bar_handle
;
9025 else if (win_y
< XINT (bar
->start
))
9026 *part
= scroll_bar_above_handle
;
9027 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
9028 *part
= scroll_bar_handle
;
9030 *part
= scroll_bar_below_handle
;
9032 XSETINT (*x
, win_y
);
9033 XSETINT (*y
, top_range
);
9036 last_mouse_scroll_bar
= Qnil
;
9039 *time
= last_mouse_movement_time
;
9045 /* The screen has been cleared so we may have changed foreground or
9046 background colors, and the scroll bars may need to be redrawn.
9047 Clear out the scroll bars, and ask for expose events, so we can
9051 x_scroll_bar_clear (f
)
9054 #ifndef USE_TOOLKIT_SCROLL_BARS
9057 /* We can have scroll bars even if this is 0,
9058 if we just turned off scroll bar mode.
9059 But in that case we should not clear them. */
9060 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
9061 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
9062 bar
= XSCROLL_BAR (bar
)->next
)
9063 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
9065 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9068 /* This processes Expose events from the menu-bar specific X event
9069 loop in xmenu.c. This allows to redisplay the frame if necessary
9070 when handling menu-bar or pop-up items. */
9073 process_expose_from_menu (event
)
9077 struct x_display_info
*dpyinfo
;
9078 int frame_exposed_p
= 0;
9082 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
9083 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9086 if (f
->async_visible
== 0)
9088 f
->async_visible
= 1;
9089 f
->async_iconified
= 0;
9090 f
->output_data
.x
->has_been_visible
= 1;
9091 SET_FRAME_GARBAGED (f
);
9095 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
9096 event
.xexpose
.x
, event
.xexpose
.y
,
9097 event
.xexpose
.width
, event
.xexpose
.height
);
9098 frame_exposed_p
= 1;
9103 struct scroll_bar
*bar
9104 = x_window_to_scroll_bar (event
.xexpose
.window
);
9107 x_scroll_bar_expose (bar
, &event
);
9111 return frame_exposed_p
;
9114 /* Define a queue to save up SelectionRequest events for later handling. */
9116 struct selection_event_queue
9119 struct selection_event_queue
*next
;
9122 static struct selection_event_queue
*queue
;
9124 /* Nonzero means queue up certain events--don't process them yet. */
9126 static int x_queue_selection_requests
;
9128 /* Queue up an X event *EVENT, to be processed later. */
9131 x_queue_event (f
, event
)
9135 struct selection_event_queue
*queue_tmp
9136 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
9138 if (queue_tmp
!= NULL
)
9140 queue_tmp
->event
= *event
;
9141 queue_tmp
->next
= queue
;
9146 /* Take all the queued events and put them back
9147 so that they get processed afresh. */
9150 x_unqueue_events (display
)
9153 while (queue
!= NULL
)
9155 struct selection_event_queue
*queue_tmp
= queue
;
9156 XPutBackEvent (display
, &queue_tmp
->event
);
9157 queue
= queue_tmp
->next
;
9158 xfree ((char *)queue_tmp
);
9162 /* Start queuing SelectionRequest events. */
9165 x_start_queuing_selection_requests (display
)
9168 x_queue_selection_requests
++;
9171 /* Stop queuing SelectionRequest events. */
9174 x_stop_queuing_selection_requests (display
)
9177 x_queue_selection_requests
--;
9178 x_unqueue_events (display
);
9181 /* The main X event-reading loop - XTread_socket. */
9183 /* Time stamp of enter window event. This is only used by XTread_socket,
9184 but we have to put it out here, since static variables within functions
9185 sometimes don't work. */
9187 static Time enter_timestamp
;
9189 /* This holds the state XLookupString needs to implement dead keys
9190 and other tricks known as "compose processing". _X Window System_
9191 says that a portable program can't use this, but Stephen Gildea assures
9192 me that letting the compiler initialize it to zeros will work okay.
9194 This must be defined outside of XTread_socket, for the same reasons
9195 given for enter_time stamp, above. */
9197 static XComposeStatus compose_status
;
9199 /* Record the last 100 characters stored
9200 to help debug the loss-of-chars-during-GC problem. */
9202 static int temp_index
;
9203 static short temp_buffer
[100];
9205 /* Set this to nonzero to fake an "X I/O error"
9206 on a particular display. */
9208 struct x_display_info
*XTread_socket_fake_io_error
;
9210 /* When we find no input here, we occasionally do a no-op command
9211 to verify that the X server is still running and we can still talk with it.
9212 We try all the open displays, one by one.
9213 This variable is used for cycling thru the displays. */
9215 static struct x_display_info
*next_noop_dpyinfo
;
9217 #define SET_SAVED_MENU_EVENT(size) \
9220 if (f->output_data.x->saved_menu_event == 0) \
9221 f->output_data.x->saved_menu_event \
9222 = (XEvent *) xmalloc (sizeof (XEvent)); \
9223 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9224 if (numchars >= 1) \
9226 bufp->kind = menu_bar_activate_event; \
9227 XSETFRAME (bufp->frame_or_window, f); \
9236 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9237 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9239 /* Read events coming from the X server.
9240 This routine is called by the SIGIO handler.
9241 We return as soon as there are no more events to be read.
9243 Events representing keys are stored in buffer BUFP,
9244 which can hold up to NUMCHARS characters.
9245 We return the number of characters stored into the buffer,
9246 thus pretending to be `read'.
9248 EXPECTED is nonzero if the caller knows input is available. */
9251 XTread_socket (sd
, bufp
, numchars
, expected
)
9253 /* register */ struct input_event
*bufp
;
9254 /* register */ int numchars
;
9261 int event_found
= 0;
9262 struct x_display_info
*dpyinfo
;
9263 struct coding_system coding
;
9265 if (interrupt_input_blocked
)
9267 interrupt_input_pending
= 1;
9271 interrupt_input_pending
= 0;
9274 /* So people can tell when we have read the available input. */
9275 input_signal_count
++;
9278 abort (); /* Don't think this happens. */
9282 /* The input should be decoded if it is from XIM. Currently the
9283 locale of XIM is the same as that of the system. So, we can use
9284 Vlocale_coding_system which is initialized properly at Emacs
9286 setup_coding_system (Vlocale_coding_system
, &coding
);
9287 coding
.src_multibyte
= 0;
9288 coding
.dst_multibyte
= 1;
9289 /* The input is converted to events, thus we can't handle
9290 composition. Anyway, there's no XIM that gives us composition
9292 coding
.composing
= COMPOSITION_DISABLED
;
9294 /* Find the display we are supposed to read input for.
9295 It's the one communicating on descriptor SD. */
9296 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
9298 #if 0 /* This ought to be unnecessary; let's verify it. */
9300 /* If available, Xlib uses FIOSNBIO to make the socket
9301 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9302 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9303 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9304 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
9305 #endif /* ! defined (FIOSNBIO) */
9308 #if 0 /* This code can't be made to work, with multiple displays,
9309 and appears not to be used on any system any more.
9310 Also keyboard.c doesn't turn O_NDELAY on and off
9311 for X connections. */
9314 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
9316 extern int read_alarm_should_throw
;
9317 read_alarm_should_throw
= 1;
9318 XPeekEvent (dpyinfo
->display
, &event
);
9319 read_alarm_should_throw
= 0;
9321 #endif /* HAVE_SELECT */
9325 /* For debugging, this gives a way to fake an I/O error. */
9326 if (dpyinfo
== XTread_socket_fake_io_error
)
9328 XTread_socket_fake_io_error
= 0;
9329 x_io_error_quitter (dpyinfo
->display
);
9332 while (XPending (dpyinfo
->display
))
9334 XNextEvent (dpyinfo
->display
, &event
);
9338 /* Filter events for the current X input method.
9339 XFilterEvent returns non-zero if the input method has
9340 consumed the event. We pass the frame's X window to
9341 XFilterEvent because that's the one for which the IC
9343 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
9344 event
.xclient
.window
);
9345 if (XFilterEvent (&event
, f1
? FRAME_X_WINDOW (f1
) : None
))
9355 if (event
.xclient
.message_type
9356 == dpyinfo
->Xatom_wm_protocols
9357 && event
.xclient
.format
== 32)
9359 if (event
.xclient
.data
.l
[0]
9360 == dpyinfo
->Xatom_wm_take_focus
)
9362 /* Use x_any_window_to_frame because this
9363 could be the shell widget window
9364 if the frame has no title bar. */
9365 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
9367 /* Not quite sure this is needed -pd */
9368 if (f
&& FRAME_XIC (f
))
9369 XSetICFocus (FRAME_XIC (f
));
9371 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9372 instructs the WM to set the input focus automatically for
9373 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9374 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9375 it has set the focus. So, XSetInputFocus below is not
9378 The call to XSetInputFocus below has also caused trouble. In
9379 cases where the XSetInputFocus done by the WM and the one
9380 below are temporally close (on a fast machine), the call
9381 below can generate additional FocusIn events which confuse
9384 /* Since we set WM_TAKE_FOCUS, we must call
9385 XSetInputFocus explicitly. But not if f is null,
9386 since that might be an event for a deleted frame. */
9389 Display
*d
= event
.xclient
.display
;
9390 /* Catch and ignore errors, in case window has been
9391 iconified by a window manager such as GWM. */
9392 int count
= x_catch_errors (d
);
9393 XSetInputFocus (d
, event
.xclient
.window
,
9394 /* The ICCCM says this is
9395 the only valid choice. */
9397 event
.xclient
.data
.l
[1]);
9398 /* This is needed to detect the error
9399 if there is an error. */
9401 x_uncatch_errors (d
, count
);
9403 /* Not certain about handling scroll bars here */
9406 else if (event
.xclient
.data
.l
[0]
9407 == dpyinfo
->Xatom_wm_save_yourself
)
9409 /* Save state modify the WM_COMMAND property to
9410 something which can reinstate us. This notifies
9411 the session manager, who's looking for such a
9412 PropertyNotify. Can restart processing when
9413 a keyboard or mouse event arrives. */
9416 f
= x_top_window_to_frame (dpyinfo
,
9417 event
.xclient
.window
);
9419 /* This is just so we only give real data once
9420 for a single Emacs process. */
9421 if (f
== SELECTED_FRAME ())
9422 XSetCommand (FRAME_X_DISPLAY (f
),
9423 event
.xclient
.window
,
9424 initial_argv
, initial_argc
);
9426 XSetCommand (FRAME_X_DISPLAY (f
),
9427 event
.xclient
.window
,
9431 else if (event
.xclient
.data
.l
[0]
9432 == dpyinfo
->Xatom_wm_delete_window
)
9435 = x_any_window_to_frame (dpyinfo
,
9436 event
.xclient
.window
);
9443 bufp
->kind
= delete_window_event
;
9444 XSETFRAME (bufp
->frame_or_window
, f
);
9453 else if (event
.xclient
.message_type
9454 == dpyinfo
->Xatom_wm_configure_denied
)
9457 else if (event
.xclient
.message_type
9458 == dpyinfo
->Xatom_wm_window_moved
)
9462 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9464 new_x
= event
.xclient
.data
.s
[0];
9465 new_y
= event
.xclient
.data
.s
[1];
9469 f
->output_data
.x
->left_pos
= new_x
;
9470 f
->output_data
.x
->top_pos
= new_y
;
9474 else if (event
.xclient
.message_type
9475 == dpyinfo
->Xatom_editres
)
9478 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
9479 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
9482 #endif /* HACK_EDITRES */
9483 else if ((event
.xclient
.message_type
9484 == dpyinfo
->Xatom_DONE
)
9485 || (event
.xclient
.message_type
9486 == dpyinfo
->Xatom_PAGE
))
9488 /* Ghostview job completed. Kill it. We could
9489 reply with "Next" if we received "Page", but we
9490 currently never do because we are interested in
9491 images, only, which should have 1 page. */
9492 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
9494 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9495 x_kill_gs_process (pixmap
, f
);
9496 expose_frame (f
, 0, 0, 0, 0);
9498 #ifdef USE_TOOLKIT_SCROLL_BARS
9499 /* Scroll bar callbacks send a ClientMessage from which
9500 we construct an input_event. */
9501 else if (event
.xclient
.message_type
9502 == dpyinfo
->Xatom_Scrollbar
)
9504 x_scroll_bar_to_input_event (&event
, bufp
);
9505 ++bufp
, ++count
, --numchars
;
9508 #endif /* USE_TOOLKIT_SCROLL_BARS */
9514 case SelectionNotify
:
9515 #ifdef USE_X_TOOLKIT
9516 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
9518 #endif /* not USE_X_TOOLKIT */
9519 x_handle_selection_notify (&event
.xselection
);
9522 case SelectionClear
: /* Someone has grabbed ownership. */
9523 #ifdef USE_X_TOOLKIT
9524 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
9526 #endif /* USE_X_TOOLKIT */
9528 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
9533 bufp
->kind
= selection_clear_event
;
9534 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9535 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9536 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9537 bufp
->frame_or_window
= Qnil
;
9546 case SelectionRequest
: /* Someone wants our selection. */
9547 #ifdef USE_X_TOOLKIT
9548 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
9550 #endif /* USE_X_TOOLKIT */
9551 if (x_queue_selection_requests
)
9552 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
9556 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
9561 bufp
->kind
= selection_request_event
;
9562 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9563 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
9564 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9565 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
9566 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
9567 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9568 bufp
->frame_or_window
= Qnil
;
9577 case PropertyNotify
:
9578 #ifdef USE_X_TOOLKIT
9579 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
9581 #endif /* not USE_X_TOOLKIT */
9582 x_handle_property_notify (&event
.xproperty
);
9585 case ReparentNotify
:
9586 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
9590 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
9591 x_real_positions (f
, &x
, &y
);
9592 f
->output_data
.x
->left_pos
= x
;
9593 f
->output_data
.x
->top_pos
= y
;
9598 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9601 if (f
->async_visible
== 0)
9603 f
->async_visible
= 1;
9604 f
->async_iconified
= 0;
9605 f
->output_data
.x
->has_been_visible
= 1;
9606 SET_FRAME_GARBAGED (f
);
9609 expose_frame (x_window_to_frame (dpyinfo
,
9610 event
.xexpose
.window
),
9611 event
.xexpose
.x
, event
.xexpose
.y
,
9612 event
.xexpose
.width
, event
.xexpose
.height
);
9616 #ifdef USE_TOOLKIT_SCROLL_BARS
9617 /* Dispatch event to the widget. */
9619 #else /* not USE_TOOLKIT_SCROLL_BARS */
9620 struct scroll_bar
*bar
9621 = x_window_to_scroll_bar (event
.xexpose
.window
);
9624 x_scroll_bar_expose (bar
, &event
);
9625 #ifdef USE_X_TOOLKIT
9628 #endif /* USE_X_TOOLKIT */
9629 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9633 case GraphicsExpose
: /* This occurs when an XCopyArea's
9634 source area was obscured or not
9636 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
9640 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
9641 event
.xgraphicsexpose
.width
,
9642 event
.xgraphicsexpose
.height
);
9644 #ifdef USE_X_TOOLKIT
9647 #endif /* USE_X_TOOLKIT */
9650 case NoExpose
: /* This occurs when an XCopyArea's
9651 source area was completely
9656 /* Redo the mouse-highlight after the tooltip has gone. */
9657 if (event
.xmap
.window
== tip_window
)
9660 redo_mouse_highlight ();
9663 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
9664 if (f
) /* F may no longer exist if
9665 the frame was deleted. */
9667 /* While a frame is unmapped, display generation is
9668 disabled; you don't want to spend time updating a
9669 display that won't ever be seen. */
9670 f
->async_visible
= 0;
9671 /* We can't distinguish, from the event, whether the window
9672 has become iconified or invisible. So assume, if it
9673 was previously visible, than now it is iconified.
9674 But x_make_frame_invisible clears both
9675 the visible flag and the iconified flag;
9676 and that way, we know the window is not iconified now. */
9677 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
9679 f
->async_iconified
= 1;
9681 bufp
->kind
= iconify_event
;
9682 XSETFRAME (bufp
->frame_or_window
, f
);
9692 if (event
.xmap
.window
== tip_window
)
9693 /* The tooltip has been drawn already. Avoid
9694 the SET_FRAME_GARBAGED below. */
9697 /* We use x_top_window_to_frame because map events can
9698 come for sub-windows and they don't mean that the
9699 frame is visible. */
9700 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
9703 f
->async_visible
= 1;
9704 f
->async_iconified
= 0;
9705 f
->output_data
.x
->has_been_visible
= 1;
9707 /* wait_reading_process_input will notice this and update
9708 the frame's display structures. */
9709 SET_FRAME_GARBAGED (f
);
9713 bufp
->kind
= deiconify_event
;
9714 XSETFRAME (bufp
->frame_or_window
, f
);
9720 else if (! NILP (Vframe_list
)
9721 && ! NILP (XCDR (Vframe_list
)))
9722 /* Force a redisplay sooner or later
9723 to update the frame titles
9724 in case this is the second frame. */
9725 record_asynch_buffer_change ();
9730 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
9733 /* I couldn't find a way to prevent LessTif scroll bars
9734 from consuming key events. */
9737 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
9739 if (widget
&& XmIsScrollBar (widget
))
9741 widget
= XtParent (widget
);
9742 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
9745 #endif /* USE_MOTIF */
9749 KeySym keysym
, orig_keysym
;
9750 /* al%imercury@uunet.uu.net says that making this 81
9751 instead of 80 fixed a bug whereby meta chars made
9754 It seems that some version of XmbLookupString has
9755 a bug of not returning XBufferOverflow in
9756 status_return even if the input is too long to
9757 fit in 81 bytes. So, we must prepare sufficient
9758 bytes for copy_buffer. 513 bytes (256 chars for
9759 two-byte character set) seems to be a faily good
9760 approximation. -- 2000.8.10 handa@etl.go.jp */
9761 unsigned char copy_buffer
[513];
9762 unsigned char *copy_bufptr
= copy_buffer
;
9763 int copy_bufsiz
= sizeof (copy_buffer
);
9767 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
9768 extra_keyboard_modifiers
);
9769 modifiers
= event
.xkey
.state
;
9771 /* This will have to go some day... */
9773 /* make_lispy_event turns chars into control chars.
9774 Don't do it here because XLookupString is too eager. */
9775 event
.xkey
.state
&= ~ControlMask
;
9776 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
9777 | dpyinfo
->super_mod_mask
9778 | dpyinfo
->hyper_mod_mask
9779 | dpyinfo
->alt_mod_mask
);
9781 /* In case Meta is ComposeCharacter,
9782 clear its status. According to Markus Ehrnsperger
9783 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9784 this enables ComposeCharacter to work whether or
9785 not it is combined with Meta. */
9786 if (modifiers
& dpyinfo
->meta_mod_mask
)
9787 bzero (&compose_status
, sizeof (compose_status
));
9792 Status status_return
;
9794 nbytes
= XmbLookupString (FRAME_XIC (f
),
9795 &event
.xkey
, copy_bufptr
,
9796 copy_bufsiz
, &keysym
,
9798 if (status_return
== XBufferOverflow
)
9800 copy_bufsiz
= nbytes
+ 1;
9801 copy_bufptr
= (char *) alloca (copy_bufsiz
);
9802 nbytes
= XmbLookupString (FRAME_XIC (f
),
9803 &event
.xkey
, copy_bufptr
,
9804 copy_bufsiz
, &keysym
,
9808 if (status_return
== XLookupNone
)
9810 else if (status_return
== XLookupChars
)
9815 else if (status_return
!= XLookupKeySym
9816 && status_return
!= XLookupBoth
)
9820 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
9821 copy_bufsiz
, &keysym
,
9824 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
9825 copy_bufsiz
, &keysym
,
9829 orig_keysym
= keysym
;
9833 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
9834 || keysym
== XK_Delete
9835 #ifdef XK_ISO_Left_Tab
9836 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
9838 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
9839 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
9840 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
9842 /* This recognizes the "extended function keys".
9843 It seems there's no cleaner way.
9844 Test IsModifierKey to avoid handling mode_switch
9846 || ((unsigned) (keysym
) >= XK_Select
9847 && (unsigned)(keysym
) < XK_KP_Space
)
9849 #ifdef XK_dead_circumflex
9850 || orig_keysym
== XK_dead_circumflex
9852 #ifdef XK_dead_grave
9853 || orig_keysym
== XK_dead_grave
9855 #ifdef XK_dead_tilde
9856 || orig_keysym
== XK_dead_tilde
9858 #ifdef XK_dead_diaeresis
9859 || orig_keysym
== XK_dead_diaeresis
9861 #ifdef XK_dead_macron
9862 || orig_keysym
== XK_dead_macron
9864 #ifdef XK_dead_degree
9865 || orig_keysym
== XK_dead_degree
9867 #ifdef XK_dead_acute
9868 || orig_keysym
== XK_dead_acute
9870 #ifdef XK_dead_cedilla
9871 || orig_keysym
== XK_dead_cedilla
9873 #ifdef XK_dead_breve
9874 || orig_keysym
== XK_dead_breve
9876 #ifdef XK_dead_ogonek
9877 || orig_keysym
== XK_dead_ogonek
9879 #ifdef XK_dead_caron
9880 || orig_keysym
== XK_dead_caron
9882 #ifdef XK_dead_doubleacute
9883 || orig_keysym
== XK_dead_doubleacute
9885 #ifdef XK_dead_abovedot
9886 || orig_keysym
== XK_dead_abovedot
9888 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9889 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9890 /* Any "vendor-specific" key is ok. */
9891 || (orig_keysym
& (1 << 28)))
9892 && ! (IsModifierKey (orig_keysym
)
9894 #ifdef XK_Mode_switch
9895 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9898 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9900 #endif /* not HAVE_X11R5 */
9903 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9905 temp_buffer
[temp_index
++] = keysym
;
9906 bufp
->kind
= non_ascii_keystroke
;
9907 bufp
->code
= keysym
;
9908 XSETFRAME (bufp
->frame_or_window
, f
);
9911 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9913 bufp
->timestamp
= event
.xkey
.time
;
9918 else if (numchars
> nbytes
)
9922 unsigned char *p
, *pend
;
9925 for (i
= 0; i
< nbytes
; i
++)
9927 if (temp_index
== (sizeof temp_buffer
9930 temp_buffer
[temp_index
++] = copy_bufptr
[i
];
9933 if (/* If the event is not from XIM, */
9934 event
.xkey
.keycode
!= 0
9935 /* or the current locale doesn't request
9936 decoding of the intup data, ... */
9937 || coding
.type
== coding_type_raw_text
9938 || coding
.type
== coding_type_no_conversion
)
9940 /* ... we can use the input data as is. */
9945 /* We have to decode the input data. */
9949 require
= decoding_buffer_size (&coding
, nbytes
);
9950 p
= (unsigned char *) alloca (require
);
9951 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
9952 decode_coding (&coding
, copy_bufptr
, p
,
9954 nbytes
= coding
.produced
;
9955 nchars
= coding
.produced_char
;
9959 /* Convert the input data to a sequence of
9960 character events. */
9961 for (i
= 0; i
< nbytes
; i
+= len
)
9963 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
9965 bufp
->kind
= (SINGLE_BYTE_CHAR_P (c
)
9967 : multibyte_char_keystroke
);
9969 XSETFRAME (bufp
->frame_or_window
, f
);
9972 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9974 bufp
->timestamp
= event
.xkey
.time
;
9981 if (keysym
== NoSymbol
)
9991 /* Don't dispatch this event since XtDispatchEvent calls
9992 XFilterEvent, and two calls in a row may freeze the
10001 /* Don't dispatch this event since XtDispatchEvent calls
10002 XFilterEvent, and two calls in a row may freeze the
10009 /* Here's a possible interpretation of the whole
10010 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10011 you get a FocusIn event, you have to get a FocusOut
10012 event before you relinquish the focus. If you
10013 haven't received a FocusIn event, then a mere
10014 LeaveNotify is enough to free you. */
10018 int from_menu_bar_p
= 0;
10020 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10022 #ifdef LESSTIF_VERSION
10023 /* When clicking outside of a menu bar popup to close
10024 it, we get a FocusIn/ EnterNotify sequence of
10025 events. The flag event.xcrossing.focus is not set
10026 in the EnterNotify event of that sequence because
10027 the focus is in the menu bar,
10028 event.xcrossing.window is the frame's X window.
10029 Unconditionally setting the focus frame to null in
10030 this case is not the right thing, because no event
10031 follows that could set the focus frame to the right
10034 This could be a LessTif bug, but I wasn't able to
10035 reproduce the behavior in a simple test program.
10037 (gerd, LessTif 0.88.1). */
10039 if (!event
.xcrossing
.focus
10041 && f
->output_data
.x
->menubar_widget
)
10046 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
10047 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
10048 from_menu_bar_p
= 1;
10050 #endif /* LESSTIF_VERSION */
10052 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
10054 /* Avoid nasty pop/raise loops. */
10055 if (f
&& (!(f
->auto_raise
)
10056 || !(f
->auto_lower
)
10057 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
10059 x_new_focus_frame (dpyinfo
, f
);
10060 enter_timestamp
= event
.xcrossing
.time
;
10063 else if (f
== dpyinfo
->x_focus_frame
)
10064 x_new_focus_frame (dpyinfo
, 0);
10066 /* EnterNotify counts as mouse movement,
10067 so update things that depend on mouse position. */
10068 if (f
&& !f
->output_data
.x
->busy_p
)
10069 note_mouse_movement (f
, &event
.xmotion
);
10074 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
10075 if (event
.xfocus
.detail
!= NotifyPointer
)
10076 dpyinfo
->x_focus_event_frame
= f
;
10079 x_new_focus_frame (dpyinfo
, f
);
10081 /* Don't stop displaying the initial startup message
10082 for a switch-frame event we don't need. */
10083 if (GC_NILP (Vterminal_frame
)
10084 && GC_CONSP (Vframe_list
)
10085 && !GC_NILP (XCDR (Vframe_list
)))
10087 bufp
->kind
= FOCUS_IN_EVENT
;
10088 XSETFRAME (bufp
->frame_or_window
, f
);
10090 ++bufp
, ++count
, --numchars
;
10095 if (f
&& FRAME_XIC (f
))
10096 XSetICFocus (FRAME_XIC (f
));
10102 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
10106 int from_menu_bar_p
= 0;
10108 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10110 /* If we move outside the frame, then we're
10111 certainly no longer on any text in the frame. */
10112 clear_mouse_face (dpyinfo
);
10113 dpyinfo
->mouse_face_mouse_frame
= 0;
10116 /* Generate a nil HELP_EVENT to cancel a help-echo.
10117 Do it only if there's something to cancel.
10118 Otherwise, the startup message is cleared when
10119 the mouse leaves the frame. */
10120 if (any_help_event_p
)
10125 XSETFRAME (frame
, f
);
10126 n
= gen_help_event (bufp
, numchars
,
10127 Qnil
, frame
, Qnil
, Qnil
, 0);
10128 bufp
+= n
, count
+= n
, numchars
-= n
;
10131 #ifdef LESSTIF_VERSION
10132 /* Please see the comment at the start of the
10133 EnterNotify case. */
10134 if (!event
.xcrossing
.focus
10135 && f
->output_data
.x
->menubar_widget
)
10139 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
10140 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
10141 from_menu_bar_p
= 1;
10143 #endif /* LESSTIF_VERSION */
10145 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
10146 x_mouse_leave (dpyinfo
);
10149 if (f
== dpyinfo
->x_focus_event_frame
)
10150 dpyinfo
->x_focus_event_frame
= 0;
10151 if (f
== dpyinfo
->x_focus_frame
)
10152 x_new_focus_frame (dpyinfo
, 0);
10158 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
10159 if (event
.xfocus
.detail
!= NotifyPointer
10160 && f
== dpyinfo
->x_focus_event_frame
)
10161 dpyinfo
->x_focus_event_frame
= 0;
10162 if (f
&& f
== dpyinfo
->x_focus_frame
)
10163 x_new_focus_frame (dpyinfo
, 0);
10166 if (f
&& FRAME_XIC (f
))
10167 XUnsetICFocus (FRAME_XIC (f
));
10174 previous_help_echo
= help_echo
;
10175 help_echo
= help_echo_object
= help_echo_window
= Qnil
;
10176 help_echo_pos
= -1;
10178 if (dpyinfo
->grabbed
&& last_mouse_frame
10179 && FRAME_LIVE_P (last_mouse_frame
))
10180 f
= last_mouse_frame
;
10182 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
10185 note_mouse_movement (f
, &event
.xmotion
);
10188 #ifndef USE_TOOLKIT_SCROLL_BARS
10189 struct scroll_bar
*bar
10190 = x_window_to_scroll_bar (event
.xmotion
.window
);
10193 x_scroll_bar_note_movement (bar
, &event
);
10194 #endif /* USE_TOOLKIT_SCROLL_BARS */
10196 /* If we move outside the frame, then we're
10197 certainly no longer on any text in the frame. */
10198 clear_mouse_face (dpyinfo
);
10201 /* If the contents of the global variable help_echo
10202 has changed, generate a HELP_EVENT. */
10203 if (!NILP (help_echo
)
10204 || !NILP (previous_help_echo
))
10210 XSETFRAME (frame
, f
);
10214 any_help_event_p
= 1;
10215 n
= gen_help_event (bufp
, numchars
, help_echo
, frame
,
10216 help_echo_window
, help_echo_object
,
10218 bufp
+= n
, count
+= n
, numchars
-= n
;
10224 case ConfigureNotify
:
10225 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
10228 #ifndef USE_X_TOOLKIT
10229 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
10230 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
10232 /* In the toolkit version, change_frame_size
10233 is called by the code that handles resizing
10234 of the EmacsFrame widget. */
10236 /* Even if the number of character rows and columns has
10237 not changed, the font size may have changed, so we need
10238 to check the pixel dimensions as well. */
10239 if (columns
!= f
->width
10240 || rows
!= f
->height
10241 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
10242 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
10244 change_frame_size (f
, rows
, columns
, 0, 1, 0);
10245 SET_FRAME_GARBAGED (f
);
10246 cancel_mouse_face (f
);
10250 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
10251 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
10253 /* What we have now is the position of Emacs's own window.
10254 Convert that to the position of the window manager window. */
10255 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
10256 &f
->output_data
.x
->top_pos
);
10259 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
10260 xic_set_statusarea (f
);
10263 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10265 /* Since the WM decorations come below top_pos now,
10266 we must put them below top_pos in the future. */
10267 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10268 x_wm_set_size_hint (f
, (long) 0, 0);
10271 /* Some window managers pass (0,0) as the location of
10272 the window, and the Motif event handler stores it
10273 in the emacs widget, which messes up Motif menus. */
10274 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
10276 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
10277 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
10279 #endif /* USE_MOTIF */
10284 case ButtonRelease
:
10286 /* If we decide we want to generate an event to be seen
10287 by the rest of Emacs, we put it here. */
10288 struct input_event emacs_event
;
10289 int tool_bar_p
= 0;
10291 emacs_event
.kind
= no_event
;
10292 bzero (&compose_status
, sizeof (compose_status
));
10294 if (dpyinfo
->grabbed
10295 && last_mouse_frame
10296 && FRAME_LIVE_P (last_mouse_frame
))
10297 f
= last_mouse_frame
;
10299 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
10303 /* Is this in the tool-bar? */
10304 if (WINDOWP (f
->tool_bar_window
)
10305 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
10307 Lisp_Object window
;
10310 x
= event
.xbutton
.x
;
10311 y
= event
.xbutton
.y
;
10314 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
10315 if (EQ (window
, f
->tool_bar_window
))
10317 x_handle_tool_bar_click (f
, &event
.xbutton
);
10323 if (!dpyinfo
->x_focus_frame
10324 || f
== dpyinfo
->x_focus_frame
)
10325 construct_mouse_click (&emacs_event
, &event
, f
);
10329 #ifndef USE_TOOLKIT_SCROLL_BARS
10330 struct scroll_bar
*bar
10331 = x_window_to_scroll_bar (event
.xbutton
.window
);
10334 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
10335 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10338 if (event
.type
== ButtonPress
)
10340 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
10341 last_mouse_frame
= f
;
10342 /* Ignore any mouse motion that happened
10343 before this event; any subsequent mouse-movement
10344 Emacs events should reflect only motion after
10345 the ButtonPress. */
10347 f
->mouse_moved
= 0;
10350 last_tool_bar_item
= -1;
10354 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
10357 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
10359 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
10365 #ifdef USE_X_TOOLKIT
10366 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
10367 /* For a down-event in the menu bar,
10368 don't pass it to Xt right now.
10369 Instead, save it away
10370 and we will pass it to Xt from kbd_buffer_get_event.
10371 That way, we can run some Lisp code first. */
10372 if (f
&& event
.type
== ButtonPress
10373 /* Verify the event is really within the menu bar
10374 and not just sent to it due to grabbing. */
10375 && event
.xbutton
.x
>= 0
10376 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
10377 && event
.xbutton
.y
>= 0
10378 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
10379 && event
.xbutton
.same_screen
)
10381 SET_SAVED_BUTTON_EVENT
;
10382 XSETFRAME (last_mouse_press_frame
, f
);
10384 else if (event
.type
== ButtonPress
)
10386 last_mouse_press_frame
= Qnil
;
10390 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10391 but I am trying to be cautious. */
10392 else if (event
.type
== ButtonRelease
)
10394 if (!NILP (last_mouse_press_frame
))
10396 f
= XFRAME (last_mouse_press_frame
);
10397 if (f
->output_data
.x
)
10398 SET_SAVED_BUTTON_EVENT
;
10403 #endif /* USE_MOTIF */
10406 #endif /* USE_X_TOOLKIT */
10410 case CirculateNotify
:
10413 case CirculateRequest
:
10416 case VisibilityNotify
:
10419 case MappingNotify
:
10420 /* Someone has changed the keyboard mapping - update the
10422 switch (event
.xmapping
.request
)
10424 case MappingModifier
:
10425 x_find_modifier_meanings (dpyinfo
);
10426 /* This is meant to fall through. */
10427 case MappingKeyboard
:
10428 XRefreshKeyboardMapping (&event
.xmapping
);
10434 #ifdef USE_X_TOOLKIT
10436 XtDispatchEvent (&event
);
10438 #endif /* USE_X_TOOLKIT */
10446 /* On some systems, an X bug causes Emacs to get no more events
10447 when the window is destroyed. Detect that. (1994.) */
10450 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10451 One XNOOP in 100 loops will make Emacs terminate.
10452 B. Bretthauer, 1994 */
10454 if (x_noop_count
>= 100)
10458 if (next_noop_dpyinfo
== 0)
10459 next_noop_dpyinfo
= x_display_list
;
10461 XNoOp (next_noop_dpyinfo
->display
);
10463 /* Each time we get here, cycle through the displays now open. */
10464 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
10468 /* If the focus was just given to an auto-raising frame,
10470 /* ??? This ought to be able to handle more than one such frame. */
10471 if (pending_autoraise_frame
)
10473 x_raise_frame (pending_autoraise_frame
);
10474 pending_autoraise_frame
= 0;
10485 /***********************************************************************
10487 ***********************************************************************/
10489 /* Note if the text cursor of window W has been overwritten by a
10490 drawing operation that outputs N glyphs starting at HPOS in the
10491 line given by output_cursor.vpos. N < 0 means all the rest of the
10492 line after HPOS has been written. */
10495 note_overwritten_text_cursor (w
, hpos
, n
)
10499 if (updated_area
== TEXT_AREA
10500 && output_cursor
.vpos
== w
->phys_cursor
.vpos
10501 && hpos
<= w
->phys_cursor
.hpos
10503 || hpos
+ n
> w
->phys_cursor
.hpos
))
10504 w
->phys_cursor_on_p
= 0;
10508 /* Set clipping for output in glyph row ROW. W is the window in which
10509 we operate. GC is the graphics context to set clipping in.
10510 WHOLE_LINE_P non-zero means include the areas used for truncation
10511 mark display and alike in the clipping rectangle.
10513 ROW may be a text row or, e.g., a mode line. Text rows must be
10514 clipped to the interior of the window dedicated to text display,
10515 mode lines must be clipped to the whole window. */
10518 x_clip_to_row (w
, row
, gc
, whole_line_p
)
10520 struct glyph_row
*row
;
10524 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
10525 XRectangle clip_rect
;
10526 int window_x
, window_y
, window_width
, window_height
;
10528 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
10530 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
10531 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
10532 clip_rect
.y
= max (clip_rect
.y
, window_y
);
10533 clip_rect
.width
= window_width
;
10534 clip_rect
.height
= row
->visible_height
;
10536 /* If clipping to the whole line, including trunc marks, extend
10537 the rectangle to the left and increase its width. */
10540 clip_rect
.x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
10541 clip_rect
.width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
10544 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
10548 /* Draw a hollow box cursor on window W in glyph row ROW. */
10551 x_draw_hollow_cursor (w
, row
)
10553 struct glyph_row
*row
;
10555 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
10556 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10557 Display
*dpy
= FRAME_X_DISPLAY (f
);
10560 struct glyph
*cursor_glyph
;
10563 /* Compute frame-relative coordinates from window-relative
10565 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10566 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
10567 + row
->ascent
- w
->phys_cursor_ascent
);
10568 h
= row
->height
- 1;
10570 /* Get the glyph the cursor is on. If we can't tell because
10571 the current matrix is invalid or such, give up. */
10572 cursor_glyph
= get_phys_cursor_glyph (w
);
10573 if (cursor_glyph
== NULL
)
10576 /* Compute the width of the rectangle to draw. If on a stretch
10577 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10578 rectangle as wide as the glyph, but use a canonical character
10580 wd
= cursor_glyph
->pixel_width
- 1;
10581 if (cursor_glyph
->type
== STRETCH_GLYPH
10582 && !x_stretch_cursor_p
)
10583 wd
= min (CANON_X_UNIT (f
), wd
);
10585 /* The foreground of cursor_gc is typically the same as the normal
10586 background color, which can cause the cursor box to be invisible. */
10587 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10588 if (dpyinfo
->scratch_cursor_gc
)
10589 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
10591 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
10592 GCForeground
, &xgcv
);
10593 gc
= dpyinfo
->scratch_cursor_gc
;
10595 /* Set clipping, draw the rectangle, and reset clipping again. */
10596 x_clip_to_row (w
, row
, gc
, 0);
10597 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
10598 XSetClipMask (dpy
, gc
, None
);
10602 /* Draw a bar cursor on window W in glyph row ROW.
10604 Implementation note: One would like to draw a bar cursor with an
10605 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10606 Unfortunately, I didn't find a font yet that has this property set.
10610 x_draw_bar_cursor (w
, row
, width
)
10612 struct glyph_row
*row
;
10615 struct frame
*f
= XFRAME (w
->frame
);
10616 struct glyph
*cursor_glyph
;
10619 unsigned long mask
;
10624 /* If cursor is out of bounds, don't draw garbage. This can happen
10625 in mini-buffer windows when switching between echo area glyphs
10626 and mini-buffer. */
10627 cursor_glyph
= get_phys_cursor_glyph (w
);
10628 if (cursor_glyph
== NULL
)
10631 /* If on an image, draw like a normal cursor. That's usually better
10632 visible than drawing a bar, esp. if the image is large so that
10633 the bar might not be in the window. */
10634 if (cursor_glyph
->type
== IMAGE_GLYPH
)
10636 struct glyph_row
*row
;
10637 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
10638 x_draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
10642 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
10643 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10644 xgcv
.graphics_exposures
= 0;
10645 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
10646 dpy
= FRAME_X_DISPLAY (f
);
10647 window
= FRAME_X_WINDOW (f
);
10648 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
10651 XChangeGC (dpy
, gc
, mask
, &xgcv
);
10654 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
10655 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
10659 width
= f
->output_data
.x
->cursor_width
;
10661 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10662 x_clip_to_row (w
, row
, gc
, 0);
10663 XFillRectangle (dpy
, window
, gc
,
10665 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
10666 min (cursor_glyph
->pixel_width
, width
),
10668 XSetClipMask (dpy
, gc
, None
);
10673 /* Clear the cursor of window W to background color, and mark the
10674 cursor as not shown. This is used when the text where the cursor
10675 is is about to be rewritten. */
10681 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
10682 x_update_window_cursor (w
, 0);
10686 /* Draw the cursor glyph of window W in glyph row ROW. See the
10687 comment of x_draw_glyphs for the meaning of HL. */
10690 x_draw_phys_cursor_glyph (w
, row
, hl
)
10692 struct glyph_row
*row
;
10693 enum draw_glyphs_face hl
;
10695 /* If cursor hpos is out of bounds, don't draw garbage. This can
10696 happen in mini-buffer windows when switching between echo area
10697 glyphs and mini-buffer. */
10698 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10700 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
10701 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
10704 /* When we erase the cursor, and ROW is overlapped by other
10705 rows, make sure that these overlapping parts of other rows
10707 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
10709 if (row
> w
->current_matrix
->rows
10710 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
10711 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
10713 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
10714 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
10715 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
10721 /* Erase the image of a cursor of window W from the screen. */
10724 x_erase_phys_cursor (w
)
10727 struct frame
*f
= XFRAME (w
->frame
);
10728 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10729 int hpos
= w
->phys_cursor
.hpos
;
10730 int vpos
= w
->phys_cursor
.vpos
;
10731 int mouse_face_here_p
= 0;
10732 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
10733 struct glyph_row
*cursor_row
;
10734 struct glyph
*cursor_glyph
;
10735 enum draw_glyphs_face hl
;
10737 /* No cursor displayed or row invalidated => nothing to do on the
10739 if (w
->phys_cursor_type
== NO_CURSOR
)
10740 goto mark_cursor_off
;
10742 /* VPOS >= active_glyphs->nrows means that window has been resized.
10743 Don't bother to erase the cursor. */
10744 if (vpos
>= active_glyphs
->nrows
)
10745 goto mark_cursor_off
;
10747 /* If row containing cursor is marked invalid, there is nothing we
10749 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
10750 if (!cursor_row
->enabled_p
)
10751 goto mark_cursor_off
;
10753 /* This can happen when the new row is shorter than the old one.
10754 In this case, either x_draw_glyphs or clear_end_of_line
10755 should have cleared the cursor. Note that we wouldn't be
10756 able to erase the cursor in this case because we don't have a
10757 cursor glyph at hand. */
10758 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
10759 goto mark_cursor_off
;
10761 /* If the cursor is in the mouse face area, redisplay that when
10762 we clear the cursor. */
10763 if (! NILP (dpyinfo
->mouse_face_window
)
10764 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
10765 && (vpos
> dpyinfo
->mouse_face_beg_row
10766 || (vpos
== dpyinfo
->mouse_face_beg_row
10767 && hpos
>= dpyinfo
->mouse_face_beg_col
))
10768 && (vpos
< dpyinfo
->mouse_face_end_row
10769 || (vpos
== dpyinfo
->mouse_face_end_row
10770 && hpos
< dpyinfo
->mouse_face_end_col
))
10771 /* Don't redraw the cursor's spot in mouse face if it is at the
10772 end of a line (on a newline). The cursor appears there, but
10773 mouse highlighting does not. */
10774 && cursor_row
->used
[TEXT_AREA
] > hpos
)
10775 mouse_face_here_p
= 1;
10777 /* Maybe clear the display under the cursor. */
10778 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
10781 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
10783 cursor_glyph
= get_phys_cursor_glyph (w
);
10784 if (cursor_glyph
== NULL
)
10785 goto mark_cursor_off
;
10787 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
10789 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10791 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
10793 cursor_glyph
->pixel_width
,
10794 cursor_row
->visible_height
,
10798 /* Erase the cursor by redrawing the character underneath it. */
10799 if (mouse_face_here_p
)
10800 hl
= DRAW_MOUSE_FACE
;
10801 else if (cursor_row
->inverse_p
)
10802 hl
= DRAW_INVERSE_VIDEO
;
10804 hl
= DRAW_NORMAL_TEXT
;
10805 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
10808 w
->phys_cursor_on_p
= 0;
10809 w
->phys_cursor_type
= NO_CURSOR
;
10813 /* Display or clear cursor of window W. If ON is zero, clear the
10814 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10815 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10818 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
10820 int on
, hpos
, vpos
, x
, y
;
10822 struct frame
*f
= XFRAME (w
->frame
);
10823 int new_cursor_type
;
10824 int new_cursor_width
;
10825 struct glyph_matrix
*current_glyphs
;
10826 struct glyph_row
*glyph_row
;
10827 struct glyph
*glyph
;
10829 /* This is pointless on invisible frames, and dangerous on garbaged
10830 windows and frames; in the latter case, the frame or window may
10831 be in the midst of changing its size, and x and y may be off the
10833 if (! FRAME_VISIBLE_P (f
)
10834 || FRAME_GARBAGED_P (f
)
10835 || vpos
>= w
->current_matrix
->nrows
10836 || hpos
>= w
->current_matrix
->matrix_w
)
10839 /* If cursor is off and we want it off, return quickly. */
10840 if (!on
&& !w
->phys_cursor_on_p
)
10843 current_glyphs
= w
->current_matrix
;
10844 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
10845 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
10847 /* If cursor row is not enabled, we don't really know where to
10848 display the cursor. */
10849 if (!glyph_row
->enabled_p
)
10851 w
->phys_cursor_on_p
= 0;
10855 xassert (interrupt_input_blocked
);
10857 /* Set new_cursor_type to the cursor we want to be displayed. In a
10858 mini-buffer window, we want the cursor only to appear if we are
10859 reading input from this window. For the selected window, we want
10860 the cursor type given by the frame parameter. If explicitly
10861 marked off, draw no cursor. In all other cases, we want a hollow
10863 new_cursor_width
= -1;
10864 if (cursor_in_echo_area
10865 && FRAME_HAS_MINIBUF_P (f
)
10866 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
10868 if (w
== XWINDOW (echo_area_window
))
10869 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10871 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10875 if (w
!= XWINDOW (selected_window
)
10876 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
10878 extern int cursor_in_non_selected_windows
;
10880 if (MINI_WINDOW_P (w
)
10881 || !cursor_in_non_selected_windows
10882 || NILP (XBUFFER (w
->buffer
)->cursor_type
))
10883 new_cursor_type
= NO_CURSOR
;
10885 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10887 else if (w
->cursor_off_p
)
10888 new_cursor_type
= NO_CURSOR
;
10891 struct buffer
*b
= XBUFFER (w
->buffer
);
10893 if (EQ (b
->cursor_type
, Qt
))
10894 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10896 new_cursor_type
= x_specified_cursor_type (b
->cursor_type
,
10897 &new_cursor_width
);
10901 /* If cursor is currently being shown and we don't want it to be or
10902 it is in the wrong place, or the cursor type is not what we want,
10904 if (w
->phys_cursor_on_p
10906 || w
->phys_cursor
.x
!= x
10907 || w
->phys_cursor
.y
!= y
10908 || new_cursor_type
!= w
->phys_cursor_type
))
10909 x_erase_phys_cursor (w
);
10911 /* If the cursor is now invisible and we want it to be visible,
10913 if (on
&& !w
->phys_cursor_on_p
)
10915 w
->phys_cursor_ascent
= glyph_row
->ascent
;
10916 w
->phys_cursor_height
= glyph_row
->height
;
10918 /* Set phys_cursor_.* before x_draw_.* is called because some
10919 of them may need the information. */
10920 w
->phys_cursor
.x
= x
;
10921 w
->phys_cursor
.y
= glyph_row
->y
;
10922 w
->phys_cursor
.hpos
= hpos
;
10923 w
->phys_cursor
.vpos
= vpos
;
10924 w
->phys_cursor_type
= new_cursor_type
;
10925 w
->phys_cursor_on_p
= 1;
10927 switch (new_cursor_type
)
10929 case HOLLOW_BOX_CURSOR
:
10930 x_draw_hollow_cursor (w
, glyph_row
);
10933 case FILLED_BOX_CURSOR
:
10934 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
10938 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
);
10949 if (w
== XWINDOW (f
->selected_window
))
10950 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
10951 xic_set_preeditarea (w
, x
, y
);
10956 if (updating_frame
!= f
)
10957 XFlush (FRAME_X_DISPLAY (f
));
10962 /* Display the cursor on window W, or clear it. X and Y are window
10963 relative pixel coordinates. HPOS and VPOS are glyph matrix
10964 positions. If W is not the selected window, display a hollow
10965 cursor. ON non-zero means display the cursor at X, Y which
10966 correspond to HPOS, VPOS, otherwise it is cleared. */
10969 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
10971 int on
, hpos
, vpos
, x
, y
;
10974 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
10979 /* Display the cursor on window W, or clear it, according to ON_P.
10980 Don't change the cursor's position. */
10983 x_update_cursor (f
, on_p
)
10986 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
10990 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10991 in the window tree rooted at W. */
10994 x_update_cursor_in_window_tree (w
, on_p
)
11000 if (!NILP (w
->hchild
))
11001 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
11002 else if (!NILP (w
->vchild
))
11003 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
11005 x_update_window_cursor (w
, on_p
);
11007 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
11012 /* Switch the display of W's cursor on or off, according to the value
11016 x_update_window_cursor (w
, on
)
11020 /* Don't update cursor in windows whose frame is in the process
11021 of being deleted. */
11022 if (w
->current_matrix
)
11025 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
11026 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
11036 /* Refresh bitmap kitchen sink icon for frame F
11037 when we get an expose event for it. */
11043 /* Normally, the window manager handles this function. */
11046 /* Make the x-window of frame F use the gnu icon bitmap. */
11049 x_bitmap_icon (f
, file
)
11055 if (FRAME_X_WINDOW (f
) == 0)
11058 /* Free up our existing icon bitmap if any. */
11059 if (f
->output_data
.x
->icon_bitmap
> 0)
11060 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
11061 f
->output_data
.x
->icon_bitmap
= 0;
11063 if (STRINGP (file
))
11064 bitmap_id
= x_create_bitmap_from_file (f
, file
);
11067 /* Create the GNU bitmap if necessary. */
11068 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
11069 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
11070 = x_create_bitmap_from_data (f
, gnu_bits
,
11071 gnu_width
, gnu_height
);
11073 /* The first time we create the GNU bitmap,
11074 this increments the ref-count one extra time.
11075 As a result, the GNU bitmap is never freed.
11076 That way, we don't have to worry about allocating it again. */
11077 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
11079 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
11082 x_wm_set_icon_pixmap (f
, bitmap_id
);
11083 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
11089 /* Make the x-window of frame F use a rectangle with text.
11090 Use ICON_NAME as the text. */
11093 x_text_icon (f
, icon_name
)
11097 if (FRAME_X_WINDOW (f
) == 0)
11102 XTextProperty text
;
11103 text
.value
= (unsigned char *) icon_name
;
11104 text
.encoding
= XA_STRING
;
11106 text
.nitems
= strlen (icon_name
);
11107 #ifdef USE_X_TOOLKIT
11108 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11110 #else /* not USE_X_TOOLKIT */
11111 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
11112 #endif /* not USE_X_TOOLKIT */
11114 #else /* not HAVE_X11R4 */
11115 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
11116 #endif /* not HAVE_X11R4 */
11118 if (f
->output_data
.x
->icon_bitmap
> 0)
11119 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
11120 f
->output_data
.x
->icon_bitmap
= 0;
11121 x_wm_set_icon_pixmap (f
, 0);
11126 #define X_ERROR_MESSAGE_SIZE 200
11128 /* If non-nil, this should be a string.
11129 It means catch X errors and store the error message in this string. */
11131 static Lisp_Object x_error_message_string
;
11133 /* An X error handler which stores the error message in
11134 x_error_message_string. This is called from x_error_handler if
11135 x_catch_errors is in effect. */
11138 x_error_catcher (display
, error
)
11140 XErrorEvent
*error
;
11142 XGetErrorText (display
, error
->error_code
,
11143 XSTRING (x_error_message_string
)->data
,
11144 X_ERROR_MESSAGE_SIZE
);
11147 /* Begin trapping X errors for display DPY. Actually we trap X errors
11148 for all displays, but DPY should be the display you are actually
11151 After calling this function, X protocol errors no longer cause
11152 Emacs to exit; instead, they are recorded in the string
11153 stored in x_error_message_string.
11155 Calling x_check_errors signals an Emacs error if an X error has
11156 occurred since the last call to x_catch_errors or x_check_errors.
11158 Calling x_uncatch_errors resumes the normal error handling. */
11160 void x_check_errors ();
11161 static Lisp_Object
x_catch_errors_unwind ();
11164 x_catch_errors (dpy
)
11167 int count
= specpdl_ptr
- specpdl
;
11169 /* Make sure any errors from previous requests have been dealt with. */
11170 XSync (dpy
, False
);
11172 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
11174 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
11175 XSTRING (x_error_message_string
)->data
[0] = 0;
11180 /* Unbind the binding that we made to check for X errors. */
11183 x_catch_errors_unwind (old_val
)
11184 Lisp_Object old_val
;
11186 x_error_message_string
= old_val
;
11190 /* If any X protocol errors have arrived since the last call to
11191 x_catch_errors or x_check_errors, signal an Emacs error using
11192 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11195 x_check_errors (dpy
, format
)
11199 /* Make sure to catch any errors incurred so far. */
11200 XSync (dpy
, False
);
11202 if (XSTRING (x_error_message_string
)->data
[0])
11203 error (format
, XSTRING (x_error_message_string
)->data
);
11206 /* Nonzero if we had any X protocol errors
11207 since we did x_catch_errors on DPY. */
11210 x_had_errors_p (dpy
)
11213 /* Make sure to catch any errors incurred so far. */
11214 XSync (dpy
, False
);
11216 return XSTRING (x_error_message_string
)->data
[0] != 0;
11219 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11222 x_clear_errors (dpy
)
11225 XSTRING (x_error_message_string
)->data
[0] = 0;
11228 /* Stop catching X protocol errors and let them make Emacs die.
11229 DPY should be the display that was passed to x_catch_errors.
11230 COUNT should be the value that was returned by
11231 the corresponding call to x_catch_errors. */
11234 x_uncatch_errors (dpy
, count
)
11238 unbind_to (count
, Qnil
);
11242 static unsigned int x_wire_count
;
11245 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
11250 /* Handle SIGPIPE, which can happen when the connection to a server
11251 simply goes away. SIGPIPE is handled by x_connection_signal.
11252 Don't need to do anything, because the write which caused the
11253 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11254 which will do the appropriate cleanup for us. */
11257 x_connection_signal (signalnum
) /* If we don't have an argument, */
11258 int signalnum
; /* some compilers complain in signal calls. */
11261 /* USG systems forget handlers when they are used;
11262 must reestablish each time */
11263 signal (signalnum
, x_connection_signal
);
11267 /* Handling X errors. */
11269 /* Handle the loss of connection to display DISPLAY. */
11272 x_connection_closed (display
, error_message
)
11274 char *error_message
;
11276 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
11277 Lisp_Object frame
, tail
;
11279 /* Indicate that this display is dead. */
11281 #if 0 /* Closing the display caused a bus error on OpenWindows. */
11282 #ifdef USE_X_TOOLKIT
11283 XtCloseDisplay (display
);
11288 dpyinfo
->display
= 0;
11290 /* First delete frames whose mini-buffers are on frames
11291 that are on the dead display. */
11292 FOR_EACH_FRAME (tail
, frame
)
11294 Lisp_Object minibuf_frame
;
11296 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
11297 if (FRAME_X_P (XFRAME (frame
))
11298 && FRAME_X_P (XFRAME (minibuf_frame
))
11299 && ! EQ (frame
, minibuf_frame
)
11300 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
11301 Fdelete_frame (frame
, Qt
);
11304 /* Now delete all remaining frames on the dead display.
11305 We are now sure none of these is used as the mini-buffer
11306 for another frame that we need to delete. */
11307 FOR_EACH_FRAME (tail
, frame
)
11308 if (FRAME_X_P (XFRAME (frame
))
11309 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
11311 /* Set this to t so that Fdelete_frame won't get confused
11312 trying to find a replacement. */
11313 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
11314 Fdelete_frame (frame
, Qt
);
11318 x_delete_display (dpyinfo
);
11320 if (x_display_list
== 0)
11322 fprintf (stderr
, "%s\n", error_message
);
11323 shut_down_emacs (0, 0, Qnil
);
11327 /* Ordinary stack unwind doesn't deal with these. */
11329 sigunblock (sigmask (SIGIO
));
11331 sigunblock (sigmask (SIGALRM
));
11332 TOTALLY_UNBLOCK_INPUT
;
11334 clear_waiting_for_input ();
11335 handling_signal
= 0;
11336 error ("%s", error_message
);
11339 /* This is the usual handler for X protocol errors.
11340 It kills all frames on the display that we got the error for.
11341 If that was the only one, it prints an error message and kills Emacs. */
11344 x_error_quitter (display
, error
)
11346 XErrorEvent
*error
;
11348 char buf
[256], buf1
[356];
11350 /* Note that there is no real way portable across R3/R4 to get the
11351 original error handler. */
11353 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
11354 sprintf (buf1
, "X protocol error: %s on protocol request %d",
11355 buf
, error
->request_code
);
11356 x_connection_closed (display
, buf1
);
11359 /* This is the first-level handler for X protocol errors.
11360 It calls x_error_quitter or x_error_catcher. */
11363 x_error_handler (display
, error
)
11365 XErrorEvent
*error
;
11367 if (! NILP (x_error_message_string
))
11368 x_error_catcher (display
, error
);
11370 x_error_quitter (display
, error
);
11374 /* This is the handler for X IO errors, always.
11375 It kills all frames on the display that we lost touch with.
11376 If that was the only one, it prints an error message and kills Emacs. */
11379 x_io_error_quitter (display
)
11384 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
11385 x_connection_closed (display
, buf
);
11389 /* Changing the font of the frame. */
11391 /* Give frame F the font named FONTNAME as its default font, and
11392 return the full name of that font. FONTNAME may be a wildcard
11393 pattern; in that case, we choose some font that fits the pattern.
11394 The return value shows which font we chose. */
11397 x_new_font (f
, fontname
)
11399 register char *fontname
;
11401 struct font_info
*fontp
11402 = FS_LOAD_FONT (f
, 0, fontname
, -1);
11407 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
11408 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
11409 f
->output_data
.x
->fontset
= -1;
11411 /* Compute the scroll bar width in character columns. */
11412 if (f
->scroll_bar_pixel_width
> 0)
11414 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
11415 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
11419 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
11420 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
11423 /* Now make the frame display the given font. */
11424 if (FRAME_X_WINDOW (f
) != 0)
11426 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
11427 f
->output_data
.x
->font
->fid
);
11428 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
11429 f
->output_data
.x
->font
->fid
);
11430 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
11431 f
->output_data
.x
->font
->fid
);
11433 frame_update_line_height (f
);
11434 x_set_window_size (f
, 0, f
->width
, f
->height
);
11437 /* If we are setting a new frame's font for the first time,
11438 there are no faces yet, so this font's height is the line height. */
11439 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
11441 return build_string (fontp
->full_name
);
11444 /* Give frame F the fontset named FONTSETNAME as its default font, and
11445 return the full name of that fontset. FONTSETNAME may be a wildcard
11446 pattern; in that case, we choose some fontset that fits the pattern.
11447 The return value shows which fontset we chose. */
11450 x_new_fontset (f
, fontsetname
)
11454 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
11455 Lisp_Object result
;
11460 if (f
->output_data
.x
->fontset
== fontset
)
11461 /* This fontset is already set in frame F. There's nothing more
11463 return fontset_name (fontset
);
11465 result
= x_new_font (f
, (XSTRING (fontset_ascii (fontset
))->data
));
11467 if (!STRINGP (result
))
11468 /* Can't load ASCII font. */
11471 /* Since x_new_font doesn't update any fontset information, do it now. */
11472 f
->output_data
.x
->fontset
= fontset
;
11476 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
11477 xic_set_xfontset (f
, XSTRING (fontset_ascii (fontset
))->data
);
11480 return build_string (fontsetname
);
11484 /***********************************************************************
11486 ***********************************************************************/
11492 /* XIM destroy callback function, which is called whenever the
11493 connection to input method XIM dies. CLIENT_DATA contains a
11494 pointer to the x_display_info structure corresponding to XIM. */
11497 xim_destroy_callback (xim
, client_data
, call_data
)
11499 XPointer client_data
;
11500 XPointer call_data
;
11502 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
11503 Lisp_Object frame
, tail
;
11507 /* No need to call XDestroyIC.. */
11508 FOR_EACH_FRAME (tail
, frame
)
11510 struct frame
*f
= XFRAME (frame
);
11511 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
11513 FRAME_XIC (f
) = NULL
;
11514 if (FRAME_XIC_FONTSET (f
))
11516 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
11517 FRAME_XIC_FONTSET (f
) = NULL
;
11522 /* No need to call XCloseIM. */
11523 dpyinfo
->xim
= NULL
;
11524 XFree (dpyinfo
->xim_styles
);
11528 #endif /* HAVE_X11R6 */
11530 /* Open the connection to the XIM server on display DPYINFO.
11531 RESOURCE_NAME is the resource name Emacs uses. */
11534 xim_open_dpy (dpyinfo
, resource_name
)
11535 struct x_display_info
*dpyinfo
;
11536 char *resource_name
;
11541 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
, EMACS_CLASS
);
11542 dpyinfo
->xim
= xim
;
11547 XIMCallback destroy
;
11550 /* Get supported styles and XIM values. */
11551 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
11554 destroy
.callback
= xim_destroy_callback
;
11555 destroy
.client_data
= (XPointer
)dpyinfo
;
11556 /* This isn't prptotyped in OSF 5.0. */
11557 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
11561 #else /* not USE_XIM */
11562 dpyinfo
->xim
= NULL
;
11563 #endif /* not USE_XIM */
11567 #ifdef HAVE_X11R6_XIM
11571 struct x_display_info
*dpyinfo
;
11572 char *resource_name
;
11575 /* XIM instantiate callback function, which is called whenever an XIM
11576 server is available. DISPLAY is teh display of the XIM.
11577 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11578 when the callback was registered. */
11581 xim_instantiate_callback (display
, client_data
, call_data
)
11583 XPointer client_data
;
11584 XPointer call_data
;
11586 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
11587 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
11589 /* We don't support multiple XIM connections. */
11593 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
11595 /* Create XIC for the existing frames on the same display, as long
11596 as they have no XIC. */
11597 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
11599 Lisp_Object tail
, frame
;
11602 FOR_EACH_FRAME (tail
, frame
)
11604 struct frame
*f
= XFRAME (frame
);
11606 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
11607 if (FRAME_XIC (f
) == NULL
)
11609 create_frame_xic (f
);
11610 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
11611 xic_set_statusarea (f
);
11612 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
11614 struct window
*w
= XWINDOW (f
->selected_window
);
11615 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
11624 #endif /* HAVE_X11R6_XIM */
11627 /* Open a connection to the XIM server on display DPYINFO.
11628 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11629 connection only at the first time. On X11R6, open the connection
11630 in the XIM instantiate callback function. */
11633 xim_initialize (dpyinfo
, resource_name
)
11634 struct x_display_info
*dpyinfo
;
11635 char *resource_name
;
11638 #ifdef HAVE_X11R6_XIM
11639 struct xim_inst_t
*xim_inst
;
11642 dpyinfo
->xim
= NULL
;
11643 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
11644 xim_inst
->dpyinfo
= dpyinfo
;
11645 len
= strlen (resource_name
);
11646 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
11647 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
11648 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
11649 resource_name
, EMACS_CLASS
,
11650 xim_instantiate_callback
,
11651 /* Fixme: This is XPointer in
11652 XFree86 but (XPointer *) on
11653 Tru64, at least. */
11654 (XPointer
) xim_inst
);
11655 #else /* not HAVE_X11R6_XIM */
11656 dpyinfo
->xim
= NULL
;
11657 xim_open_dpy (dpyinfo
, resource_name
);
11658 #endif /* not HAVE_X11R6_XIM */
11660 #else /* not USE_XIM */
11661 dpyinfo
->xim
= NULL
;
11662 #endif /* not USE_XIM */
11666 /* Close the connection to the XIM server on display DPYINFO. */
11669 xim_close_dpy (dpyinfo
)
11670 struct x_display_info
*dpyinfo
;
11673 #ifdef HAVE_X11R6_XIM
11674 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
11676 xim_instantiate_callback
, NULL
);
11677 #endif /* not HAVE_X11R6_XIM */
11678 XCloseIM (dpyinfo
->xim
);
11679 dpyinfo
->xim
= NULL
;
11680 XFree (dpyinfo
->xim_styles
);
11681 #endif /* USE_XIM */
11684 #endif /* not HAVE_X11R6_XIM */
11688 /* Calculate the absolute position in frame F
11689 from its current recorded position values and gravity. */
11692 x_calc_absolute_position (f
)
11696 int win_x
= 0, win_y
= 0;
11697 int flags
= f
->output_data
.x
->size_hint_flags
;
11700 /* We have nothing to do if the current position
11701 is already for the top-left corner. */
11702 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
11705 #ifdef USE_X_TOOLKIT
11706 this_window
= XtWindow (f
->output_data
.x
->widget
);
11708 this_window
= FRAME_X_WINDOW (f
);
11711 /* Find the position of the outside upper-left corner of
11712 the inner window, with respect to the outer window.
11713 But do this only if we will need the results. */
11714 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
11719 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
11722 x_clear_errors (FRAME_X_DISPLAY (f
));
11723 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
11725 /* From-window, to-window. */
11727 f
->output_data
.x
->parent_desc
,
11729 /* From-position, to-position. */
11730 0, 0, &win_x
, &win_y
,
11732 /* Child of win. */
11734 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
11736 Window newroot
, newparent
= 0xdeadbeef;
11737 Window
*newchildren
;
11738 unsigned int nchildren
;
11740 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
11741 &newparent
, &newchildren
, &nchildren
))
11744 XFree ((char *) newchildren
);
11746 f
->output_data
.x
->parent_desc
= newparent
;
11752 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
11756 /* Treat negative positions as relative to the leftmost bottommost
11757 position that fits on the screen. */
11758 if (flags
& XNegative
)
11759 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
11760 - 2 * f
->output_data
.x
->border_width
- win_x
11762 + f
->output_data
.x
->left_pos
);
11764 if (flags
& YNegative
)
11766 int menubar_height
= 0;
11768 #ifdef USE_X_TOOLKIT
11769 if (f
->output_data
.x
->menubar_widget
)
11771 = (f
->output_data
.x
->menubar_widget
->core
.height
11772 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
11775 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
11776 - 2 * f
->output_data
.x
->border_width
11780 + f
->output_data
.x
->top_pos
);
11783 /* The left_pos and top_pos
11784 are now relative to the top and left screen edges,
11785 so the flags should correspond. */
11786 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11789 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11790 to really change the position, and 0 when calling from
11791 x_make_frame_visible (in that case, XOFF and YOFF are the current
11792 position values). It is -1 when calling from x_set_frame_parameters,
11793 which means, do adjust for borders but don't change the gravity. */
11796 x_set_offset (f
, xoff
, yoff
, change_gravity
)
11798 register int xoff
, yoff
;
11799 int change_gravity
;
11801 int modified_top
, modified_left
;
11803 if (change_gravity
> 0)
11805 f
->output_data
.x
->top_pos
= yoff
;
11806 f
->output_data
.x
->left_pos
= xoff
;
11807 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11809 f
->output_data
.x
->size_hint_flags
|= XNegative
;
11811 f
->output_data
.x
->size_hint_flags
|= YNegative
;
11812 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11814 x_calc_absolute_position (f
);
11817 x_wm_set_size_hint (f
, (long) 0, 0);
11819 modified_left
= f
->output_data
.x
->left_pos
;
11820 modified_top
= f
->output_data
.x
->top_pos
;
11821 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11822 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11823 /* It is a mystery why we need to add the border_width here
11824 when the frame is already visible, but experiment says we do. */
11825 if (change_gravity
!= 0)
11827 modified_left
+= f
->output_data
.x
->border_width
;
11828 modified_top
+= f
->output_data
.x
->border_width
;
11832 #ifdef USE_X_TOOLKIT
11833 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11834 modified_left
, modified_top
);
11835 #else /* not USE_X_TOOLKIT */
11836 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11837 modified_left
, modified_top
);
11838 #endif /* not USE_X_TOOLKIT */
11842 /* Call this to change the size of frame F's x-window.
11843 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11844 for this size change and subsequent size changes.
11845 Otherwise we leave the window gravity unchanged. */
11848 x_set_window_size (f
, change_gravity
, cols
, rows
)
11850 int change_gravity
;
11853 #ifndef USE_X_TOOLKIT
11854 int pixelwidth
, pixelheight
;
11859 #ifdef USE_X_TOOLKIT
11861 /* The x and y position of the widget is clobbered by the
11862 call to XtSetValues within EmacsFrameSetCharSize.
11863 This is a real kludge, but I don't understand Xt so I can't
11864 figure out a correct fix. Can anyone else tell me? -- rms. */
11865 int xpos
= f
->output_data
.x
->widget
->core
.x
;
11866 int ypos
= f
->output_data
.x
->widget
->core
.y
;
11867 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
11868 f
->output_data
.x
->widget
->core
.x
= xpos
;
11869 f
->output_data
.x
->widget
->core
.y
= ypos
;
11872 #else /* not USE_X_TOOLKIT */
11874 check_frame_size (f
, &rows
, &cols
);
11875 f
->output_data
.x
->vertical_scroll_bar_extra
11876 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
11878 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
11879 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
11880 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
11881 f
->output_data
.x
->flags_areas_extra
11882 = FRAME_FLAGS_AREA_WIDTH (f
);
11883 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
11884 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
11886 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11887 x_wm_set_size_hint (f
, (long) 0, 0);
11889 XSync (FRAME_X_DISPLAY (f
), False
);
11890 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11891 pixelwidth
, pixelheight
);
11893 /* Now, strictly speaking, we can't be sure that this is accurate,
11894 but the window manager will get around to dealing with the size
11895 change request eventually, and we'll hear how it went when the
11896 ConfigureNotify event gets here.
11898 We could just not bother storing any of this information here,
11899 and let the ConfigureNotify event set everything up, but that
11900 might be kind of confusing to the Lisp code, since size changes
11901 wouldn't be reported in the frame parameters until some random
11902 point in the future when the ConfigureNotify event arrives.
11904 We pass 1 for DELAY since we can't run Lisp code inside of
11906 change_frame_size (f
, rows
, cols
, 0, 1, 0);
11907 PIXEL_WIDTH (f
) = pixelwidth
;
11908 PIXEL_HEIGHT (f
) = pixelheight
;
11910 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11911 receive in the ConfigureNotify event; if we get what we asked
11912 for, then the event won't cause the screen to become garbaged, so
11913 we have to make sure to do it here. */
11914 SET_FRAME_GARBAGED (f
);
11916 XFlush (FRAME_X_DISPLAY (f
));
11918 #endif /* not USE_X_TOOLKIT */
11920 /* If cursor was outside the new size, mark it as off. */
11921 mark_window_cursors_off (XWINDOW (f
->root_window
));
11923 /* Clear out any recollection of where the mouse highlighting was,
11924 since it might be in a place that's outside the new frame size.
11925 Actually checking whether it is outside is a pain in the neck,
11926 so don't try--just let the highlighting be done afresh with new size. */
11927 cancel_mouse_face (f
);
11932 /* Mouse warping. */
11935 x_set_mouse_position (f
, x
, y
)
11941 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
11942 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
11944 if (pix_x
< 0) pix_x
= 0;
11945 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
11947 if (pix_y
< 0) pix_y
= 0;
11948 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
11952 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11953 0, 0, 0, 0, pix_x
, pix_y
);
11957 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11960 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
11966 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11967 0, 0, 0, 0, pix_x
, pix_y
);
11971 /* focus shifting, raising and lowering. */
11974 x_focus_on_frame (f
)
11977 #if 0 /* This proves to be unpleasant. */
11981 /* I don't think that the ICCCM allows programs to do things like this
11982 without the interaction of the window manager. Whatever you end up
11983 doing with this code, do it to x_unfocus_frame too. */
11984 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11985 RevertToPointerRoot
, CurrentTime
);
11990 x_unfocus_frame (f
)
11994 /* Look at the remarks in x_focus_on_frame. */
11995 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
11996 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
11997 RevertToPointerRoot
, CurrentTime
);
12001 /* Raise frame F. */
12007 if (f
->async_visible
)
12010 #ifdef USE_X_TOOLKIT
12011 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
12012 #else /* not USE_X_TOOLKIT */
12013 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12014 #endif /* not USE_X_TOOLKIT */
12015 XFlush (FRAME_X_DISPLAY (f
));
12020 /* Lower frame F. */
12026 if (f
->async_visible
)
12029 #ifdef USE_X_TOOLKIT
12030 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
12031 #else /* not USE_X_TOOLKIT */
12032 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12033 #endif /* not USE_X_TOOLKIT */
12034 XFlush (FRAME_X_DISPLAY (f
));
12040 XTframe_raise_lower (f
, raise_flag
)
12050 /* Change of visibility. */
12052 /* This tries to wait until the frame is really visible.
12053 However, if the window manager asks the user where to position
12054 the frame, this will return before the user finishes doing that.
12055 The frame will not actually be visible at that time,
12056 but it will become visible later when the window manager
12057 finishes with it. */
12060 x_make_frame_visible (f
)
12064 int original_top
, original_left
;
12065 int retry_count
= 2;
12071 type
= x_icon_type (f
);
12073 x_bitmap_icon (f
, type
);
12075 if (! FRAME_VISIBLE_P (f
))
12077 /* We test FRAME_GARBAGED_P here to make sure we don't
12078 call x_set_offset a second time
12079 if we get to x_make_frame_visible a second time
12080 before the window gets really visible. */
12081 if (! FRAME_ICONIFIED_P (f
)
12082 && ! f
->output_data
.x
->asked_for_visible
)
12083 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
12085 f
->output_data
.x
->asked_for_visible
= 1;
12087 if (! EQ (Vx_no_window_manager
, Qt
))
12088 x_wm_set_window_state (f
, NormalState
);
12089 #ifdef USE_X_TOOLKIT
12090 /* This was XtPopup, but that did nothing for an iconified frame. */
12091 XtMapWidget (f
->output_data
.x
->widget
);
12092 #else /* not USE_X_TOOLKIT */
12093 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12094 #endif /* not USE_X_TOOLKIT */
12095 #if 0 /* This seems to bring back scroll bars in the wrong places
12096 if the window configuration has changed. They seem
12097 to come back ok without this. */
12098 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
12099 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12103 XFlush (FRAME_X_DISPLAY (f
));
12105 /* Synchronize to ensure Emacs knows the frame is visible
12106 before we do anything else. We do this loop with input not blocked
12107 so that incoming events are handled. */
12111 /* This must be before UNBLOCK_INPUT
12112 since events that arrive in response to the actions above
12113 will set it when they are handled. */
12114 int previously_visible
= f
->output_data
.x
->has_been_visible
;
12116 original_left
= f
->output_data
.x
->left_pos
;
12117 original_top
= f
->output_data
.x
->top_pos
;
12119 /* This must come after we set COUNT. */
12122 /* We unblock here so that arriving X events are processed. */
12124 /* Now move the window back to where it was "supposed to be".
12125 But don't do it if the gravity is negative.
12126 When the gravity is negative, this uses a position
12127 that is 3 pixels too low. Perhaps that's really the border width.
12129 Don't do this if the window has never been visible before,
12130 because the window manager may choose the position
12131 and we don't want to override it. */
12133 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
12134 && f
->output_data
.x
->win_gravity
== NorthWestGravity
12135 && previously_visible
)
12139 unsigned int width
, height
, border
, depth
;
12143 /* On some window managers (such as FVWM) moving an existing
12144 window, even to the same place, causes the window manager
12145 to introduce an offset. This can cause the window to move
12146 to an unexpected location. Check the geometry (a little
12147 slow here) and then verify that the window is in the right
12148 place. If the window is not in the right place, move it
12149 there, and take the potential window manager hit. */
12150 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
12151 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
12153 if (original_left
!= x
|| original_top
!= y
)
12154 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
12155 original_left
, original_top
);
12160 XSETFRAME (frame
, f
);
12162 /* Wait until the frame is visible. Process X events until a
12163 MapNotify event has been seen, or until we think we won't get a
12164 MapNotify at all.. */
12165 for (count
= input_signal_count
+ 10;
12166 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
12168 /* Force processing of queued events. */
12171 /* Machines that do polling rather than SIGIO have been
12172 observed to go into a busy-wait here. So we'll fake an
12173 alarm signal to let the handler know that there's something
12174 to be read. We used to raise a real alarm, but it seems
12175 that the handler isn't always enabled here. This is
12177 if (input_polling_used ())
12179 /* It could be confusing if a real alarm arrives while
12180 processing the fake one. Turn it off and let the
12181 handler reset it. */
12182 extern void poll_for_input_1
P_ ((void));
12183 int old_poll_suppress_count
= poll_suppress_count
;
12184 poll_suppress_count
= 1;
12185 poll_for_input_1 ();
12186 poll_suppress_count
= old_poll_suppress_count
;
12189 /* See if a MapNotify event has been processed. */
12190 FRAME_SAMPLE_VISIBILITY (f
);
12195 (let ((f (selected-frame)))
12199 the frame is not raised with various window managers on
12200 FreeBSD, Linux and Solaris. It turns out that, for some
12201 unknown reason, the call to XtMapWidget is completely ignored.
12202 Mapping the widget a second time works. */
12204 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
12209 /* Change from mapped state to withdrawn state. */
12211 /* Make the frame visible (mapped and not iconified). */
12214 x_make_frame_invisible (f
)
12219 #ifdef USE_X_TOOLKIT
12220 /* Use the frame's outermost window, not the one we normally draw on. */
12221 window
= XtWindow (f
->output_data
.x
->widget
);
12222 #else /* not USE_X_TOOLKIT */
12223 window
= FRAME_X_WINDOW (f
);
12224 #endif /* not USE_X_TOOLKIT */
12226 /* Don't keep the highlight on an invisible frame. */
12227 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
12228 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
12230 #if 0/* This might add unreliability; I don't trust it -- rms. */
12231 if (! f
->async_visible
&& ! f
->async_iconified
)
12237 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12238 that the current position of the window is user-specified, rather than
12239 program-specified, so that when the window is mapped again, it will be
12240 placed at the same location, without forcing the user to position it
12241 by hand again (they have already done that once for this window.) */
12242 x_wm_set_size_hint (f
, (long) 0, 1);
12246 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
12247 DefaultScreen (FRAME_X_DISPLAY (f
))))
12249 UNBLOCK_INPUT_RESIGNAL
;
12250 error ("Can't notify window manager of window withdrawal");
12252 #else /* ! defined (HAVE_X11R4) */
12254 /* Tell the window manager what we're going to do. */
12255 if (! EQ (Vx_no_window_manager
, Qt
))
12259 unmap
.xunmap
.type
= UnmapNotify
;
12260 unmap
.xunmap
.window
= window
;
12261 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
12262 unmap
.xunmap
.from_configure
= False
;
12263 if (! XSendEvent (FRAME_X_DISPLAY (f
),
12264 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
12266 SubstructureRedirectMaskSubstructureNotifyMask
,
12269 UNBLOCK_INPUT_RESIGNAL
;
12270 error ("Can't notify window manager of withdrawal");
12274 /* Unmap the window ourselves. Cheeky! */
12275 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
12276 #endif /* ! defined (HAVE_X11R4) */
12278 /* We can't distinguish this from iconification
12279 just by the event that we get from the server.
12280 So we can't win using the usual strategy of letting
12281 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12282 and synchronize with the server to make sure we agree. */
12284 FRAME_ICONIFIED_P (f
) = 0;
12285 f
->async_visible
= 0;
12286 f
->async_iconified
= 0;
12293 /* Change window state from mapped to iconified. */
12296 x_iconify_frame (f
)
12302 /* Don't keep the highlight on an invisible frame. */
12303 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
12304 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
12306 if (f
->async_iconified
)
12311 FRAME_SAMPLE_VISIBILITY (f
);
12313 type
= x_icon_type (f
);
12315 x_bitmap_icon (f
, type
);
12317 #ifdef USE_X_TOOLKIT
12319 if (! FRAME_VISIBLE_P (f
))
12321 if (! EQ (Vx_no_window_manager
, Qt
))
12322 x_wm_set_window_state (f
, IconicState
);
12323 /* This was XtPopup, but that did nothing for an iconified frame. */
12324 XtMapWidget (f
->output_data
.x
->widget
);
12325 /* The server won't give us any event to indicate
12326 that an invisible frame was changed to an icon,
12327 so we have to record it here. */
12330 f
->async_iconified
= 1;
12331 f
->async_visible
= 0;
12336 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
12337 XtWindow (f
->output_data
.x
->widget
),
12338 DefaultScreen (FRAME_X_DISPLAY (f
)));
12342 error ("Can't notify window manager of iconification");
12344 f
->async_iconified
= 1;
12345 f
->async_visible
= 0;
12349 XFlush (FRAME_X_DISPLAY (f
));
12351 #else /* not USE_X_TOOLKIT */
12353 /* Make sure the X server knows where the window should be positioned,
12354 in case the user deiconifies with the window manager. */
12355 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
12356 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
12358 /* Since we don't know which revision of X we're running, we'll use both
12359 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12361 /* X11R4: send a ClientMessage to the window manager using the
12362 WM_CHANGE_STATE type. */
12366 message
.xclient
.window
= FRAME_X_WINDOW (f
);
12367 message
.xclient
.type
= ClientMessage
;
12368 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
12369 message
.xclient
.format
= 32;
12370 message
.xclient
.data
.l
[0] = IconicState
;
12372 if (! XSendEvent (FRAME_X_DISPLAY (f
),
12373 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
12375 SubstructureRedirectMask
| SubstructureNotifyMask
,
12378 UNBLOCK_INPUT_RESIGNAL
;
12379 error ("Can't notify window manager of iconification");
12383 /* X11R3: set the initial_state field of the window manager hints to
12385 x_wm_set_window_state (f
, IconicState
);
12387 if (!FRAME_VISIBLE_P (f
))
12389 /* If the frame was withdrawn, before, we must map it. */
12390 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12393 f
->async_iconified
= 1;
12394 f
->async_visible
= 0;
12396 XFlush (FRAME_X_DISPLAY (f
));
12398 #endif /* not USE_X_TOOLKIT */
12401 /* Destroy the X window of frame F. */
12404 x_destroy_window (f
)
12407 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12411 /* If a display connection is dead, don't try sending more
12412 commands to the X server. */
12413 if (dpyinfo
->display
!= 0)
12415 if (f
->output_data
.x
->icon_desc
!= 0)
12416 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
12419 free_frame_xic (f
);
12421 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
12422 #ifdef USE_X_TOOLKIT
12423 if (f
->output_data
.x
->widget
)
12424 XtDestroyWidget (f
->output_data
.x
->widget
);
12425 free_frame_menubar (f
);
12426 #endif /* USE_X_TOOLKIT */
12428 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
12429 unload_color (f
, f
->output_data
.x
->background_pixel
);
12430 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
12431 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
12432 unload_color (f
, f
->output_data
.x
->border_pixel
);
12433 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
12434 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
12435 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
12436 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
12437 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
12438 if (f
->output_data
.x
->white_relief
.allocated_p
)
12439 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
12440 if (f
->output_data
.x
->black_relief
.allocated_p
)
12441 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
12443 free_frame_faces (f
);
12444 XFlush (FRAME_X_DISPLAY (f
));
12447 if (f
->output_data
.x
->saved_menu_event
)
12448 xfree (f
->output_data
.x
->saved_menu_event
);
12450 xfree (f
->output_data
.x
);
12451 f
->output_data
.x
= 0;
12452 if (f
== dpyinfo
->x_focus_frame
)
12453 dpyinfo
->x_focus_frame
= 0;
12454 if (f
== dpyinfo
->x_focus_event_frame
)
12455 dpyinfo
->x_focus_event_frame
= 0;
12456 if (f
== dpyinfo
->x_highlight_frame
)
12457 dpyinfo
->x_highlight_frame
= 0;
12459 dpyinfo
->reference_count
--;
12461 if (f
== dpyinfo
->mouse_face_mouse_frame
)
12463 dpyinfo
->mouse_face_beg_row
12464 = dpyinfo
->mouse_face_beg_col
= -1;
12465 dpyinfo
->mouse_face_end_row
12466 = dpyinfo
->mouse_face_end_col
= -1;
12467 dpyinfo
->mouse_face_window
= Qnil
;
12468 dpyinfo
->mouse_face_deferred_gc
= 0;
12469 dpyinfo
->mouse_face_mouse_frame
= 0;
12475 /* Setting window manager hints. */
12477 /* Set the normal size hints for the window manager, for frame F.
12478 FLAGS is the flags word to use--or 0 meaning preserve the flags
12479 that the window now has.
12480 If USER_POSITION is nonzero, we set the USPosition
12481 flag (this is useful when FLAGS is 0). */
12484 x_wm_set_size_hint (f
, flags
, user_position
)
12489 XSizeHints size_hints
;
12491 #ifdef USE_X_TOOLKIT
12494 Dimension widget_width
, widget_height
;
12495 Window window
= XtWindow (f
->output_data
.x
->widget
);
12496 #else /* not USE_X_TOOLKIT */
12497 Window window
= FRAME_X_WINDOW (f
);
12498 #endif /* not USE_X_TOOLKIT */
12500 /* Setting PMaxSize caused various problems. */
12501 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
12503 size_hints
.x
= f
->output_data
.x
->left_pos
;
12504 size_hints
.y
= f
->output_data
.x
->top_pos
;
12506 #ifdef USE_X_TOOLKIT
12507 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
12508 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
12509 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
12510 size_hints
.height
= widget_height
;
12511 size_hints
.width
= widget_width
;
12512 #else /* not USE_X_TOOLKIT */
12513 size_hints
.height
= PIXEL_HEIGHT (f
);
12514 size_hints
.width
= PIXEL_WIDTH (f
);
12515 #endif /* not USE_X_TOOLKIT */
12517 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
12518 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
12519 size_hints
.max_width
12520 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
12521 size_hints
.max_height
12522 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
12524 /* Calculate the base and minimum sizes.
12526 (When we use the X toolkit, we don't do it here.
12527 Instead we copy the values that the widgets are using, below.) */
12528 #ifndef USE_X_TOOLKIT
12530 int base_width
, base_height
;
12531 int min_rows
= 0, min_cols
= 0;
12533 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
12534 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
12536 check_frame_size (f
, &min_rows
, &min_cols
);
12538 /* The window manager uses the base width hints to calculate the
12539 current number of rows and columns in the frame while
12540 resizing; min_width and min_height aren't useful for this
12541 purpose, since they might not give the dimensions for a
12542 zero-row, zero-column frame.
12544 We use the base_width and base_height members if we have
12545 them; otherwise, we set the min_width and min_height members
12546 to the size for a zero x zero frame. */
12549 size_hints
.flags
|= PBaseSize
;
12550 size_hints
.base_width
= base_width
;
12551 size_hints
.base_height
= base_height
;
12552 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
12553 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
12555 size_hints
.min_width
= base_width
;
12556 size_hints
.min_height
= base_height
;
12560 /* If we don't need the old flags, we don't need the old hint at all. */
12563 size_hints
.flags
|= flags
;
12566 #endif /* not USE_X_TOOLKIT */
12569 XSizeHints hints
; /* Sometimes I hate X Windows... */
12570 long supplied_return
;
12574 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
12577 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
12580 #ifdef USE_X_TOOLKIT
12581 size_hints
.base_height
= hints
.base_height
;
12582 size_hints
.base_width
= hints
.base_width
;
12583 size_hints
.min_height
= hints
.min_height
;
12584 size_hints
.min_width
= hints
.min_width
;
12588 size_hints
.flags
|= flags
;
12593 if (hints
.flags
& PSize
)
12594 size_hints
.flags
|= PSize
;
12595 if (hints
.flags
& PPosition
)
12596 size_hints
.flags
|= PPosition
;
12597 if (hints
.flags
& USPosition
)
12598 size_hints
.flags
|= USPosition
;
12599 if (hints
.flags
& USSize
)
12600 size_hints
.flags
|= USSize
;
12604 #ifndef USE_X_TOOLKIT
12609 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
12610 size_hints
.flags
|= PWinGravity
;
12614 size_hints
.flags
&= ~ PPosition
;
12615 size_hints
.flags
|= USPosition
;
12617 #endif /* PWinGravity */
12620 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
12622 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
12626 /* Used for IconicState or NormalState */
12629 x_wm_set_window_state (f
, state
)
12633 #ifdef USE_X_TOOLKIT
12636 XtSetArg (al
[0], XtNinitialState
, state
);
12637 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
12638 #else /* not USE_X_TOOLKIT */
12639 Window window
= FRAME_X_WINDOW (f
);
12641 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
12642 f
->output_data
.x
->wm_hints
.initial_state
= state
;
12644 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12645 #endif /* not USE_X_TOOLKIT */
12649 x_wm_set_icon_pixmap (f
, pixmap_id
)
12653 Pixmap icon_pixmap
;
12655 #ifndef USE_X_TOOLKIT
12656 Window window
= FRAME_X_WINDOW (f
);
12661 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
12662 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
12666 /* It seems there is no way to turn off use of an icon pixmap.
12667 The following line does it, only if no icon has yet been created,
12668 for some window managers. But with mwm it crashes.
12669 Some people say it should clear the IconPixmapHint bit in this case,
12670 but that doesn't work, and the X consortium said it isn't the
12671 right thing at all. Since there is no way to win,
12672 best to explicitly give up. */
12674 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
12680 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12684 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
12685 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
12688 #else /* not USE_X_TOOLKIT */
12690 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
12691 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12693 #endif /* not USE_X_TOOLKIT */
12697 x_wm_set_icon_position (f
, icon_x
, icon_y
)
12699 int icon_x
, icon_y
;
12701 #ifdef USE_X_TOOLKIT
12702 Window window
= XtWindow (f
->output_data
.x
->widget
);
12704 Window window
= FRAME_X_WINDOW (f
);
12707 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
12708 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
12709 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
12711 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12715 /***********************************************************************
12717 ***********************************************************************/
12719 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12722 x_get_font_info (f
, font_idx
)
12726 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
12730 /* Return a list of names of available fonts matching PATTERN on frame
12731 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12732 to be listed. Frame F NULL means we have not yet created any
12733 frame on X, and consult the first display in x_display_list.
12734 MAXNAMES sets a limit on how many fonts to match. */
12737 x_list_fonts (f
, pattern
, size
, maxnames
)
12739 Lisp_Object pattern
;
12743 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
12744 Lisp_Object tem
, second_best
;
12745 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
12746 int try_XLoadQueryFont
= 0;
12749 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
12750 if (NILP (patterns
))
12751 patterns
= Fcons (pattern
, Qnil
);
12753 if (maxnames
== 1 && !size
)
12754 /* We can return any single font matching PATTERN. */
12755 try_XLoadQueryFont
= 1;
12757 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
12760 char **names
= NULL
;
12762 pattern
= XCAR (patterns
);
12763 /* See if we cached the result for this particular query.
12764 The cache is an alist of the form:
12765 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12767 if (f
&& (tem
= XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
),
12768 key
= Fcons (pattern
, make_number (maxnames
)),
12769 !NILP (list
= Fassoc (key
, tem
))))
12771 list
= Fcdr_safe (list
);
12772 /* We have a cashed list. Don't have to get the list again. */
12776 /* At first, put PATTERN in the cache. */
12779 count
= x_catch_errors (dpy
);
12781 if (try_XLoadQueryFont
)
12784 unsigned long value
;
12786 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
12787 if (x_had_errors_p (dpy
))
12789 /* This error is perhaps due to insufficient memory on X
12790 server. Let's just ignore it. */
12792 x_clear_errors (dpy
);
12796 && XGetFontProperty (font
, XA_FONT
, &value
))
12798 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
12799 int len
= strlen (name
);
12802 /* If DXPC (a Differential X Protocol Compressor)
12803 Ver.3.7 is running, XGetAtomName will return null
12804 string. We must avoid such a name. */
12806 try_XLoadQueryFont
= 0;
12810 names
= (char **) alloca (sizeof (char *));
12811 /* Some systems only allow alloca assigned to a
12813 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
12814 bcopy (name
, names
[0], len
+ 1);
12819 try_XLoadQueryFont
= 0;
12822 XFreeFont (dpy
, font
);
12825 if (!try_XLoadQueryFont
)
12827 /* We try at least 10 fonts because XListFonts will return
12828 auto-scaled fonts at the head. */
12829 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
12831 if (x_had_errors_p (dpy
))
12833 /* This error is perhaps due to insufficient memory on X
12834 server. Let's just ignore it. */
12836 x_clear_errors (dpy
);
12840 x_uncatch_errors (dpy
, count
);
12847 /* Make a list of all the fonts we got back.
12848 Store that in the font cache for the display. */
12849 for (i
= 0; i
< num_fonts
; i
++)
12852 char *p
= names
[i
];
12853 int average_width
= -1, dashes
= 0;
12855 /* Count the number of dashes in NAMES[I]. If there are
12856 14 dashes, and the field value following 12th dash
12857 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12858 is usually too ugly to be used for editing. Let's
12864 if (dashes
== 7) /* PIXEL_SIZE field */
12866 else if (dashes
== 12) /* AVERAGE_WIDTH field */
12867 average_width
= atoi (p
);
12869 if (dashes
< 14 || average_width
!= 0)
12871 tem
= build_string (names
[i
]);
12872 if (NILP (Fassoc (tem
, list
)))
12874 if (STRINGP (Vx_pixel_size_width_font_regexp
)
12875 && ((fast_c_string_match_ignore_case
12876 (Vx_pixel_size_width_font_regexp
, names
[i
]))
12878 /* We can set the value of PIXEL_SIZE to the
12879 width of this font. */
12880 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
12882 /* For the moment, width is not known. */
12883 list
= Fcons (Fcons (tem
, Qnil
), list
);
12887 if (!try_XLoadQueryFont
)
12888 XFreeFontNames (names
);
12891 /* Now store the result in the cache. */
12893 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)
12894 = Fcons (Fcons (key
, list
),
12895 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
12898 if (NILP (list
)) continue; /* Try the remaining alternatives. */
12900 newlist
= second_best
= Qnil
;
12901 /* Make a list of the fonts that have the right width. */
12902 for (; CONSP (list
); list
= XCDR (list
))
12908 if (!CONSP (tem
) || NILP (XCAR (tem
)))
12912 newlist
= Fcons (XCAR (tem
), newlist
);
12916 if (!INTEGERP (XCDR (tem
)))
12918 /* Since we have not yet known the size of this font, we
12919 must try slow function call XLoadQueryFont. */
12920 XFontStruct
*thisinfo
;
12923 count
= x_catch_errors (dpy
);
12924 thisinfo
= XLoadQueryFont (dpy
,
12925 XSTRING (XCAR (tem
))->data
);
12926 if (x_had_errors_p (dpy
))
12928 /* This error is perhaps due to insufficient memory on X
12929 server. Let's just ignore it. */
12931 x_clear_errors (dpy
);
12933 x_uncatch_errors (dpy
, count
);
12939 = (thisinfo
->min_bounds
.width
== 0
12941 : make_number (thisinfo
->max_bounds
.width
));
12942 XFreeFont (dpy
, thisinfo
);
12945 /* For unknown reason, the previous call of XListFont had
12946 returned a font which can't be opened. Record the size
12947 as 0 not to try to open it again. */
12948 XCDR (tem
) = make_number (0);
12951 found_size
= XINT (XCDR (tem
));
12952 if (found_size
== size
)
12953 newlist
= Fcons (XCAR (tem
), newlist
);
12954 else if (found_size
> 0)
12956 if (NILP (second_best
))
12958 else if (found_size
< size
)
12960 if (XINT (XCDR (second_best
)) > size
12961 || XINT (XCDR (second_best
)) < found_size
)
12966 if (XINT (XCDR (second_best
)) > size
12967 && XINT (XCDR (second_best
)) > found_size
)
12972 if (!NILP (newlist
))
12974 else if (!NILP (second_best
))
12976 newlist
= Fcons (XCAR (second_best
), Qnil
);
12987 /* Check that FONT is valid on frame F. It is if it can be found in F's
12991 x_check_font (f
, font
)
12996 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12998 xassert (font
!= NULL
);
13000 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13001 if (dpyinfo
->font_table
[i
].name
13002 && font
== dpyinfo
->font_table
[i
].font
)
13005 xassert (i
< dpyinfo
->n_fonts
);
13008 #endif /* GLYPH_DEBUG != 0 */
13010 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13011 Note: There are (broken) X fonts out there with invalid XFontStruct
13012 min_bounds contents. For example, handa@etl.go.jp reports that
13013 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13014 have font->min_bounds.width == 0. */
13017 x_font_min_bounds (font
, w
, h
)
13021 *h
= FONT_HEIGHT (font
);
13022 *w
= font
->min_bounds
.width
;
13024 /* Try to handle the case where FONT->min_bounds has invalid
13025 contents. Since the only font known to have invalid min_bounds
13026 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13028 *w
= font
->max_bounds
.width
;
13032 /* Compute the smallest character width and smallest font height over
13033 all fonts available on frame F. Set the members smallest_char_width
13034 and smallest_font_height in F's x_display_info structure to
13035 the values computed. Value is non-zero if smallest_font_height or
13036 smallest_char_width become smaller than they were before. */
13039 x_compute_min_glyph_bounds (f
)
13043 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13045 int old_width
= dpyinfo
->smallest_char_width
;
13046 int old_height
= dpyinfo
->smallest_font_height
;
13048 dpyinfo
->smallest_font_height
= 100000;
13049 dpyinfo
->smallest_char_width
= 100000;
13051 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
13052 if (dpyinfo
->font_table
[i
].name
)
13054 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
13057 font
= (XFontStruct
*) fontp
->font
;
13058 xassert (font
!= (XFontStruct
*) ~0);
13059 x_font_min_bounds (font
, &w
, &h
);
13061 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
13062 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
13065 xassert (dpyinfo
->smallest_char_width
> 0
13066 && dpyinfo
->smallest_font_height
> 0);
13068 return (dpyinfo
->n_fonts
== 1
13069 || dpyinfo
->smallest_char_width
< old_width
13070 || dpyinfo
->smallest_font_height
< old_height
);
13074 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13075 pointer to the structure font_info while allocating it dynamically.
13076 If SIZE is 0, load any size of font.
13077 If loading is failed, return NULL. */
13080 x_load_font (f
, fontname
, size
)
13082 register char *fontname
;
13085 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13086 Lisp_Object font_names
;
13089 /* Get a list of all the fonts that match this name. Once we
13090 have a list of matching fonts, we compare them against the fonts
13091 we already have by comparing names. */
13092 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
13094 if (!NILP (font_names
))
13099 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13100 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
13101 if (dpyinfo
->font_table
[i
].name
13102 && (!strcmp (dpyinfo
->font_table
[i
].name
,
13103 XSTRING (XCAR (tail
))->data
)
13104 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
13105 XSTRING (XCAR (tail
))->data
)))
13106 return (dpyinfo
->font_table
+ i
);
13109 /* Load the font and add it to the table. */
13113 struct font_info
*fontp
;
13114 unsigned long value
;
13117 /* If we have found fonts by x_list_font, load one of them. If
13118 not, we still try to load a font by the name given as FONTNAME
13119 because XListFonts (called in x_list_font) of some X server has
13120 a bug of not finding a font even if the font surely exists and
13121 is loadable by XLoadQueryFont. */
13122 if (size
> 0 && !NILP (font_names
))
13123 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
13126 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
13127 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
13128 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
13130 /* This error is perhaps due to insufficient memory on X
13131 server. Let's just ignore it. */
13133 x_clear_errors (FRAME_X_DISPLAY (f
));
13135 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
13140 /* Find a free slot in the font table. */
13141 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
13142 if (dpyinfo
->font_table
[i
].name
== NULL
)
13145 /* If no free slot found, maybe enlarge the font table. */
13146 if (i
== dpyinfo
->n_fonts
13147 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
13150 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
13151 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
13152 dpyinfo
->font_table
13153 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
13156 fontp
= dpyinfo
->font_table
+ i
;
13157 if (i
== dpyinfo
->n_fonts
)
13158 ++dpyinfo
->n_fonts
;
13160 /* Now fill in the slots of *FONTP. */
13162 fontp
->font
= font
;
13163 fontp
->font_idx
= i
;
13164 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
13165 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
13167 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13169 if (XGetFontProperty (font
, XA_FONT
, &value
))
13171 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
13175 /* Count the number of dashes in the "full name".
13176 If it is too few, this isn't really the font's full name,
13178 In X11R4, the fonts did not come with their canonical names
13189 full_name
= (char *) xmalloc (p
- name
+ 1);
13190 bcopy (name
, full_name
, p
- name
+ 1);
13196 if (full_name
!= 0)
13197 fontp
->full_name
= full_name
;
13199 fontp
->full_name
= fontp
->name
;
13201 fontp
->size
= font
->max_bounds
.width
;
13202 fontp
->height
= FONT_HEIGHT (font
);
13204 /* For some font, ascent and descent in max_bounds field is
13205 larger than the above value. */
13206 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
13207 if (max_height
> fontp
->height
)
13208 fontp
->height
= max_height
;
13211 if (NILP (font_names
))
13213 /* We come here because of a bug of XListFonts mentioned at
13214 the head of this block. Let's store this information in
13215 the cache for x_list_fonts. */
13216 Lisp_Object lispy_name
= build_string (fontname
);
13217 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
13219 XCDR (dpyinfo
->name_list_element
)
13220 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
13221 Fcons (Fcons (lispy_full_name
,
13222 make_number (fontp
->size
)),
13224 XCDR (dpyinfo
->name_list_element
));
13226 XCDR (dpyinfo
->name_list_element
)
13227 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
13228 Fcons (Fcons (lispy_full_name
,
13229 make_number (fontp
->size
)),
13231 XCDR (dpyinfo
->name_list_element
));
13234 /* The slot `encoding' specifies how to map a character
13235 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13236 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13237 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13238 2:0xA020..0xFF7F). For the moment, we don't know which charset
13239 uses this font. So, we set information in fontp->encoding[1]
13240 which is never used by any charset. If mapping can't be
13241 decided, set FONT_ENCODING_NOT_DECIDED. */
13243 = (font
->max_byte1
== 0
13245 ? (font
->min_char_or_byte2
< 0x80
13246 ? (font
->max_char_or_byte2
< 0x80
13247 ? 0 /* 0x20..0x7F */
13248 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
13249 : 1) /* 0xA0..0xFF */
13251 : (font
->min_byte1
< 0x80
13252 ? (font
->max_byte1
< 0x80
13253 ? (font
->min_char_or_byte2
< 0x80
13254 ? (font
->max_char_or_byte2
< 0x80
13255 ? 0 /* 0x2020..0x7F7F */
13256 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
13257 : 3) /* 0x20A0..0x7FFF */
13258 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
13259 : (font
->min_char_or_byte2
< 0x80
13260 ? (font
->max_char_or_byte2
< 0x80
13261 ? 2 /* 0xA020..0xFF7F */
13262 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
13263 : 1))); /* 0xA0A0..0xFFFF */
13265 fontp
->baseline_offset
13266 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
13267 ? (long) value
: 0);
13268 fontp
->relative_compose
13269 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
13270 ? (long) value
: 0);
13271 fontp
->default_ascent
13272 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
13273 ? (long) value
: 0);
13275 /* Set global flag fonts_changed_p to non-zero if the font loaded
13276 has a character with a smaller width than any other character
13277 before, or if the font loaded has a smalle>r height than any
13278 other font loaded before. If this happens, it will make a
13279 glyph matrix reallocation necessary. */
13280 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
13287 /* Return a pointer to struct font_info of a font named FONTNAME for
13288 frame F. If no such font is loaded, return NULL. */
13291 x_query_font (f
, fontname
)
13293 register char *fontname
;
13295 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
13298 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
13299 if (dpyinfo
->font_table
[i
].name
13300 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
13301 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
13302 return (dpyinfo
->font_table
+ i
);
13307 /* Find a CCL program for a font specified by FONTP, and set the member
13308 `encoder' of the structure. */
13311 x_find_ccl_program (fontp
)
13312 struct font_info
*fontp
;
13314 Lisp_Object list
, elt
;
13317 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
13321 && STRINGP (XCAR (elt
))
13322 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
13324 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
13331 struct ccl_program
*ccl
13332 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
13334 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
13337 fontp
->font_encoder
= ccl
;
13343 /***********************************************************************
13345 ***********************************************************************/
13347 #ifdef USE_X_TOOLKIT
13348 static XrmOptionDescRec emacs_options
[] = {
13349 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
13350 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
13352 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13353 XrmoptionSepArg
, NULL
},
13354 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
13356 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13357 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13358 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
13359 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13360 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
13361 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
13362 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
13364 #endif /* USE_X_TOOLKIT */
13366 static int x_initialized
;
13368 #ifdef MULTI_KBOARD
13369 /* Test whether two display-name strings agree up to the dot that separates
13370 the screen number from the server number. */
13372 same_x_server (name1
, name2
)
13373 char *name1
, *name2
;
13375 int seen_colon
= 0;
13376 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
13377 int system_name_length
= strlen (system_name
);
13378 int length_until_period
= 0;
13380 while (system_name
[length_until_period
] != 0
13381 && system_name
[length_until_period
] != '.')
13382 length_until_period
++;
13384 /* Treat `unix' like an empty host name. */
13385 if (! strncmp (name1
, "unix:", 5))
13387 if (! strncmp (name2
, "unix:", 5))
13389 /* Treat this host's name like an empty host name. */
13390 if (! strncmp (name1
, system_name
, system_name_length
)
13391 && name1
[system_name_length
] == ':')
13392 name1
+= system_name_length
;
13393 if (! strncmp (name2
, system_name
, system_name_length
)
13394 && name2
[system_name_length
] == ':')
13395 name2
+= system_name_length
;
13396 /* Treat this host's domainless name like an empty host name. */
13397 if (! strncmp (name1
, system_name
, length_until_period
)
13398 && name1
[length_until_period
] == ':')
13399 name1
+= length_until_period
;
13400 if (! strncmp (name2
, system_name
, length_until_period
)
13401 && name2
[length_until_period
] == ':')
13402 name2
+= length_until_period
;
13404 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
13408 if (seen_colon
&& *name1
== '.')
13412 && (*name1
== '.' || *name1
== '\0')
13413 && (*name2
== '.' || *name2
== '\0'));
13417 struct x_display_info
*
13418 x_term_init (display_name
, xrm_option
, resource_name
)
13419 Lisp_Object display_name
;
13421 char *resource_name
;
13425 struct x_display_info
*dpyinfo
;
13430 if (!x_initialized
)
13436 #ifdef USE_X_TOOLKIT
13437 /* weiner@footloose.sps.mot.com reports that this causes
13439 X protocol error: BadAtom (invalid Atom parameter)
13440 on protocol request 18skiloaf.
13441 So let's not use it until R6. */
13442 #ifdef HAVE_X11XTR6
13443 XtSetLanguageProc (NULL
, NULL
, NULL
);
13454 argv
[argc
++] = "-xrm";
13455 argv
[argc
++] = xrm_option
;
13457 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
13458 resource_name
, EMACS_CLASS
,
13459 emacs_options
, XtNumber (emacs_options
),
13462 #ifdef HAVE_X11XTR6
13463 /* I think this is to compensate for XtSetLanguageProc. */
13468 #else /* not USE_X_TOOLKIT */
13470 XSetLocaleModifiers ("");
13472 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
13473 #endif /* not USE_X_TOOLKIT */
13475 /* Detect failure. */
13482 /* We have definitely succeeded. Record the new connection. */
13484 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
13485 bzero (dpyinfo
, sizeof *dpyinfo
);
13487 #ifdef MULTI_KBOARD
13489 struct x_display_info
*share
;
13492 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
13493 share
= share
->next
, tail
= XCDR (tail
))
13494 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
13495 XSTRING (display_name
)->data
))
13498 dpyinfo
->kboard
= share
->kboard
;
13501 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
13502 init_kboard (dpyinfo
->kboard
);
13503 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
13505 char *vendor
= ServerVendor (dpy
);
13507 dpyinfo
->kboard
->Vsystem_key_alist
13508 = call1 (Qvendor_specific_keysyms
,
13509 build_string (vendor
? vendor
: ""));
13513 dpyinfo
->kboard
->next_kboard
= all_kboards
;
13514 all_kboards
= dpyinfo
->kboard
;
13515 /* Don't let the initial kboard remain current longer than necessary.
13516 That would cause problems if a file loaded on startup tries to
13517 prompt in the mini-buffer. */
13518 if (current_kboard
== initial_kboard
)
13519 current_kboard
= dpyinfo
->kboard
;
13521 dpyinfo
->kboard
->reference_count
++;
13525 /* Put this display on the chain. */
13526 dpyinfo
->next
= x_display_list
;
13527 x_display_list
= dpyinfo
;
13529 /* Put it on x_display_name_list as well, to keep them parallel. */
13530 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
13531 x_display_name_list
);
13532 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
13534 dpyinfo
->display
= dpy
;
13537 XSetAfterFunction (x_current_display
, x_trace_wire
);
13541 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
13542 + STRING_BYTES (XSTRING (Vsystem_name
))
13544 sprintf (dpyinfo
->x_id_name
, "%s@%s",
13545 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
13547 /* Figure out which modifier bits mean what. */
13548 x_find_modifier_meanings (dpyinfo
);
13550 /* Get the scroll bar cursor. */
13551 dpyinfo
->vertical_scroll_bar_cursor
13552 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
13554 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
13555 resource_name
, EMACS_CLASS
);
13556 #ifdef HAVE_XRMSETDATABASE
13557 XrmSetDatabase (dpyinfo
->display
, xrdb
);
13559 dpyinfo
->display
->db
= xrdb
;
13561 /* Put the rdb where we can find it in a way that works on
13563 dpyinfo
->xrdb
= xrdb
;
13565 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
13566 DefaultScreen (dpyinfo
->display
));
13567 select_visual (dpyinfo
);
13568 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
13569 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
13570 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
13571 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
13572 dpyinfo
->grabbed
= 0;
13573 dpyinfo
->reference_count
= 0;
13574 dpyinfo
->icon_bitmap_id
= -1;
13575 dpyinfo
->font_table
= NULL
;
13576 dpyinfo
->n_fonts
= 0;
13577 dpyinfo
->font_table_size
= 0;
13578 dpyinfo
->bitmaps
= 0;
13579 dpyinfo
->bitmaps_size
= 0;
13580 dpyinfo
->bitmaps_last
= 0;
13581 dpyinfo
->scratch_cursor_gc
= 0;
13582 dpyinfo
->mouse_face_mouse_frame
= 0;
13583 dpyinfo
->mouse_face_deferred_gc
= 0;
13584 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
13585 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
13586 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
13587 dpyinfo
->mouse_face_window
= Qnil
;
13588 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
13589 dpyinfo
->mouse_face_defer
= 0;
13590 dpyinfo
->x_focus_frame
= 0;
13591 dpyinfo
->x_focus_event_frame
= 0;
13592 dpyinfo
->x_highlight_frame
= 0;
13593 dpyinfo
->image_cache
= make_image_cache ();
13595 /* See if a private colormap is requested. */
13596 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
13598 if (dpyinfo
->visual
->class == PseudoColor
)
13601 value
= display_x_get_resource (dpyinfo
,
13602 build_string ("privateColormap"),
13603 build_string ("PrivateColormap"),
13605 if (STRINGP (value
)
13606 && (!strcmp (XSTRING (value
)->data
, "true")
13607 || !strcmp (XSTRING (value
)->data
, "on")))
13608 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
13612 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
13613 dpyinfo
->visual
, AllocNone
);
13616 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
13617 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
13618 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
13619 dpyinfo
->resy
= pixels
* 25.4 / mm
;
13620 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
13621 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
13622 dpyinfo
->resx
= pixels
* 25.4 / mm
;
13625 dpyinfo
->Xatom_wm_protocols
13626 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
13627 dpyinfo
->Xatom_wm_take_focus
13628 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
13629 dpyinfo
->Xatom_wm_save_yourself
13630 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
13631 dpyinfo
->Xatom_wm_delete_window
13632 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
13633 dpyinfo
->Xatom_wm_change_state
13634 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
13635 dpyinfo
->Xatom_wm_configure_denied
13636 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
13637 dpyinfo
->Xatom_wm_window_moved
13638 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
13639 dpyinfo
->Xatom_editres
13640 = XInternAtom (dpyinfo
->display
, "Editres", False
);
13641 dpyinfo
->Xatom_CLIPBOARD
13642 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
13643 dpyinfo
->Xatom_TIMESTAMP
13644 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
13645 dpyinfo
->Xatom_TEXT
13646 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
13647 dpyinfo
->Xatom_COMPOUND_TEXT
13648 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
13649 dpyinfo
->Xatom_DELETE
13650 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
13651 dpyinfo
->Xatom_MULTIPLE
13652 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
13653 dpyinfo
->Xatom_INCR
13654 = XInternAtom (dpyinfo
->display
, "INCR", False
);
13655 dpyinfo
->Xatom_EMACS_TMP
13656 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
13657 dpyinfo
->Xatom_TARGETS
13658 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
13659 dpyinfo
->Xatom_NULL
13660 = XInternAtom (dpyinfo
->display
, "NULL", False
);
13661 dpyinfo
->Xatom_ATOM_PAIR
13662 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
13663 /* For properties of font. */
13664 dpyinfo
->Xatom_PIXEL_SIZE
13665 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
13666 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
13667 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
13668 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
13669 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
13670 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
13671 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
13673 /* Ghostscript support. */
13674 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
13675 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
13677 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
13680 dpyinfo
->cut_buffers_initialized
= 0;
13682 connection
= ConnectionNumber (dpyinfo
->display
);
13683 dpyinfo
->connection
= connection
;
13688 null_bits
[0] = 0x00;
13690 dpyinfo
->null_pixel
13691 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
13692 null_bits
, 1, 1, (long) 0, (long) 0,
13697 extern int gray_bitmap_width
, gray_bitmap_height
;
13698 extern unsigned char *gray_bitmap_bits
;
13700 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
13702 gray_bitmap_width
, gray_bitmap_height
,
13703 (unsigned long) 1, (unsigned long) 0, 1);
13707 xim_initialize (dpyinfo
, resource_name
);
13710 #ifdef subprocesses
13711 /* This is only needed for distinguishing keyboard and process input. */
13712 if (connection
!= 0)
13713 add_keyboard_wait_descriptor (connection
);
13716 #ifndef F_SETOWN_BUG
13718 #ifdef F_SETOWN_SOCK_NEG
13719 /* stdin is a socket here */
13720 fcntl (connection
, F_SETOWN
, -getpid ());
13721 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13722 fcntl (connection
, F_SETOWN
, getpid ());
13723 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13724 #endif /* ! defined (F_SETOWN) */
13725 #endif /* F_SETOWN_BUG */
13728 if (interrupt_input
)
13729 init_sigio (connection
);
13730 #endif /* ! defined (SIGIO) */
13733 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13734 /* Make sure that we have a valid font for dialog boxes
13735 so that Xt does not crash. */
13737 Display
*dpy
= dpyinfo
->display
;
13738 XrmValue d
, fr
, to
;
13742 d
.addr
= (XPointer
)&dpy
;
13743 d
.size
= sizeof (Display
*);
13744 fr
.addr
= XtDefaultFont
;
13745 fr
.size
= sizeof (XtDefaultFont
);
13746 to
.size
= sizeof (Font
*);
13747 to
.addr
= (XPointer
)&font
;
13748 count
= x_catch_errors (dpy
);
13749 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
13751 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
13752 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
13753 x_uncatch_errors (dpy
, count
);
13758 /* See if we should run in synchronous mode. This is useful
13759 for debugging X code. */
13762 value
= display_x_get_resource (dpyinfo
,
13763 build_string ("synchronous"),
13764 build_string ("Synchronous"),
13766 if (STRINGP (value
)
13767 && (!strcmp (XSTRING (value
)->data
, "true")
13768 || !strcmp (XSTRING (value
)->data
, "on")))
13769 XSynchronize (dpyinfo
->display
, True
);
13777 /* Get rid of display DPYINFO, assuming all frames are already gone,
13778 and without sending any more commands to the X server. */
13781 x_delete_display (dpyinfo
)
13782 struct x_display_info
*dpyinfo
;
13784 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
13786 /* Discard this display from x_display_name_list and x_display_list.
13787 We can't use Fdelq because that can quit. */
13788 if (! NILP (x_display_name_list
)
13789 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
13790 x_display_name_list
= XCDR (x_display_name_list
);
13795 tail
= x_display_name_list
;
13796 while (CONSP (tail
) && CONSP (XCDR (tail
)))
13798 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
13800 XCDR (tail
) = XCDR (XCDR (tail
));
13803 tail
= XCDR (tail
);
13807 if (next_noop_dpyinfo
== dpyinfo
)
13808 next_noop_dpyinfo
= dpyinfo
->next
;
13810 if (x_display_list
== dpyinfo
)
13811 x_display_list
= dpyinfo
->next
;
13814 struct x_display_info
*tail
;
13816 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
13817 if (tail
->next
== dpyinfo
)
13818 tail
->next
= tail
->next
->next
;
13821 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13822 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13823 XrmDestroyDatabase (dpyinfo
->xrdb
);
13826 #ifdef MULTI_KBOARD
13827 if (--dpyinfo
->kboard
->reference_count
== 0)
13828 delete_kboard (dpyinfo
->kboard
);
13832 xim_close_dpy (dpyinfo
);
13835 xfree (dpyinfo
->font_table
);
13836 xfree (dpyinfo
->x_id_name
);
13837 xfree (dpyinfo
->color_cells
);
13842 /* Set up use of X before we make the first connection. */
13844 static struct redisplay_interface x_redisplay_interface
=
13849 x_clear_end_of_line
,
13851 x_after_update_window_line
,
13852 x_update_window_begin
,
13853 x_update_window_end
,
13856 x_clear_mouse_face
,
13857 x_get_glyph_overhangs
,
13858 x_fix_overlapping_area
13864 rif
= &x_redisplay_interface
;
13866 clear_frame_hook
= x_clear_frame
;
13867 ins_del_lines_hook
= x_ins_del_lines
;
13868 change_line_highlight_hook
= x_change_line_highlight
;
13869 delete_glyphs_hook
= x_delete_glyphs
;
13870 ring_bell_hook
= XTring_bell
;
13871 reset_terminal_modes_hook
= XTreset_terminal_modes
;
13872 set_terminal_modes_hook
= XTset_terminal_modes
;
13873 update_begin_hook
= x_update_begin
;
13874 update_end_hook
= x_update_end
;
13875 set_terminal_window_hook
= XTset_terminal_window
;
13876 read_socket_hook
= XTread_socket
;
13877 frame_up_to_date_hook
= XTframe_up_to_date
;
13878 reassert_line_highlight_hook
= XTreassert_line_highlight
;
13879 mouse_position_hook
= XTmouse_position
;
13880 frame_rehighlight_hook
= XTframe_rehighlight
;
13881 frame_raise_lower_hook
= XTframe_raise_lower
;
13882 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13883 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13884 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13885 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13886 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13888 scroll_region_ok
= 1; /* we'll scroll partial frames */
13889 char_ins_del_ok
= 0; /* just as fast to write the line */
13890 line_ins_del_ok
= 1; /* we'll just blt 'em */
13891 fast_clear_end_of_line
= 1; /* X does this well */
13892 memory_below_frame
= 0; /* we don't remember what scrolls
13897 last_tool_bar_item
= -1;
13898 any_help_event_p
= 0;
13900 /* Try to use interrupt input; if we can't, then start polling. */
13901 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13903 #ifdef USE_X_TOOLKIT
13904 XtToolkitInitialize ();
13905 Xt_app_con
= XtCreateApplicationContext ();
13906 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13908 /* Install an asynchronous timer that processes Xt timeout events
13909 every 0.1s. This is necessary because some widget sets use
13910 timeouts internally, for example the LessTif menu bar, or the
13911 Xaw3d scroll bar. When Xt timouts aren't processed, these
13912 widgets don't behave normally. */
13914 EMACS_TIME interval
;
13915 EMACS_SET_SECS_USECS (interval
, 0, 100000);
13916 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
13920 #if USE_TOOLKIT_SCROLL_BARS
13921 xaw3d_arrow_scroll
= False
;
13922 xaw3d_pick_top
= True
;
13925 /* Note that there is no real way portable across R3/R4 to get the
13926 original error handler. */
13927 XSetErrorHandler (x_error_handler
);
13928 XSetIOErrorHandler (x_io_error_quitter
);
13930 /* Disable Window Change signals; they are handled by X events. */
13932 signal (SIGWINCH
, SIG_DFL
);
13933 #endif /* ! defined (SIGWINCH) */
13935 signal (SIGPIPE
, x_connection_signal
);
13942 staticpro (&x_error_message_string
);
13943 x_error_message_string
= Qnil
;
13945 staticpro (&x_display_name_list
);
13946 x_display_name_list
= Qnil
;
13948 staticpro (&last_mouse_scroll_bar
);
13949 last_mouse_scroll_bar
= Qnil
;
13951 staticpro (&Qvendor_specific_keysyms
);
13952 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13954 staticpro (&last_mouse_press_frame
);
13955 last_mouse_press_frame
= Qnil
;
13958 staticpro (&help_echo
);
13959 help_echo_object
= Qnil
;
13960 staticpro (&help_echo_object
);
13961 help_echo_window
= Qnil
;
13962 staticpro (&help_echo_window
);
13963 previous_help_echo
= Qnil
;
13964 staticpro (&previous_help_echo
);
13965 help_echo_pos
= -1;
13967 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13968 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13969 For example, if a block cursor is over a tab, it will be drawn as\n\
13970 wide as that tab on the display.");
13971 x_stretch_cursor_p
= 0;
13973 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
13974 "If not nil, Emacs uses toolkit scroll bars.");
13975 #if USE_TOOLKIT_SCROLL_BARS
13976 x_toolkit_scroll_bars_p
= 1;
13978 x_toolkit_scroll_bars_p
= 0;
13981 staticpro (&last_mouse_motion_frame
);
13982 last_mouse_motion_frame
= Qnil
;
13985 #endif /* not HAVE_X_WINDOWS */